Is given string a valid media descriptor (including media query)?

Quick Take

import { strict as assert } from "assert";
import { isMediaD } from "is-media-descriptor";

assert.deepEqual(isMediaD("screeen"), [
    idxFrom: 0,
    idxTo: 7,
    message: `Did you mean "screen"?`,
    fix: {
      ranges: [[0, 7, "screen"]],


We are talking about so-called media descriptors (older spec opens in a new tab, newer spec - CSS MQ Level 4, draft at the moment opens in a new tab), for example, the part screen and (color), projection and (color) in both HTML and CSS:

<link media="screen and (color), projection and (color)" rel="stylesheet" href="example.css">

<link media="screen and (color), projection and (color)" rel="stylesheet" href="example.css" />

<?xml-stylesheet media="screen and (color), projection and (color)" rel="stylesheet" href="example.css" ?>
@import url(example.css) screen and (color), projection and (color);

@media screen and (color), projection and (color) { ... }

We plan to catch as many errors as possible:

  • typos
  • unclosed brackets
  • redundant characters
  • untangle the boolean logic
  • ... anything that can happen to media queries and media selectors in general.

This is not a replacement for the validator; this is a linting tool. We will use it in emlint.

Conceptually, CSS spec is very permissive, if it doesn't like something it invalidates that part and moves on. In this light, linting needs to be the opposite.

API - Input

isMediaD(str, opts)

In other words, a function which takes a string and options, a plain object.

Input argument Type Obligatory? Description
str String no The extracted value of HTML media attribute or CSS media query without @media or opening bracket.
opts Plain object no Optional options go here.

For example, all the calls below will yield an empty array (no errors):

isMediaD("screen", {});
isMediaD("screen", null);
isMediaD("screen", { offset: 0 });
isMediaD("screen", { offset: 51 });

⚠️ A bad example is below - don't put @media, please extract the value:

// program won't work with `@media` - extract the value first!
"@media only (screen) and (min-width: 320px) and (max-width: 500px) {"

Feed function with extracted value, with no @media:

isMediaD("only (screen) and (min-width: 320px) and (max-width: 500px)");

If an input is not a string or an empty string, an empty array will be returned.

Options object

options object's key Type Obligatory? Default Description
offset Integer no 0 All reported indexes will be incremented by this much.

Falsy opt.offset is fine but something truthy which is not a natural number will throw.

API - Output

The program returns an array of zero or more plain objects, each meaning an error. Each object's notation is the same as in emlint (except there's no ruleId):

idxFrom: 21,
idxTo: 22,
message: `Rogue bracket.`,
fix: {
ranges: [[21, 22]]

Quick basics: idxFrom and idxTo are the same as in String.slice, just used for marking.

The fix key is either null or has value — plain object — with key ranges. ESLint uses singular, range, EMLint uses ranges, plural, because EMLint uses Ranges notation — where ESLint marks "to add" thing separately, EMLint puts it as the third element in ranges array.

Ranges are always either null or array of arrays.

EMLint and ranges arrays here follow Ranges notation and all Ranges packages can be used to process them — merging, inverting, resolving/applying and so on.


There are capable CSS parsers out there, but they are all oriented at parsing the correct code and strictly pure HTML or CSS. Code validators built upon such parsers are not really serious validators.

Conceptually, code checking tools should use advanced but slow parsers, likely scanerless-ones to find and fix errors. Then, for general parsing (like syntax highlighting), parsers which can't recognise many errors but are fast should be used.

We're talking about two different levels of the "food-chain". Currently, there is not much competition for this program in this sense.


See it in the monorepo opens in a new tab, on GitHub.


To report bugs or request features or assistance, raise an issue on GitHub opens in a new tab.

Any code contributions welcome! All Pull Requests will be dealt promptly.


MIT opens in a new tab

Copyright © 2010–2021 Roy Revelt and other contributors

Related packages:

📦 emlint 5.0.1
Pluggable email template code linter
📦 html-crush 5.0.1
Minifies HTML/CSS: valid or broken, pure or mixed with other languages
📦 stristri 4.0.1
Extracts or deletes HTML, CSS, text and/or templating tags from string
📦 string-strip-html 9.0.1
Strips HTML tags from strings. No parser, accepts mixed sources
📦 detect-is-it-html-or-xhtml 5.0.1
Answers, is the string input string more an HTML or XHTML (or neither)
📦 detect-templating-language 3.0.1
Detects various templating languages present in string
📦 html-table-patcher 5.0.1
Visual helper to place templating code around table tags into correct places