Update (28/7/2017): Doesn’t work in Firefox as it cascades differently and this won’t work in browsers than don’t support Web Animations. Some clever attempts to break include background: linear-gradient(blue, blue) (that technically sets a generated image, not a color, but fixed it anyway in the Pen by animating background instead) and filter: hue-rotate(90deg) (I wouldn’t say this counts, as it doesn’t just change the background-color).


Ana just wrote about some clever ways of preventing access to a page from DevTools, and coincidentally, during a debugging session with Dima and Ali from the AMP team, we stumbled upon something…interesting.

What if I told you that there was an a way to set CSS properties that become more important than !important? Better even, so important that whatever you do, you’ll never be able to override them in CSS?

Behold! The try-it-yourself Pandora’s box demo:

Yes, you cannot change the background-color. No, not even by overriding it with !important, or setting an inline style. But why?

Meet Web Animation’s fill property

The Web Animation spec has a little-known property on the AnimationEffectTiming interface (that you use to control an animation, e.g. by setting a duration) called fill. The equivalent exists in the world of CSS as animation-fill-mode.

For both JS and CSS animations, setting the fill property to either forwards or both keeps the element in the final state of the animation. Without setting it, the animated CSS properties would be reset to the origin state, before the animation.

When used in CSS, the way it works is straight forward. As long as the animation-fill-mode property stays on a selector targeting the element, the element stays on the last keyframe. If you remove it, you remove the fill behavior.

But when using Web Animation’s animate API, like so:

locked.animate([
  { backgroundColor: 'hotpink' },
  { backgroundColor: 'hotpink' }
], {
  duration: 0,
  fill: 'both'
});

..whatever styles where applied in the last keyframe become immutable. After running this seemingly harmless code, the background-color can not be changed. Not via stylesheets, !important, not even by setting an inline style via JS.

Really? Locked forever?

My twisted brain immediately thought about use-cases for this – think 3p embeds that don’t require iframes, yet cannot be tampered with. But there’s one way out: Run another animation with fill applied (OMG).

This is madness!

Yes. Yes, indeed. Though spec authors will most likely say “nothing to see here, works as expected” :) In any case, use the fill property sparingly and maybe don’t abuse it for stupid things. Thanks!