You should always respect the choices your users make. There are a few media queries you can use to easily make your site or app experience more in line with what your users want.
Color Scheme
One of the best ways to give your users true value on the media queries front is having both a dark and light color scheme, and respecting the user’s device’s/browser’s setting in that regard.
The two possible options for prefers-color-scheme
are light
(which is the default), and dark
. This can easily be combined with CSS custom properties (variables) to implement color schemes for your app:
:root {
--button-bg-color: white;
--button-text-color: black;
}
@media (prefers-color-scheme: dark) {
:root {
--button-bg-color: black;
--button-text-color: white;
}
}
.c-button {
background-color: var(--button-bg-color);
color: var(--button-text-color);
}
This example will switch the color based on the user’s preference, if their browser supports the feature, all without having to provide two sets of CSS definition for every component.
Higher/Lower Contrast
Just like with the color scheme example above, you can use media queries to match your user’s preference regarding contrast. prefer-contrast
can have the values no-preference
(default), more
, less
or custom
.
The important one here is more
, which has accessibility implications: A user demanding higher contrast might have a harder time reading text on screen, and you can help them by increasing the contrast between text and background, or even increasing the font size or weight.
Setting less
is, well, less common, and it has less accessibility implications if simply ignored.
Reduce Motion
prefers-reduced-motion lets you know a user desires to not see (moving) animations. Querying against it is as easy as checking @media (prefers-reduced-motion: reduce)
. Browsers that do not yet support this feature will simply ignore the assignment:
.c-modal {
transform: translateY(-100%);
transition: transform 0.4s ease;
}
.c-modal.-open {
transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
.c-modal {
transition: none;
}
}
This (simplified) example has a modal sliding in from the top, but if the user set the option to reduce motion on screen, it will skip the movement and simply pop into existence. You could also use the media query to change the animation to something non-moving, for example transitioning the opacity instead.
Remember: This option is about reducing motion, not reducing transitions.
The opposite media query would be @media (prefers-reduced-motion: no-preference)
to indicate that the user did not request less animations. As with the above example, browsers without support would simply skip the whole block though.
Javascript
You can query any of those settings in Javascript, too. window.matchMedia
offers the possibility to check against CSS media queries, and call a method whenever changes are made - for example when the user’s phone activates night mode.
let mediaQueryList = window.matchMedia('(prefers-color-scheme: dark)')
// can take a MediaQueryList or MediaQueryListEvent
function handleColorScheme(mql) {
if (mql.matches) {
// dark color scheme
} else {
// light color scheme
}
}
// handle immediately
handleColorScheme(mediaQueryList)
// handle future changes
mediaQueryList.addEventListener('change', handleColorScheme)