selery is a small, handwritten CSS selector parser and DOM query engine.
It aims to be compliant with the relevant specifications (CSS Syntax Level 3, CSS Selectors Level 4, and others), while remaining compact and understandable so that it can be used as a starting point to experiment with new CSS syntax.
⚠️ Currently a work-in-progress
You can install selery as an npm package:
npm install selery
Alternatively, head over to the latest release and download the
selery-<version>.zip file from under Assets. The archive contains the library built in several variants to choose from, suitable for both browsers and Node.js.
Or fetch the library from Unpkg by including this in your web page:
Or, to bring the library into any web page you're on (as long as its configuration doesn't prevent it), bring up the browser's Console and paste this snippet:
withdocumentbodysrc = '//unpkg.com/selery';
When used with a
<script>tag, the library is available under the
Takes a string selector and returns an array of tokens.
let tokenize = ;;
A token is a plain object having a
type property, along with other optional properties, which are documented in the CSS token reference. For the sample selector
'article a[href="#"]' mentioned above, the resulting token array is:
type: 'ident' value: 'article'type: 'whitespace'type: 'ident' value: 'a'type: '['type: 'ident' value: 'href'type: 'delim' value: '='type: 'string' value: '#'type: ']';
The function will throw an erorr if the selector supplied does not follow generally valid CSS syntax.
Accepts an input argument, which can be either an array of tokens obtained from the
tokenize() function or, more conveniently, a string representing a selector. The latter is passed through
It produces an abstract syntax tree (AST), also called a parse tree, for the provided input.
let parse = ;let tree = ;
syntax (Object) — provide custom microsyntaxes to various pseudo-classes and pseudo-elements. By default, the argument of
:nth-*() pseudo-classes are parsed with the An+B microsyntax, while for the
:has(), the argument is parsed as a
The keys to the syntax object are the identifier for the pseudo-class (prefixed by
:) or pseudo-element (prefixed by
::), and the values are either strings (one of
SelectorList) or functions. Function values will receive an array of tokens and can return anything suitable for storing in the AST node's
Converts the input back into a string. The input argument can be either an array of tokens, or an object representing a parse tree.
DOM API shims
Shims for selector-accepting DOM methods using simpler DOM primitives.
Across these methods:
- the selector argument can be a string (as with their native DOM counterparts), an array of tokens, or an object representing a parse tree;
- the options object accepts the following keys:
- root (Element) — an optional scoping root;
- scope (Element | Array) — an optional set of :scope elements.
matches(element, selector, options)
See the Element.matches DOM method.
closest(element, selector, options)
See the Element.closest DOM method.
querySelector(element, selector, options)
See the Element.querySelector DOM method.
querySelectorAll(element, selector, options)
See the Element.querySelectorAll DOM method. While the native DOM method return a
NodeList, our implementation of
querySelectorAll returns an
CSS token reference
CSS selector AST reference
All nodes in the AST contain a
type property, and additional properties for each specific type, listed below.
The topmost node in the AST.
selectors— an array of (possibly complex) selectors.
A complex selector represents a pair of selectors stringed together with combinators, such as
article > p.
left— the left-side (possibly complex, or compound) selector;
nullwhen the selector is relative, such as the
right— the right-side (possibly complex, compound) selector;
combinator— one of
Longer sequences of selectors are represented with nested
ComplexSelector elements in the AST. For example,
article > p span is represented as:
type: 'SelectorList'selectors:type: 'ComplexSelector'left:type: 'ComplexSelector'left:type: 'TypeSelector'identifier: 'article'right:type: 'TypeSelector'identifier: 'p'combinator: ' 'right:type: 'TypeSelector'identifier: 'span'combinator: ' '
A compound selector is a combination of simple selectors, all of which impose conditions on a single element, such as
selectors— an array of simple selectors.
Represents a type selector, such as
identifier(String) — the element type to match; can be
*in the case of the universal selector;
namespace(String) — the namespace, if provided with the
namespace|typesyntax; an empty string corresponds to the
Represents an ID selector, such as
identifier(String) — the ID to match;
Represents a class selector, such as
identifier(String) — the class name to match;
Represents an attribute selector, such as
identifier(String) — the attribute to match;
value(String) — the value to match against;
matcher(String) — one of
modifier(String) — either
i, if any.
Represents a pseudo-class selector (such as
:is(a, b, c)) or a pseudo-element (such as
Both types of nodes share a common structure:
identifier(String) — the pseudo-class or pseudo-element;
argument(Anything) — the argument to the pseudo-class / pseudo-element;
In CSS, there is more than one way to interpret the argument passed to pseudo-classes and pseudo-elements which expressed with the function notation. Some pseudo-classes, such as
:nth-*(), use the
An+B microsyntax, others accept a list of selectors.
You can control how the microsyntaxes get applied to the pseudo-classes and pseudo-elements with the
syntax option on the
The selery logo is typeset in Manicotti by David Jonathan Ross.