CSS Syntax
Nest accepts CSS selector strings wherever a selector is expected. They are parsed at evaluation time and matched by the same engine as programmatic selectors.
Every form below is exercised by the selectors-demo template, whose self-tests
assert exactly which nodes each selector matches.
Basic tokens
Section titled “Basic tokens”Star *
Section titled “Star *”Matches any node:
is = "*"ID #name
Section titled “ID #name”Matches a node by its name attribute (the attrset key in the DOM):
is = "#lb-prod" # node named lb-prodis = "#web-1" # node named web-1Name (bare word)
Section titled “Name (bare word)”Matches by name, or by a trait whose path ends in that word:
is = "web" # node named web, or carrying a trait ending in `.web`Class .traitName
Section titled “Class .traitName”Matches nodes whose entity trait exposes an output class with this name:
is = ".nixos" # entity has nixos output classis = ".homeManager" # entity has homeManager output classAttribute [key=value]
Section titled “Attribute [key=value]”Matches nodes where toString node.key == value:
is = "[env=prod]"is = "[system=x86_64-linux]"Boolean attributes are understood: [key=true] / [key=false] match a real
true/false as well as the strings "true"/"false".
Attribute existence [key]
Section titled “Attribute existence [key]”Matches nodes that have the attribute, regardless of value:
is = "[sshKeys]"is = "[httpPort]"Current &
Section titled “Current &”& is the node currently being matched. On its own it matches anything; its
value is as an anchor for relative selectors (see below):
is = "&.nixos" # this node, and it has the nixos classis = "& > .web" # this node, and it has a direct .web childCompound selectors
Section titled “Compound selectors”Multiple tokens without a combinator — all must match (AND):
is = "#lb-prod.nixos" # named lb-prod AND has nixos classis = "[env=prod][system=x86_64-linux]" # two attribute conditionsCombinators
Section titled “Combinators”Descendant (space)
Section titled “Descendant (space)”A space between selectors matches a node descended from another (not necessarily a direct child):
is = "prod web" # a `web` anywhere under `prod`Child >
Section titled “Child >”Matches a node that is a direct child of another:
is = "prod > web" # node web whose parent is prodis = "cluster > *" # any direct child of clusterAdjacent sibling +
Section titled “Adjacent sibling +”Matches a node whose immediately-preceding sibling matches the left selector (siblings are ordered by their DOM key):
is = "#web-1 + #web-2" # web-2, when web-1 is the sibling just before itOr (comma)
Section titled “Or (comma)”Comma-separated alternatives — any must match:
is = "#web-1, #web-2"is = "[env=prod], [env=staging]"Pseudo-classes
Section titled “Pseudo-classes”:not(sel)
Section titled “:not(sel)”Matches nodes NOT matching sel:
is = ":not(#alice)"is = ":not([env=staging])":has(sel)
Section titled “:has(sel)”Matches nodes that have a descendant matching sel:
is = ":has(.admin)"is = ":has([sshKeys])":is(sel)
Section titled “:is(sel)”Matches nodes matching sel; with a separator-less list it is an OR over the
alternatives:
is = "box:is(#web-1#web-2)" # a box that is web-1 OR web-2:within(sel)
Section titled “:within(sel)”Matches nodes that have an ancestor matching sel:
is = ":within(#prod)"is = ":within(.nixos)"Relative selectors with &
Section titled “Relative selectors with &”Combinators anchored on & describe the matched node’s surroundings:
is = "& > .web" # I have a direct .web child (like :has(> .web))is = "&:has(.admin)" # I have an .admin descendantComplete examples
Section titled “Complete examples”# All hostsis = ".nixos"
# Hosts named web-1is = "#web-1.nixos"
# Prod hosts by attributeis = "[env=prod].nixos"
# Either prod or stagingis = "[env=prod], [env=staging]"
# Hosts with admin descendantsis = ".nixos:has(.admin)"
# Web nodes under prodis = "prod .nixos[addr]"Parsing
Section titled “Parsing”String selectors are parsed by parseCssSel which tokenizes via parseCompound:
#name→{ __sel = "id"; name = "…" }.class→{ __sel = "class"; name = "…" }&→{ __sel = "current" }[k=v]→{ __sel = "attr"; key = "k"; val = "v" }[k]→{ __sel = "attrExists"; key = "k" }:pseudo(inner)→{ __sel = "pseudo"; selector = parsed-inner },→{ __sel = "or"; selectors = [ … ] }(space) →{ __sel = "descendant"; ancestorSel = …; descendantSel = … }>→{ __sel = "child"; parentSel = …; childSel = … }+→{ __sel = "adjacent"; previousSel = …; nextSel = … }
Compound (multiple tokens) → list, matched as AND.