Conditional rules
At-rules that apply their contents only when a condition holds: the features of the device or viewport, whether the browser supports a feature, or the size and state of an ancestor container. Below the three rules are the media features and container features they can test. Layers and scoping are under Cascade & scope; everything else is under Other rules.
Conditional group rules
@media
Applies the rules inside it when a media query matches. A query is an optional media type (all, screen or print) and any number of feature tests joined with and, or and not. A comma-separated list matches when any one query in it matches.
| Syntax | @media <media-query-list> { <rule-list> } |
|---|---|
| Support | Chrome 1 · Firefox 1 · Safari 3 |
| Spec | css-conditional-3 |
| Feature | Support |
|---|---|
Range syntax, e.g. (48rem <= width < 90rem) | Chrome 104 · Firefox 102 · Safari 16.4 |
or between feature tests | Chrome 104 · Firefox 64 · Safari 16.4 |
calc() in feature values | Chrome 66 · Firefox 59 · Safari 12 |
@media (width >= 48rem) and (prefers-color-scheme: dark) {
body { background: #111; }
}
Before range syntax, range features were tested with min- and max- prefixes: (min-width: 48rem) is the same as (width >= 48rem). Both forms still work.
@supports
A feature query: applies the rules inside it only if the browser understands a declaration, selector or other feature. Tests combine with and, or and not, and a browser that does not recognise a test treats it as false.
| Syntax | @supports <supports-condition> { <rule-list> } |
|---|---|
| Support | Chrome 28 · Firefox 22 · Safari 9 |
| Spec | css-conditional-3 |
| Test | True when the browser supports | Support |
|---|---|---|
(property: value) | That declaration | Chrome 28 · Firefox 22 · Safari 9 |
selector(<complex-selector>) | That selector | Chrome 83 · Firefox 69 · Safari 14.1 |
font-tech(<font-tech>) | A font technology, such as color-COLRv1 or variations | Chrome 108 · Firefox 106 · Safari 17 |
font-format(<font-format>) | A font format, such as woff2 | Chrome 108 · Firefox 106 · Safari 17 |
at-rule(<at-keyword-token>) | An at-rule, such as at-rule(@starting-style) | Chrome 148 · Firefox 157 · Safari no |
named-feature(<ident>) | A browser behaviour that has no syntax of its own to test, named by an identifier | Chrome 150 · Firefox no · Safari no |
@supports (display: grid) {
.layout { display: grid; }
}
@supports selector(:has(*)) {
/* :has() is available */
}
selector().Pair it with not to write a fallback: @supports not (aspect-ratio: 1).
@container
A container query: styles an element by the size or state of its nearest query container rather than the viewport. Mark an ancestor as a container with container-type, and optionally name it with container-name so a query can target it.
| Syntax | @container <container-condition># { <rule-list> } |
|---|---|
| Support | Chrome 105 · Firefox 110 · Safari 16 |
| Spec | css-conditional-5 |
| Feature | Support |
|---|---|
| Size queries | Chrome 105 · Firefox 110 · Safari 16 |
style() queries on custom properties | Chrome 111 · Firefox 151 · Safari 18 |
Range syntax inside style() | Chrome 142 · Firefox 151 · Safari no |
scroll-state() queries | Chrome 133 · Firefox no · Safari no |
anchored() queries | Chrome 143 · Firefox no · Safari no |
A container name with no query, e.g. @container card { … } | Chrome 148 · Firefox 149 · Safari 26.4 |
/* mark the container */
.card { container-type: inline-size; container-name: card; }
/* query it */
@container card (width >= 30rem) {
.card h3 { font-size: 1.5rem; }
}
An element is never its own query container, so the rules inside a query style the container's descendants. Container query length units resolve against the query container: cqw, cqh, cqi (inline), cqb (block), cqmin and cqmax.
Media features
The tests used inside @media (and in the media attribute and matchMedia()). A range feature compares a value, so it accepts range syntax such as (width >= 40rem) and the min- and max- prefixes. A discrete feature matches one of a set of keywords. Any feature written on its own, such as (hover), is true unless its value would be 0, none or no-preference.
any-hover
Whether any of the available input devices can hover over elements. Use hover to ask about the primary input only.
| Type | Discrete |
|---|---|
| Values | none | hover |
| Support | Chrome 41 · Firefox 64 · Safari 9 |
| Spec | mediaqueries-5 |
any-pointer
Whether any of the available input devices is a pointer, and how accurate it is. With a mouse and a touchscreen both present, (any-pointer: fine) and (any-pointer: coarse) both match.
| Type | Discrete |
|---|---|
| Values | none | coarse | fine |
| Support | Chrome 41 · Firefox 64 · Safari 9 |
| Spec | mediaqueries-5 |
aspect-ratio
The width-to-height ratio of the viewport, written as a ratio such as 16 / 9.
| Type | Range |
|---|---|
| Values | <ratio> |
| Support | Chrome 3 · Firefox 3.5 · Safari 5 |
| Spec | mediaqueries-5 |
color
The number of bits per colour component of the output device, or 0 if it cannot show colour. (color) on its own matches any colour device.
| Type | Range |
|---|---|
| Values | <integer> |
| Support | Chrome 1 · Firefox 2 · Safari 3 |
| Spec | mediaqueries-5 |
color-gamut
The approximate range of colours the browser and output device can show. Each value matches when the display covers at least that gamut, so a P3 display matches both srgb and p3.
| Type | Discrete |
|---|---|
| Values | srgb | p3 | rec2020 |
| Support | Chrome 58 · Firefox 110 · Safari 10 |
| Spec | mediaqueries-5 |
color-index
The number of entries in the output device's colour lookup table, or 0 if it does not use one.
| Type | Range |
|---|---|
| Values | <integer> |
| Support | Chrome 29 · Firefox no · Safari 8 |
| Spec | mediaqueries-5 |
device-aspect-ratio Deprecated
The width-to-height ratio of the whole output device rather than the viewport. Use aspect-ratio instead.
| Type | Range |
|---|---|
| Values | <ratio> |
| Support | Chrome 1 · Firefox 2 · Safari 3 |
| Spec | mediaqueries-5 |
device-height Deprecated
The height of the output device's whole rendering surface rather than the viewport. Use height instead.
| Type | Range |
|---|---|
| Values | <length> |
| Support | Chrome 1 · Firefox 2 · Safari 3 |
| Spec | mediaqueries-5 |
device-posture
The posture of a foldable device: continuous when it is flat or not foldable, folded when it is bent like a book or a laptop.
| Type | Discrete |
|---|---|
| Values | continuous | folded |
| Support | Chrome 132 · Firefox no · Safari no |
| Spec | device-posture |
device-width Deprecated
The width of the output device's whole rendering surface rather than the viewport. Use width instead.
| Type | Range |
|---|---|
| Values | <length> |
| Support | Chrome 1 · Firefox 2 · Safari 3 |
| Spec | mediaqueries-5 |
display-mode
How an installed web app is being shown, such as in a normal browser tab, in its own window (standalone) or full screen. Most of the values correspond to the display member of the web app manifest.
| Type | Discrete |
|---|---|
| Values | application | fullscreen | standalone | minimal-ui | browser | picture-in-picture |
| Support | Chrome 42 · Firefox 47 · Safari 13 |
| Spec | mediaqueries-5 |
dynamic-range
Whether the browser and output device can show high dynamic range: high peak brightness, contrast and colour depth.
| Type | Discrete |
|---|---|
| Values | standard | high |
| Support | Chrome 98 · Firefox 100 · Safari 13.1 |
| Spec | mediaqueries-5 |
forced-colors
Whether the browser is replacing page colours with a limited palette chosen by the user, as in Windows contrast themes. Use it to repair details that forced colours remove, not to undo the user's choice.
| Type | Discrete |
|---|---|
| Values | none | active |
| Support | Chrome 89 · Firefox 89 · Safari 16 |
| Spec | mediaqueries-5 |
grid
Whether the output device is grid-based, such as a text terminal, rather than bitmap-based. <mq-boolean> is the integer 0 or 1.
| Type | Discrete |
|---|---|
| Values | <mq-boolean> |
| Support | Chrome 1 · Firefox 2 · Safari 3 |
| Spec | mediaqueries-5 |
height
The height of the viewport, or of the page box when printing.
| Type | Range |
|---|---|
| Values | <length> |
| Support | Chrome 1 · Firefox 2 · Safari 3 |
| Spec | mediaqueries-5 |
horizontal-viewport-segments
The number of side-by-side segments the viewport is split into, as on a dual-screen or folding device. An ordinary screen has one.
| Type | Range |
|---|---|
| Values | <integer> |
| Support | Chrome 138 · Firefox no · Safari no |
| Spec | mediaqueries-5 |
hover
Whether the primary input device can hover over elements. A mouse can; a touchscreen usually cannot.
| Type | Discrete |
|---|---|
| Values | none | hover |
| Support | Chrome 38 · Firefox 64 · Safari 9 |
| Spec | mediaqueries-5 |
@media (hover: hover) {
.card:hover { translate: 0 -2px; }
}
inverted-colors
Whether the operating system is inverting all colours on screen, so that images and video can be inverted back.
| Type | Discrete |
|---|---|
| Values | none | inverted |
| Support | Chrome no · Firefox no · Safari 9.1 |
| Spec | mediaqueries-5 |
monochrome
The number of bits per pixel on a monochrome (greyscale) device, or 0 if the device is not monochrome.
| Type | Range |
|---|---|
| Values | <integer> |
| Support | Chrome 1 · Firefox 2 · Safari 3 |
| Spec | mediaqueries-5 |
orientation
portrait when the viewport is at least as tall as it is wide, otherwise landscape.
| Type | Discrete |
|---|---|
| Values | portrait | landscape |
| Support | Chrome 3 · Firefox 2 · Safari 5 |
| Spec | mediaqueries-5 |
overflow-block
How the device handles content that overflows the viewport in the block axis: not at all, by scrolling, or by breaking it into pages as in print.
| Type | Discrete |
|---|---|
| Values | none | scroll | paged |
| Support | Chrome 113 · Firefox 66 · Safari 17 |
| Spec | mediaqueries-5 |
overflow-inline
Whether content that overflows the viewport in the inline axis can be scrolled into view.
| Type | Discrete |
|---|---|
| Values | none | scroll |
| Support | Chrome 113 · Firefox 66 · Safari 17 |
| Spec | mediaqueries-5 |
pointer
Whether the primary input device is a pointer and how accurate it is: fine for a mouse or stylus, coarse for a finger on a touchscreen. Use it to give coarse pointers larger targets.
| Type | Discrete |
|---|---|
| Values | none | coarse | fine |
| Support | Chrome 41 · Firefox 64 · Safari 9 |
| Spec | mediaqueries-5 |
prefers-color-scheme
Whether the user has asked for a light or a dark colour scheme in their system or browser settings.
| Type | Discrete |
|---|---|
| Values | light | dark |
| Support | Chrome 76 · Firefox 67 · Safari 12.1 |
| Spec | mediaqueries-5 |
@media (prefers-color-scheme: dark) {
:root { --surface: #111; --text: #eee; }
}
prefers-contrast
Whether the user has asked for more or less contrast between colours. custom matches when forced colours are active with a palette that is neither high nor low contrast.
| Type | Discrete |
|---|---|
| Values | no-preference | less | more | custom |
| Support | Chrome 96 · Firefox 101 · Safari 14.1 |
| Spec | mediaqueries-5 |
prefers-reduced-motion
Whether the user has asked the system to minimise non-essential motion. When it is reduce, tone down or remove large movements, parallax and autoplaying animation.
| Type | Discrete |
|---|---|
| Values | no-preference | reduce |
| Support | Chrome 74 · Firefox 63 · Safari 10.1 |
| Spec | mediaqueries-5 |
@media (prefers-reduced-motion: no-preference) {
.hero { animation: slide-in 0.6s ease-out; }
}
prefers-reduced-transparency
Whether the user has asked the system to reduce transparent and translucent layers, such as frosted-glass panels.
| Type | Discrete |
|---|---|
| Values | no-preference | reduce |
| Support | Chrome 118 · Firefox no · Safari no |
| Spec | mediaqueries-5 |
resolution
The pixel density of the output device, such as 2dppx or 192dpi. infinite matches devices with no physical pixel limit, such as vector displays.
| Type | Range |
|---|---|
| Values | <resolution> | infinite |
| Support | Chrome 29 · Firefox 8 · Safari 16 |
| Spec | mediaqueries-5 |
scan
Whether the display draws its image interlaced or progressively. Almost every screen in use today is progressive.
| Type | Discrete |
|---|---|
| Values | interlace | progressive |
| Support | Chrome 104 · Firefox 63 · Safari 16.4 |
| Spec | mediaqueries-5 |
scripting
Whether scripting such as JavaScript is available: enabled, none, or initial-only when scripts run only while the page loads, as in printed output.
| Type | Discrete |
|---|---|
| Values | none | initial-only | enabled |
| Support | Chrome 120 · Firefox 113 · Safari 17 |
| Spec | mediaqueries-5 |
update
How quickly the device can change what it shows: none for paper, slow for screens such as e-ink, fast for ordinary screens.
| Type | Discrete |
|---|---|
| Values | none | slow | fast |
| Support | Chrome 113 · Firefox 102 · Safari 17 |
| Spec | mediaqueries-5 |
vertical-viewport-segments
The number of stacked segments the viewport is split into, top to bottom, as on a folding device held with the fold horizontal. An ordinary screen has one.
| Type | Range |
|---|---|
| Values | <integer> |
| Support | Chrome 138 · Firefox no · Safari no |
| Spec | mediaqueries-5 |
video-dynamic-range
Like dynamic-range, but for the plane that video is drawn on, which on some devices supports high dynamic range when the rest of the page does not.
| Type | Discrete |
|---|---|
| Values | standard | high |
| Support | Chrome no · Firefox 100 · Safari no |
| Spec | mediaqueries-5 |
width
The width of the viewport including any scrollbar, or of the page box when printing. The most common media feature for responsive layout.
| Type | Range |
|---|---|
| Values | <length> |
| Support | Chrome 1 · Firefox 2 · Safari 3 |
| Spec | mediaqueries-5 |
em and rem in a media query are relative to the browser's initial font size, not to any font size set in the page.
Container features
The tests used inside @container. Size features are written in parentheses like media features and need an ancestor with a container-type of size or inline-size. State tests are wrapped in a function: style(), scroll-state() or anchored().
width, height, inline-size, block-size
The size of the query container's content box in one axis. A container with container-type: inline-size answers only queries in its inline axis (inline-size, and width in horizontal writing modes); queries in the block axis need container-type: size.
| Type | Range |
|---|---|
| Values | <length> |
| Support | Chrome 105 · Firefox 110 · Safari 16 |
| Spec | css-conditional-5 |
aspect-ratio
The width-to-height ratio of the query container's content box. It needs a container with container-type: size.
| Type | Range |
|---|---|
| Values | <ratio> |
| Support | Chrome 105 · Firefox 110 · Safari 16 |
| Spec | css-conditional-5 |
orientation
portrait when the query container is at least as tall as it is wide, otherwise landscape. It needs a container with container-type: size.
| Type | Discrete |
|---|---|
| Values | portrait | landscape |
| Support | Chrome 105 · Firefox 110 · Safari 16 |
| Spec | css-conditional-5 |
style()
Tests the computed value of a custom property on the container. Every element is a style container, so no container-type is needed; the query looks at the nearest ancestor, or the nearest one with the given container-name. Browsers support custom properties only, not ordinary properties.
| Syntax | style( <style-query> ) |
|---|---|
| Support | Chrome 111 · Firefox 151 · Safari 18 Range syntax: Chrome 142 · Firefox 151 · Safari no |
| Spec | css-conditional-5 |
.card { --variant: featured; }
@container style(--variant: featured) {
.card-title { color: crimson; }
}
A bare name such as style(--variant) is true when the property has any value other than its initial value. With range syntax a query can compare values, as in style(--columns > 2).
scroll-state()
Tests the scrolling state of a container that has container-type: scroll-state, using the features stuck, snapped, scrollable and scrolled below. The rules inside style the container's descendants.
| Syntax | scroll-state( <scroll-state-query> ) |
|---|---|
| Support | Chrome 133 · Firefox no · Safari no |
| Spec | css-conditional-5 |
header { position: sticky; top: 0; container-type: scroll-state; }
@container scroll-state(stuck: top) {
header nav { box-shadow: 0 2px 8px rgb(0 0 0 / 0.2); }
}
stuck
Inside scroll-state(): whether a sticky-positioned container is currently stuck against the given edge of its scroll container.
| Type | Discrete |
|---|---|
| Values | none | top | right | bottom | left | block-start | inline-start | block-end | inline-end |
| Support | Chrome 133 · Firefox no · Safari no |
| Spec | css-conditional-5 |
snapped
Inside scroll-state(): whether the container is the element its scroll container is currently snapped to, in the given axis.
| Type | Discrete |
|---|---|
| Values | none | x | y | block | inline | both |
| Support | Chrome 133 · Firefox no · Safari no |
| Spec | css-conditional-5 |
scrollable
Inside scroll-state(): whether the container, as a scroll container, can be scrolled further in the given direction. Use it to show scroll hints or arrows only when there is more to see.
| Type | Discrete |
|---|---|
| Values | none | top | right | bottom | left | block-start | inline-start | block-end | inline-end | x | y | block | inline |
| Support | Chrome 133 · Firefox no · Safari no |
| Spec | css-conditional-5 |
scrolled
Inside scroll-state(): the direction the container was most recently scrolled in, for example to hide a header while the user scrolls down.
| Type | Discrete |
|---|---|
| Values | none | top | right | bottom | left | block-start | inline-start | block-end | inline-end | x | y | block | inline |
| Support | Chrome 144 · Firefox no · Safari no |
| Spec | css-conditional-5 |
anchored()
Tests the state of an anchor-positioned element that has container-type: anchored. Its fallback feature matches the position option currently in use, so descendants can adapt when the browser flips the element to another side of its anchor.
| Type | Discrete |
|---|---|
| Values | fallback: none | [ [<dashed-ident> || <try-tactic>] | <position-area-query> ] |
| Support | Chrome 143 · Firefox no · Safari no |
| Spec | css-anchor-position-2 |
A <try-tactic> is one or more of flip-block, flip-inline, flip-start, flip-x and flip-y, as used in position-try-fallbacks.