skip to content

In CSS, how do you express AND, OR, and NOT across @media conditions, and what does the leading only keyword do?

level: middleimportance: must knowfreq 58%

answer

  1. comma is the union, not the intersection
  2. type defaults to all when omitted
  3. not swallows the whole query
  4. only is a fossil for IE 8
  5. invalid queries just never match

basics

~20 s

AND is the and keyword between parenthesised conditions. OR is a comma-separated list of whole queries, with an explicit or keyword available in newer syntax. NOT negates an entire query. The legacy only keyword hides a query from pre-Level-3 browsers and otherwise does nothing.

solid answer

~50 s

`and` joins conditions that must all hold: `@media screen and (width >= 40rem) and (orientation: landscape)`. OR is traditionally the comma — `@media print, (width < 30rem)` applies when *either* query matches, and the comma separates whole queries, not features. Media Queries Level 4 also added an explicit `or` keyword between parenthesised conditions, though you cannot freely mix `and` and `or` at the same level without parentheses. `not` negates an entire query, so in a comma list it only negates the query it appears in; Level 4 also allows negating a single condition, as in `@media (not (hover: hover))`. Finally, `only` is a compatibility relic: `@media only screen and (…)` made browsers that understood media types but not media features skip the rule. Modern browsers ignore it, and it must be followed by a media type.

code

css · 14 lines
css
/* AND: every condition must hold */
@media screen and (width >= 40rem) and (orientation: landscape) {
  .layout { grid-template-columns: 16rem 1fr; }
}

/* OR: a comma-separated list matches if any member matches */
@media print, (width < 30rem) {
  .sidebar { display: none; }
}

/* NOT applied to a single condition */
@media (not (hover: hover)) {
  .tooltip { display: none; }
}

go deeper

for a junior

Be able to read a query aloud correctly: and means every condition must hold, and a comma means any one of the listed queries is enough. Know that omitting the media type means all.

for a middle

Explain that not applies to the entire query rather than the following condition, that the comma separates whole queries and not features, and what only was originally for.

for a senior

Show judgment about which conditions belong in a query at all — capability and dimension rather than device guesses — and why an invalid query failing silently is a debugging trap worth checking first.

for a principal

Own the codebase's query vocabulary: a small named set of conditions rather than ad-hoc combinations scattered through components, so that a breakpoint or capability policy can be changed in one place.

## The anatomy of a query An `@media` rule takes a comma-separated *list* of media queries. Each query is an optional media type (`all`, `print`, `screen`, `speech`) plus zero or more *conditions* in parentheses, joined by logical keywords. If the media type is omitted it defaults to `all`, which is why `@media (width >= 40rem)` and `@media all and (width >= 40rem)` behave identically. ```css @media screen and (width >= 40rem) { } /* ^type ^join ^condition */ ``` When a media type appears, `and` is required between it and the first condition. `@media screen (width >= 40rem)` is invalid. ## AND `and` between parenthesised conditions requires all of them: ```css @media (width >= 40rem) and (orientation: landscape) and (hover: hover) { } ``` There is no limit on how many you chain, and the browser short-circuits nothing you can observe — either the whole conjunction matches or the block does not apply. ## OR — the comma CSS has no `or` in the original Level 3 syntax. The comma plays that role, and it separates *entire queries*, not conditions: ```css @media print, (width < 30rem) { .sidebar { display: none; } } ``` This applies when printing **or** when the viewport is narrow. A very common misreading treats the comma as "and", producing rules that fire far more often than intended. The mental model to hold: a comma-separated list matches if *any* member matches — it is a union. Media Queries Level 4 added an explicit `or` keyword usable between parenthesised conditions: ```css @media ((width < 30rem) or (orientation: portrait)) { } ``` The catch is that you may not mix `and` and `or` at the same nesting level without parentheses — the grammar forbids the ambiguous `A and B or C` precisely so that nobody has to memorise a precedence table. Parenthesise, or fall back to the comma form, which every browser has understood since media queries shipped. ## NOT `not` at the front of a query negates *that whole query*: ```css @media not screen and (width >= 40rem) { } ``` This is read as `not (screen and (width >= 40rem))` — it applies to everything except wide screens, including print at any width. It does **not** mean "non-screen media that are wide". Because negation binds to the entire query, `not` in one member of a comma list affects only that member: ```css @media not print, (width >= 60rem) { } ``` Level 4 also permits negating an individual condition, which is often what you actually want: ```css @media (not (hover: hover)) { .tooltip { display: none; } } ``` ## `only` `only` is the fossil in the syntax. In the era of browsers that understood media *types* but not media *features* — notably Internet Explorer 8 and earlier — a rule like `@media screen and (min-width: 40em)` would be parsed as plain `@media screen` and applied unconditionally, breaking layouts. Prefixing `only` produced a token those browsers did not recognise, so they skipped the rule entirely. In every current browser `only` has no effect whatsoever; it is legal, it must be followed by a media type, and its presence in a modern stylesheet is copy-paste inheritance, not technique. ## Media types worth knowing Only three matter in practice: `all` (the default), `screen`, and `print`. `speech` exists for speech synthesisers. The long tail from the CSS 2.1 era — `tty`, `tv`, `projection`, `handheld`, `braille`, `aural` — was deprecated in Level 4; browsers keep them parseable so old stylesheets don't break, but they never match. In particular `handheld` never meant "phone" in any browser you will meet, and a query aimed at it is dead code. A related instinct worth resisting: media *types* are not device categories. There is no `@media mobile`. Everything a phone browser does is `screen`, and the way you distinguish it is by querying dimensions or input capability, never by type. ## Invalid queries fail closed A malformed query — a stray unparenthesised condition, an unknown feature name, a comparison operator on a discrete feature — is invalid, and an invalid query simply never matches. Nothing is logged in the page, and the entire block silently does nothing. When a media block "isn't applying," checking the query's validity before debugging the declarations inside it saves a lot of time. In a comma list, one invalid member is dropped while the valid ones still work, which can make a partially-broken rule look intermittently correct.

  • What does @media not screen and (width >= 40rem) actually match?
    Everything except a wide screen. The `not` negates the whole query, so it reads as `not (screen and width >= 40rem)` — it matches print at any width, and it matches screens narrower than 40rem. It does *not* mean "non-screen media that happen to be wide." If you want to negate only the feature, use the Level 4 form `@media screen and (not (width >= 40rem))`.
  • Is there a media type that targets phones?
    No. Every graphical browser, on a phone or a desktop, reports `screen`; the CSS 2.1 types like `handheld` and `tv` were deprecated in Level 4 and never match. You distinguish contexts by querying what actually differs — viewport dimensions, `orientation`, `pointer` and `hover` — because a phone is not a device class in CSS, it is a small viewport with a coarse pointer.
  • Does the orientation media feature describe the device or the viewport?
    The viewport. `(orientation: landscape)` matches whenever the viewport is wider than it is tall, so a desktop window dragged wide matches landscape and a tall narrow browser window on the same monitor matches portrait. It says nothing about how the physical device is being held, which is why width-based queries usually express layout intent more directly.

saying these in an interview costs you the question

  • Reads the comma as AND rather than OR
  • Thinks not negates only the condition after it
  • Believes only screen is needed for modern browsers
  • Looks for a mobile or handheld media type
  • Assumes a broken query throws a visible error

context