DEV Community

Nicolas Hoizey
Nicolas Hoizey

Posted on • Originally published at nicolas-hoizey.com on

Running CSS animations only if both the device and the user allow it

Thanks to Chrome release notes, I discovered today that there is an update media feature which accepts values fast, slow and print, to set styles depending on the ability of the device to update the rendering and the speed of it.

As I'm already respecting the user's preference with the prefers-reduced-motion media feature, I wondered how I could progressively enhance this with the new media feature.

"Testing" media feature support without @supports

Amelia Bellamy-Royds had the answer with a clever trick. Thanks Amelia! 🙏

This is how you can apply styles only if a feature is supported by the browser:

@media (thing: one), not (thing: one) {
  …
}
Enter fullscreen mode Exit fullscreen mode

Indeed:

  • either the browser doesn't understand thing: one and ignores both media queries
  • or the browser understands thing: one and this is either true or false, so combining both matches all supporting browsers/contexts

Running CSS animations only if both the device (either update: fast not supported or true) and the user allow it (prefers-reduced-motion: no-preference)

Combining this trick with my already existing media queries for the prefers-reduced-motion media feature requires a bit of code, but it's manageable.

Here's the code I got for the Ken Burns animations running on my photography site (with non relevant selectors cleaned up):

// Without @​media update support
// Enable animations if no reduced motion preference
@media (prefers-reduced-motion: no-preference) {
  img {
    animation-play-state: running;
  }
}

// With @​media update support
@media (update: fast), not (update: fast) {
  // If screen update is fast (neither slow nor print)
  @media (update: fast) {
    // Enable animations if no reduced motion preference
    @media (prefers-reduced-motion: no-preference) {
      img {
        animation-play-state: running;
      }
    }
  }

  // If screen update is NOT fast (either slow or print)
  // Disable animations
  @media not (update: fast) {
    img {
      animation-play-state: paused;
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Being able to nest media queries is great!

Later update: a simpler solution thanks to Amelia

As Amelia noticed when I shared this (I ❤️ her comment “both awesome & awful” 😅), the code can be much simpler, without media queries inception. 😅

Here's what Amelia suggests to write, and I agree it's much better:

@media (prefers-reduced-motion: no-preference) {
  img {
    animation-play-state: running;
    /* turn animations on if user doesn't mind */
  }
}
@media not (update: fast) {
  img {
    animation-play-state: paused;
    /* except, turn them off again if the browser can't draw them effectively anyway */
  }
}
Enter fullscreen mode Exit fullscreen mode

I feel so lucky to regularly get great feedback from people with such expertise as Amelia, on many topics. Once with Twitter, I now get this with Mastodon, and it feels even better.

Now… how can I test the different permutations of update support or not, and actual value? 🤔

Top comments (0)