Timing Charts: A Blueprint For SMIL Animations

2026年8月20日1 次浏览来源:Smashing Magazine阅读原文

We know that everything on the web is a box by default, but you’ll find many animated s pretending to be circles.

But if you’ve ever met a real , you’ll know that they’ve got a lot more going for them.

Dressed in SVG, they fit into a wider range of crowds than a humble wearing HTML/CSS can. has a strict no policy.

The tag is not as static as its name suggests.

Any embedded JavaScript unfortunately won’t run if you load an SVG file with an tag, but CSS animations work perfectly fine.

Many of the SVG attributes do have CSS property counterparts, and the geometry properties have been supported across the major browsers since

2024.

Some attributes that you might want to animate, like , don’t have equivalents yet.

Besides JavaScript and CSS, there’s another way to animate SVGs: Synchronized Multimedia Integration Language (SMIL).

Despite its quirks, it’s still worth learning.

Like CSS animations, SMIL animations also work in tags and can fully animate everything in an SVG, without JavaScript.

If you’ve never heard of SMIL or need a refresher, check out Andy Clarke’s well-named article.

Then we’ll look at a way to plan an animation and make SMIL markup more manageable.

The Break Up SMIL has a problem: it gets bloated quickly.

Unlike CSS and JavaScript, where you can list multiple properties in each keyframe and easily reuse animations, each SMIL tag can only target one element and only one property of that element at a time.

A property can be animated through a list of values.

But it is still one tag, one element, one property.

The shortest way you can write a color and opacity change that will run is the following: That’s not bad, but consider that it needs to be repeated for every element included in the animation.

A SMIL animation can quickly get longer than its CSS equivalent.

To make things easier when starting a new animation, let’s plan all of the elements and properties we want to animate, and create a list of descriptive IDs for each tag.

Charting Animation Time And Space I like to plan my animations using what's called a timing chart.

A timing chart is effectively a line segment; some choose horizontal lines, others prefer vertical, which is a great analogy for animation as a whole because line segments can run parallel, overlap, and follow each other with or without a gap.

Just like animations.

For now, we’re only interested in when animations start and stop.

When drawing our charts, we’ll forget about the in-between lines and instead draw a line for each component animation, marking the beginning and end.

I like to annotate timing with a circle and a bar.

You can draw your chart using whatever, and it doesn’t have to be exactly to scale, as long as the relative timing between all the little animations that make up the whole is clear.

Besides, adding labels for the durations is an easy cheat to get around drawing to scale.

Here is a demo of how I typically set up a timing chart with more than one animation: See the Pen colorAndOpacityChange [forked] by Johan Grobler.

The important thing to note is that the timing chart lines are arranged according to how the animations are arranged in time.

One piece of the animation follows the next piece, which is followed by a subsequent piece, and so forth.

It visualizes how the animation’s parts run together and cascade over time.

S(yncbase)MIL A big part of SMIL is synchronization.

It’s even in the name, after all.

And there are multiple ways to specify when an animation should start (here’s a test case to check what your browser supports).

One of the most useful ways is with a syncbase value, which is a SMIL tag’s ID followed by either or , with an optional positive or negative offset.

Let’s piggyback off the previous animation example that includes changes in color and opacity.

If we want the opacity animation to start milliseconds before the color animation finishes, we could do arithmetic.

Alternatively, the second animation can use the syncbase value .

This way, the relative timing between the two animations becomes explicit.

Using syncbase values, the beginning of an animation is positioned in time relative to the or of some other animation.

A positive offset moves the start to the right (forwards in time), and a negative offset to the left (backwards in time).

See the Pen syncbase.end [forked] by Johan Grobler.

Something with negative offsets is that they can specify a time before the document has loaded or when a click happens.

Computers can’t predict the future (at least not yet).

The best they can do is jump the animation to where it would have been had the computer peeked into the future to preemptively start the animation.

The second animation only runs from start to finish if there is enough room, so to speak.

See the Pen syncbase.begin [forked] by Johan Grobler.

Syncbase values don’t only allow you to connect animations from to .

Elect a primary animation; the animation that first comes to mind is usually the best representation of the group.

All secondary animations can be set with .

I’ve only used the ID for emphasis.

That way, all the other animations begin relative to that starting point.

Stacking animations like this reduces maintenance if, say, we later want the whole group to start at a different time.

Let’s put the idea to work and build a loading indicator (or spinner).

Then we’re going to explore how changing the relative timing between the parts changes the effect of the whole animation: Step 1: Choose An Image Approach Browsers have wide support for the media feature and Val Head explains this in depth in another article.

We definitely want to respect this user preference as we consider moving things around.

In fact, consider it non-negotiable.

There are various approaches to adhering to a user’s setting when it comes to SMIL.

Each with its pros and cons.

Evaluating early on what’s going to work best for your use case could save you a partial rewrite down the line.

For example, we could consider using a element instead of a plain because supports multiple elements that can be used as fallbacks in a attribute for reduced motion preferences.

Or one SVG file with an inline CSS query that uses to swap between versions.

That said, it’s an approach that might cause trouble in various environments.

But browsers are continuously changing, and this might not be an issue in the future.

You might also consider a CSS instead because we can wrap that style in a media query — — that sets a static image as the fallback for reduced motion preferences.

There are even more options we can turn to!

For example, SVG’s element can also be used to swap things out for motion preferences.

Or, if we prefer everything bundled together, we can use JavaScript and the handy SMIL DOM interface to control which animations start instead of completely switching out files.

For this, I’m avoiding any motion and sticking to animations, which tend to cause less trouble.

For a non-interactive animation like this, we can load it in an tag.

When we add motion, we can go the route to show the most appropriate version of our animation.

Step 2: Draw The Graphics We’re going to do our own version of the classic three-dot spinner: See the Pen StaticDots [forked] by Johan Grobler.

SVG wizards might be able to do everything directly in a text editor.

I recommend using a graphic editor like Inkscape if you’re having trouble visualizing how the markup will be rendered.

Once again, Andy Clarke has a great article about his process for optimizing and structuring his own drawings.

Note: There’s a gotcha with Inkscape.

Setting what you would expect to be an element’s ID via the Layers window actually sets the value of a metadata attribute used internally by Inkscape.

Use Inkscape’s object properties or XML editor window to set the true element’s ID.

Your mileage may vary with a different editor.

Also, in Inkscape, remember to save the file as optimized SVG when the drawing is done to strip away unneeded metadata.

Step 3: Outline Th

分享
Baike.dev

baike.dev helps you discover great languages, frameworks, databases, DevOps and cloud-native tools.

Quick links

About

Contribute

Found a great developer tool? Share it with the community.

Submit a tool
© 2026 baike.dev Developer EncyclopediaUpdated daily · Discover great developer tools