A round-up of all the ways that media features let you respond to devices and preferences.
Responsive design wouldn't be possible without media queries. Before media queries there was no way of knowing what kind of device people were using to visit your website. Designers had to make assumptions. Those assumptions were encoded into fixed-width designs or liquid layouts.
That all changed with the introduction of media queries. For the first time designers could meet people halfway. Designers could adjust their layouts to respond to people's devices.
Remember, a media query comprises an optional media type and a mandatory media feature. There hasn't been much change in media types over the years. There are still just four possible values:
@media all
@media screen
@media print
@media speech
Media features, on the other hand, have expanded greatly. Designers now can meet users beyond halfway, adapting designs to fit far more than just screen size.
Viewport dimensions
By far the most popular media queries on the web are the ones dealing with viewport width. But even here, you're presented with a choice. You can use the max-width
media feature to apply styles below a certain width, or you can use the min-width
media feature to apply styles above a certain width.
main {
display: grid;
grid-template-columns: 2fr 1fr;
}
@media (max-width: 45em) {
main {
display: block;
}
}
@media (min-width: 45em) {
main {
display: grid;
grid-template-columns: 2fr 1fr;
}
}
Personally, I like to use min-width
. I apply layout styles in an additive way. I introduce new layout rules at each breakpoint instead of undoing previous rules.
This additive approach also works for height. Using min-height
you can introduce more rules as more viewport height becomes available. For example, you might have a header element that you want to anchor to the top of the browser window if there's enough vertical space.
@media (min-height: 30em) {
header {
position: fixed;
}
}
But you can use the max-height
media feature if you prefer. Here, the header is anchored by default, but the stickiness is removed if there isn't enough vertical space.
header {
position: fixed;
}
@media (max-height: 30em) {
header {
position: static;
}
}
Choosing between min-
and max-
prefixes doesn't just apply to width
and height
. The aspect-ratio
media feature offers the same choice. It also offers an unprefixed version if you want to apply styles at an exact ratio of width to height.
@media (min-aspect-ratio: 16/9) {
// The ratio of width to height is at least 16 by 9.
}
@media (max-aspect-ratio: 16/9) {
// The ratio of width to height is less than 16 by 9.
}
@media (aspect-ratio: 16/9) {
// The ratio of width to height is exactly 16 by 9.
}
Providing different styles for different aspect ratios could quickly get out of hand. If you don't need that fine-grained level of control, the orientation
media feature might better suit your needs. It has two possible values: portrait
or landscape
.
@media (orientation: portrait) {
// The width is less than the height.
}
@media (orientation: landscape) {
// The width is greater than the height.
}
Even though the terms "portrait" and "landscape" are most often used to refer to the orientation of mobile devices, the orientation
media feature isn't device-specific. A full-screen browser window on a typical laptop will have an orientation
value of landscape
.
Displays
Different displays have different pixel densities, measured in dpi
, dots per inch. You can adjust your styles for different pixel densities using the resolution
media feature. Like aspect-ratio
, resolution
comes in three varieties: minimum, maximum, and exact.
@media (min-resolution: 300dpi) {
// The display has a pixel density of at least 300 dots per inch.
}
@media (max-resolution: 300dpi) {
// The display has a pixel density less than 300 dots per inch.
}
@media (resolution: 300dpi) {
// The display has a pixel density of exactly 300 dots per inch.
}
You may never need to use any resolution
media queries. Pixel density is usually only an issue for images, and responsive images are a way of dealing with pixel density directly in HTML.
On the other hand, CSS is where you define your animations and transitions. You can adjust those animations and transitions to respond to different refresh rates using the update
media feature. This media feature reports one of three values: none
, slow
, and fast
.
An update
value of none
means there's no refresh rate. A printed page, for example, can't be updated.
An update
value of slow
means the display can't refresh quickly. An e-ink display is one example of a screen with a slow refresh rate.
An update
value of fast
means the display refreshes fast enough to handle animations and transitions.
@media (update: fast) {
a {
transition-duration: 0.4s;
transition-property: transform;
}
a:hover {
transform: scale(150%);
}
}
Not all aspects of the display are related to hardware capabilities. In the module on theming, you saw how to define properties in a web app manifest file. One of those properties is called display
, and you can give it a value of fullscreen
, standalone
, minimum-ui
, or browser
. The corresponding display-mode
media feature allows you to tailor your styles for these different options.
Let's say you've provided a display
value of standalone
in your web app manifest. If someone adds your site to their home screen, the site will launch without any browser interface. You might decide to display a back button for those users.
button.back {
display: none;
}
@media (display-mode: standalone) {
button.back {
display: inline;
}
}
Color
There are numerous media features for querying the color capabilities of a device. If you want to adjust your styles for any display that only outputs shades of grey, you can use the monochrome
media feature without any value.
@media (monochrome) {
body {
color: black;
background-color: white;
}
}
There's a corresponding color
media feature.
@media (color) {
body {
color: maroon;
background-color: linen;
}
}
For color screens, you can write queries with the media features color-gamut
, color-index
, or dynamic-range
. All of them report specific details about the color capabilities of the screen.
In this example, color values update in response to the dynamic-range
media feature, which reports the combination of maximum brightness, color depth, and contrast ratio of the display. The possible values are standard
or high
. A high-definition screen that reports a dynamic-range
value of high
is given a different color space using the new CSS color()
function.
.neon-red {
color: hsl(355 100% 95%);
}
@media (dynamic-range: high) {
.neon-red {
color: color(display-p3 1 0 0);
}
}
Interaction
Media features can also report the kind of input mechanism used to interact with your site: hover
, any-hover
, pointer
, and any-pointer
. See the module on interaction for more details.
Preferences
There are a range of media queries that allow you to respond to user preferences: prefers-color-scheme
, prefers-contrast
, and prefers-reduced-motion
. See the modules on theming and accessibility for more details.
You can combine media features in one media query. You could scope your animation styles so that they're only applied if the device has a fast refresh rate and the user hasn't expressed a preference for reduced motion.
@media (update: fast) and (prefers-reduced-motion: no-preference) {
a {
transition-duration: 0.4s;
transition-property: transform;
}
a:hover {
transform: scale(150%);
}
}
More media features
There are more media features on the way.
The forced-colors
and inverted-colors
media features will report whether a device is using a restricted or an inverted color palette.
A scripting
media feature will allow you to adjust your CSS based on the availability of JavaScript.
A media feature called prefers-reduced-data
will allow users to specify that they're on a metered connection so you can send smaller or fewer assets.
Other proposals are still being formulated. In the next and final module, you'll learn about a proposal for a media feature that handles different screen configurations.
Check your understanding
Test your knowledge of media features
A media query can check for a device at a specific width like @media (width: 1024px)
?
A media query can check for a device at a specific aspect-ratio
like @media (aspect-ratio: 4/3)
?
Which are valid color media queries?
@media (min-color-index: 15000)
@media (monochrome)
@media (color-gamut: srgb)
@media (color)
@media (dynamic-range: high)
Which of the following user preference media queries are valid?
@media (prefers-reduced-motion: reduce)
@media (prefers-contrast: more)
@media (prefers-color-scheme: dark)
@media (prefers-colors: high-definition)
@media (prefers-site-speed: fast)