JavaScript

Intersection Observer

What do infinite scrolling, lazy loading, and online advertisements all have in common?

They need to know about—and react to—the visibility of elements on a page!

Unfortunately, knowing whether or not an element is visible has traditionally been difficult on the Web. Most solutions listen for scroll and resize events, then use DOM APIs like getBoundingClientRect() to manually calculate where elements are relative to the viewport. This usually works, but it’s inefficient and doesn’t take into account other ways in which an element’s visibility can change, such as a large image finally loading higher up on the page, which pushes everything else downward.

Things get worse for advertisements, since real money is involved. As Malte Ubl explained in his presentation at JSConf Iceland, advertisers don’t want to pay for ads that never get displayed. To make sure they know when ads are visible, they cover them in dozens of tiny, single-pixel Flash movies whose visibility can be inferred from their framerate. On platforms without Flash, like smartphones, advertisers set up timers to force browsers to recalculate the position of each ad every few milliseconds.

These techniques kill performance, drain batteries, and would be completely unnecessary if the browser could just notify us whenever an element’s visibility changed.

That’s what IntersectionObserver does.

Tags: 

Flash is in the pan

Now browsers have audio. They have video. They even have WebGL and VR. And all those technologies work on mobile. The writing’s been on the wall for Flash for a while. Yet still, I’m sad to see it go. It was a brilliant crucible of creativity. A forge for many emerging artists in the field of creative coding, and many of the concepts from Flash and ActionScript were the proving grounds for their modern browser equivalents.

I’ll be looking back fondly on those years, rather than spitting on Flash’s grave. And as we see the last of the great browser plugins disappear* I hope you’ll join me in celebrating the creative culture that it nurtured.

*RealPlayer 4eva!

Tags: 

Introducing sphinx-js, a better way to document large JavaScript projects

Until now, there has been no good tool for documenting large JavaScript projects. JSDoc, long the sole contender, has some nice properties:

  • A well-defined set of tags for describing common structures
  • Tooling like the Closure Compiler which hooks into those tags

But the output is always a mere alphabetical list of everything in your project. JSDoc scrambles up and flattens out your functions, leaving new users to infer their relationships and mentally sort them into comprehensible groups. While you can get away with this for tiny libraries, it fails badly for large ones like Fathom, which has complex new concepts to explain. What I wanted for Fathom’s manual was the ability to organize it logically, intersperse explanatory prose with extracted docs, and add entire sections which are nothing but conceptual overview and yet link into the rest of the work.

The Python world has long favored Sphinx, a mature documentation tool with support for many languages and output formats, along with top-notch indexing, glossary generation, search, and cross-referencing. People have written entire books in it. Via plugins, it supports everything from Graphviz diagrams to YouTube videos. However, its JavaScript support has always lacked the ability to extract docs from code.

Now sphinx-js adds that ability, giving JavaScript developers the best of both worlds.

Tags: 

{{ mustache }} - Logic-less templates

Mustache can be used for HTML, config files, source code - anything. It works by expanding tags in a template using values provided in a hash or object.

We call it "logic-less" because there are no if statements, else clauses, or for loops. Instead there are only tags. Some tags are replaced with a value, some nothing, and others a series of values.

Tags: 

Building performant expand & collapse animations

Use scale transforms when animating clips. You can prevent the children from being stretched and skewed during the animation by counter-scaling them.

[...]

In this post we’re going to look over what’s involved if you want performant clip animations. If you want to see a demo, check out the Sample UI Elements GitHub repo.

Tags: 

Scrolling on the web: A primer

This is a fascinating and thorough dive into scrolling, and should be required reading for anyone writing JavaScript today:

Today, scrolling is still the most fundamental interaction on the web, and perhaps the most misunderstood. For instance, do you know the difference between the following scenarios?

  • User scrolls with two fingers on a touch pad
  • User scrolls with one finger on a touch screen
  • User scrolls with a mouse wheel on a physical mouse
  • User clicks the sidebar and drags it up and down
  • User presses up, down, PageUp, PageDown, or spacebar keys on a keyboard

If you ask the average web user (or even the average web developer!) they might tell you that these interactions are all equivalent. The truth is far more interesting.

Tags: 

Using CSS Transitions on Auto Dimensions

We've all been there. You've got an element you want to be able to collapse and expand smoothly using CSS transitions, but its expanded size needs to be content-dependent. You've set transition: height 0.2s ease-out. You've created a collapsed CSS class that applies height: 0. You try it out, and... the height doesn't transition. It snaps between the two sizes as if transition had never been set. After some fiddling, you figure out that this problem only happens when the height starts out or ends up as auto. Percentages, pixel values, any absolute units work as expected. But all of those require hard coding a specific height beforehand, rather than allowing it to naturally result from the size of the element content.

[...]

If you were hoping I had a magical, complete solution to this problem, I'm sorry to disappoint you. There's no one solution that achieves the desired effect without downsides. There are, however, multiple workarounds that each come with a different set of advantages and disadvantages, and in most use cases at least one of them will get the job done in an acceptable manner. I'll outline the major ones, and list out their ups and downs so you can hopefully pick the best one for your situation.

[...]

Technique 1: max-height

If you web search this problem, the max-height approach will probably be mentioned in all of the first five to ten results. It's actually pretty unideal, but I thought it was worth including here for the sake of comparison.

It works like this: CSS values can only be transitioned to and from fixed unit values. But imagine we have an element whose height is set to auto, but whose max-height is set to a fixed value; say, 1000px. We can't transition height, but we can transition max-height, since it has an explicit value. At any given moment, the actual height of the element will be the maximum of the height and the max-height. So as long as max-height's value is greater than what auto comes out to, we can just transition max-height and achieve a version of the desired effect.

[...]

Technique 2: transform: scaleY()

[...]

Implementation works like this: we set a transition for the element's transform property, then toggle between transform: scaleY(1) and transform: scaleY(0). These mean, respectively, "render this element at the same scale (on the y axis) that it starts out at" and "render this element at a scale of 0 (on the y axis)". Transitioning between these two states will neatly "squish" the element to and from its natural, content-based size.

Technique 3: JavaScript

Managing a CSS transition in CSS would be ideal, but as we're learning, sometimes it just isn't entirely possible.

If you absolutely have to have smoothly collapsing sections, whose expanded size is completely driven by their content, and which other elements on the page will flow around as they transition, you can achieve that with some JavaScript.

The basic strategy is to manually do what the browser refuses to: calculate the full size of the element's contents, then CSS transition the element to that explicit pixel size.

Tags: 

Pages