Current Version: 1.0.10 Project Name: csspp
CSS Preprocessor Reference -- Selectors

CSS Preprocessor parses all the selectors it finds in all the source files it parses. This ensures that only valid selectors are output making it easier to find potential errors in your source CSS files.

The supported selectors are all the selected supported in CSS 3 and the %<name> selector which is used to allow for optional rules defined in CSS libraries.

# Select All (*)

The asterisk (*) character can be used to select any one tag.

For example the following says any 'a' tag which appears in a tag defined inside a 'div' tag (i.e. <div><at least one other tag><a>):

div * a { color: orange; }

# Element Selection (E)

Any identifier is taken as the name of an element (i.e. a tag in your HTML). A tag must match one to one.

You may add more constraints to only match elements with a given class (.<class-name>), to only that one element with a given identifier (#<identifier>), to only match elements with an attribute defined ([<attribute-name>]) or an attribute with a certain value ([<attribute-name>=<value>]), all of those, except the identifier test, can be repeated any number of times.

# Element Has Attribute (E[attr])

Test whether an element has a given attribute. In this case, the value of the attribute is not checked, only that the attribute is defined.

The name of the element (E) is not required. Without it, any element that has the given attribute in the tree will match.

div[book] // matches <div book="red"> or <div book>

# Element Has Attribute with Specific Value (E[attr="value"])

Test whether an element has a given attribute set to a specific value.

The name of the element (E) is not required. Without it, any element that has the given attribute in the tree will match.

div[book="red"] // matches <div book="red">
Note
If value can be represented by an identifier, then the quotations are not required:
div[book=red] // matches <div book="red">

# Element Does Not Have Attribute with Specific Value (E[attr!="value"])

Test whether an element has a given attribute set to a specific value. If so, then refuse that element.

The name of the element (E) is not required. Without it, any element that does not have the given attribute in the tree will match.

div[book!="red"] // matches <div book="blue">
Note
When "value" can be represented by one identifier, then the quotes are not required:
div[book!=red] // matches <div book="green">
Warning
Note that CSS 3 does not support the != operator. The CSS Preprocessor replaces this syntax with:
div:not([book=red])

# Include Match "INCLUDE_MATCH" (CSS 3)

The include match, written tilde (~) and equal (=), no spaces in between, is used to check a list of whitespace separated items in the specified attribute. When attr is "class", it is the same as using the period selector.

So with this operator you can access other attributes in a way similar to the class attribute.

The name of the element (E) is not required. Without it, any element that has the given attribute in the tree will match.

div.wrapper or div[class~="wrapper"]
// matches <div class="section wrapper screen">
div[color~="green"] // matches <div color="red green blue">
Note
If value can be represented by an identifier, then the quotations are not required.
div[color~=green] // matches <div color="red green blue">

# Prefix Match "PREFIX_MATCH" (CSS 3)

The prefix match, written circumflex accent (^) and equal (=), no spaces in between, is used to check whether an attribute starts with the specified string.

The name of the element (E) is not required. Without it, any element that has the given attribute in the tree will match.

div[section^="1.1"] // matches 1.1, 1.1.0, 1.1.1, 1.1.2, 1.1b, etc.
Note
If value can be represented by an identifier, then the quotations are not required.
div[section^=sub]

# Suffix Match "SUFFIX_MATCH" (CSS 3)

The suffix match, written dollar ($) and equal (=), no spaces in between, is used to check whether an attribute ends with the specified string. The name of the element (E) is not required. Without it, any element that has the given attribute in the tree will match. div[height$=13] // match height="313" or height="113"
Note
If value can be represented by an identifier, then the quotations are not required.
div[height^=small]

# Substring Match "SUBSTRING_MATCH" (CSS 3)

The suffix match, written asterisk (*) and equal (=), no spaces in between, is used to check whether an attribute includes the specified string, anywhere.

The name of the element (E) is not required. Without it, any element that has the given attribute in the tree will match.

div[code*=part] // match code="55 part 3" or height="spartians"
Note
If value can be represented by an identifier, then the quotations are not required.
div[code^=part]

# Dash Match "DASH_MATCH" (CSS 3)

The dash match, written pipe (|) and equal (=), no spaces in between, is used to check a language in the hreflang attribute of an anchor tag. It is very unlikely that you will ever need this matching operator unless you are in the academic world or have a website similar to Wikipedia with translations of your many pages.

The value on the right side is checked against the list of languages defined in scripts/languages.scss, and when a country is defined, it is checked against the list of countries defined in script/countries.scss, lists which can be updates as required.

http://www.rfc-editor.org/rfc/bcp/bcp47.txt

Note
If value can be represented by an identifier, then the quotations are not required.
div[hreflang^=en]

# Root (E:root)

The :root pseudo class matches an element E if it is the root tag of the document.

Since the root of an HTML document is <html>, it generally is not required to specify :root.

html:root { margin: 0 }

# Nth Child (E:nth-child(n))

The :nth-child() pseudo function matches an element which is a child of E which position matches 'n'. The value 'n' can be defined as:

An+B

Where A and B have to be integers. The CSS Preprocessor will parse that definition to make sure it is valid and possibly optimize it if possible.

The letter 'n' appears verbatim. A and B are optional and the sign of the integer can be negative.

3n+1
-5n-2
7n-4

The function applies the values A and B and is a match if: $$\begin{cases} A \neq 0, & { ( child_{position} - 1 ) \bmod A - B = 0 } \\ A = 0, & { child_{position} - B = 0 }\end{cases}$$.

Todo:
The math needs to be enhanced to include the case when A is negative. I think it is wrong in that case in the current formula.

# Nth Last Child (E:nth-last-child(n))

The :nth-last-child() pseudo function matches an element which is a child of E which position, counting from the last child, matches 'n'. The value 'n' is defined as in Nth Child (E:nth-child(n)).

# Nth of Type (E:nth-of-type(n))

Search for the Nth element which is a sibling of E and has the same type (same tag name) as E. The value 'n' is defined as in Nth Child (E:nth-child(n)), only the elements that match the type are counted.

# Nth last of Type (E:nth-last-of-type(n))

Search for the Nth element, counting from the last sibling, which is a sibling of E and has the same type (same tag name) as E. The value 'n' is defined as in Nth Child (E:nth-child(n)), only the elements that match the type are counted.

# First Child (E:first-child)

This pseudo class selects the first child of element E.

# Last Child (E:last-child)

This pseudo class selects the last child of element E.

# First of Type (E:first-of-type)

Search for the first element of type E in the current list of siblings.

This is equivalent to :nth-of-type(1), see Nth of Type (E:nth-of-type(n)).

// first cell in a row
tr > td:first-of-type

# Last of Type (E:last-of-type)

Search for the last element of type E in the current list of siblings.

This is equivalent to nth-last-of-type(1), see Nth last of Type (E:nth-last-of-type(n)).

// last cell in a row
tr > td:last-of-type

# Only Child (E:only-child)

Return a tag if it is an only child (i.e. the parent of that tag has exactly 1 child).

This is equivalent to :first-child:last-child or :nth-child(1):nth-last-child(1) with lower specificity.

# Only of Type (E:only-of-type)

Search for tags with a specific type (as specified by E), if only one tag of that type is found in a list of siblings, then it matches.

This is equivalent to :first-of-type:last-of-type or :nth-type-of(1):nth-last-type-of(1) with lower specificity.

// apply CSS to cells of tables with a single column
tr > td:only-of-type

# Empty (E:empty)

Search for elements that have no children.

// hide empty span elements
span:empty { display: none }

The pseudo class "link" applies to anchors that have not yet been visited. This class only applies to anchor (A) tags.

:link { color: blue }

# Visited Link (E:visited)

The pseudo class "visited" applies to anchors that have already been visited. This class only applies to anchor (A) tags.

:visited { color: purple }

# Active Link (E:active)

The pseudo class "active" applies to anchors that are currently clicked (i.e. the user is pressing the mouse button and did not yet release the button.)

This class only applies to anchor (A) tags.

:active { color: red }

# Hover Link (E:hover)

The pseudo class ":hover" applies to anchors that are currently being hovered by a mouse pointer.

This class only applies to anchor (A) tags.

:hover { color: green }

# Element with Focus (E:focus)

The pseudo class ":focus" applies to anchors and input elements (including tags marked with contenteditable="true"). It is true for one element: the one which is currently focused by the browser.

:focus { color: cyan }

# Target Element (E:target)

The pseudo class ":target" applies to the element with identifier defined in the URI after the '#' character (also called the anchor).

:target { background-color: yellow }

# Language (E:lang(n))

The special :lang() pseudo function checks for a "lang" attribute in this element or any parent element. The system handling the language may actually use other definitions than just the lang attribute.

# Enabled Element (E:enabled)

The pseudo class ":enabled" applies to elements that can be enabled and disabled (i.e. <input> and <button> tags.) This class applies to elements that are current enabled (i.e. editable.)

:enabled { font-size: 150% }

# Disabled Element (E:disabled)

The pseudo class ":disabled" applies to elements that can be enabled and disabled (i.e. <input> and <button> tags.) This class applies to elements that are current disabled (i.e. cannot be modified by the end user.)

:disabled { background-color: gray }

# Checked Element (E:checked)

The pseudo class ":checked" applies to elements that can be checked (i.e. checkboxes and radio buttons.)

:checked { border: 1px solid #fff }

# First Line Pseudo Element (E::first-line) -- uses '::' since CSS 3

The pseudo element "::first-list" applies to "elements" (characters, inline images, etc.) that appear on the first line of a paragraph.

p::first-line { font-variant: small-caps }

# First Letter Pseudo Element (E::first-letter) -- uses '::' since CSS 3

The pseudo element "::first-letter" applies to the first letter that appears in E.

// make the first character appear on 3 lines and make sure said lines
p::first-letter { font-size: 300%; float: left; }

# Insert Before (E::before) -- uses '::' since CSS 3

The pseudo element "::before" injects the string specified with "content: \<string>" at the beginning of the specified element.

p::before { content: "Inject This"; }

# Insert After (E::after) -- uses '::' since CSS 3

The pseudo element "::after" injects the string specified with "content: \<string>" at the end of the specified element.

p::after { content: "Append That"; }

# Class Selector (E.class)

The pseudo class ".class" matches an element with a class attribute that includes the word "class". This is a shortcut of the ~= operator used with the name "class" as in:

p.super-class <=> p[class~="super-class"]

A match against multiple classes can be specified by avoiding spaces as in p.class1.class2.class3...

# Identifier Selector (E#id)

The pseudo class "\#id" matches an element which has identifier "id". Since identifiers are expected to be unique, selectors before a #id are generally useless unless your document may include the same identifier more than once.

#id { ... }

# Not Selector (E:not(s))

The pseudo function ":not(s)" matches an element which does not match the specified selector "s".

The "s" selector can only be a simple selector. This include most except selectors that start with "::" and ":not(s)". We also do not allow our extensions (name and &:hover in the not().)

// a paragraph except the one with identifier #id
p:not(#id) { ... }

# Selector Selector (E F)

A whitespace between two selectors E and F mean an element of type E and a descendant element of E of type F. There are no other constraints than the type, attribute, etc. (since E and F can be any type of selector.)

# Selector Child (E > F)

A greater than (>) between two selectors E and F mean an element of type E and a direct descendant element (i.e. a child) of E of type F. There are no other constraints than the type, attribute, etc. (since E and F can be any type of selector.)

# Selector Sibling (E + F)

A plus (+) between two selectors E and F mean an element of type E and the next sibling of type F. There are no other constraints than the type, attribute, etc. (since E and F can be any type of selector.)

E and F must be one after another. If F should should be any sibling, then use the ~ operator instead (Selector Sibling (E ~ F)).

# Selector Sibling (E ~ F)

A tilde (~) between two selectors E and F mean an element of type E followed by a sibling of type F. There are no other constraints than the type, attribute, etc. (since E and F can be any type of selector.)

This is similar to the + operator (Selector Sibling (E + F)), only F can be any sibling after E.

# Grammar used to parse the selectors

The definition of the grammar appears in CSS 3, the selectors:

http://www.w3.org/TR/selectors/

Note
The :not() function is considered to be a term ("complex term") because it cannot be used within itself (so :not(:not(...)) is not allowed.)

There is a more yacc like grammar definition:

selector-list: selector
| selector-list ',' selector
selector: term
| selector WHITESPACE '>' WHITESPACE term
| selector WHITESPACE '+' WHITESPACE term
| selector WHITESPACE '~' WHITESPACE term
| selector WHITESPACE term
| selector term
term: simple-term
| ':' FUNCTION (="not") component-value-list ')'
| ':' ':' IDENTIFIER
simple-term: universal-selector
| qualified-name
| HASH
| ':' IDENTIFIER
| ':' FUNCTION (!="not") component-value-list ')'
| '.' IDENTIFIER
| '[' WHITESPACE attribute-check WHITESPACE ']'
universal-selector: IDENTIFIER '|' '*'
| '*' '|' '*'
| '|' '*'
| '*'
qualified-name: IDENTIFIER '|' IDENTIFIER
| '*' '|' IDENTIFIER
| '|' IDENTIFIER
| IDENTIFIER
attribute-check: qualified-name
| qualified-name WHITESPACE attribute-operator WHITESPACE attribute-value
attribute-operator: '='
| '!='
| '~='
| '^='
| '\$='
| '*='
| '|='
attribute-value: IDENTIFIER
| INTEGER
| DECIMAL_NUMBER
| STRING

All operators have the same priority and all selections are always going from left to right.

The FUNCTION parsing changes for all n-th functions to re-read the input data as an A+Bn which generates a new token as expected.

Further we detect whether the same HASH appears more than once. Something like:

#my-div .super-class #my-div { ... }

is not going to work (assuming that the document respects the idea that 'my-div' cannot be used more than once since identifiers are expected to be unique.)

Documentation of CSS Preprocessor.

This document is part of the Snap! Websites Project.

Copyright by Made to Order Software Corp.