DEV Community

Addie B
Addie B

Posted on

A11y media queries via Svelte stores

Svelte's readable stores provide a useful way to track the state of a media query in JS throughout your application, and update settings automatically when it changes.

Here's an example: we'll create a readable store called prefersReducedMotion whose value is tied to the state of the prefers-reduced-motion media query.

In store.js:

import { readable } from "svelte/store";

export const prefersReducedMotion = readable(true, set => {
  // No behavior unless we're in a browser.
  let stop = () => {};

  if (typeof window != "undefined") {
    let mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
    // Define a function that sets the store to match the media query
    const setMatches = () => set(mediaQuery.matches);
    // Call it once now
    // Call it on changes
    mediaQuery.addEventListener("change", setMatches);
    // Set the stop function which will be returned
    stop = () => mediaQuery.removeEventListener("change", setMatches);
  return stop;
Enter fullscreen mode Exit fullscreen mode

Now, in our Svelte components, we can import the store and reference it in markup using the reactive store syntax ($storeName), and our markup will update immediately when the setting changes.

In any .svelte file:

  import { prefersReducedMotion } from "/path/to/store"

{#if $prefersReducedMotion}
  <p>Reduce motion and animations please!</p>
  <p>No need to reduce motion for me.</p>
Enter fullscreen mode Exit fullscreen mode

An example REPL can be found here.

Top comments (1)

fedorovvvv profile image
Nikita Fedorov

There is a very convenient and easy package for this 🙂

svelte-media-queries - npm

A light and magical Svelte component for CSS media queries🐹. Latest version: 1.2.2, last published: a day ago. Start using svelte-media-queries in your project by running `npm i svelte-media-queries`. There are no other projects in the npm registry using svelte-media-queries.