Selectors

A selector is a pattern that describes the scope of a rule, i.e. the set of HTML elements to which it should apply. Tecton supports several types of selectors, including element, class, ID, attribute, and pseudo-class selectors. You can combine these to form more advanced selectors or even a selector list.

Element selectors

An element selector targets all HTML elements of a particular type, such as div, p, a, or img. In its most basic form, an element selector simply consists of the target element type, e.g.

module Example.StyleSheet where

import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  a ? Rule.do -- Applies to HTML `a` (anchor) elements.
    textDecorationLine := none

Open with Try PureScript

Universal selector

The universal selector is a special type of element selector that applies to any element. In CSS, it is denoted by the * symbol. In Tecton, it is called universal. Any selector that does not target another type of element must begin with the universal selector.

Note If you have written CSS before, you have almost certainly used the universal selector, perhaps without realizing: It is implicitly included in other types of selectors; for example, .foo is actually the same as *.foo. For more information, see Selectors Level 3 (W3C).

The following rule uses the universal selector to remove the margin from every element in the webpage:

module Example.StyleSheet where

import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  universal ? Rule.do
    margin := nil

Open with Try PureScript

Class selectors

A class selector matches any element whose class attribute contains the specified class name. The &. operator appends the target class to a selector. For example, the following selector targets all elements with the class name container:

module Example.StyleSheet where

import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  universal &. ClassName "container" ? Rule.do
    width := auto

Open with Try PureScript

ID selectors

An ID selector targets the element whose id attribute is exactly the specified value. The &# operator appends the element ID to another selector. The selector in the following example matches the element with ID appBar:

module Example.StyleSheet where

import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  universal &# ElementId "appBar" ? Rule.do
    height := px 64

Open with Try PureScript

Attribute selectors

An attribute selector targets elements based on their attributes or attribute values. It can match on the presence of any HTML attribute such as href, src, or alt. A number of operators can further limit matches to specific attribute values.

Presence

To match elements based on the presence of an attribute, the attribute is used by itself without any additional operator. For example, the following selector applies to an input element with a required attribute:

module Example.StyleSheet where

import Color (rgb)
import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  input &@ required ? Rule.do
    backgroundColor := rgb 255 153 0

Open with Try PureScript

Exact value

The @= operator can be used to target an element whose attribute value exactly matches the specified value. For example, the following selector matches elements with the attribute role="button":

module Example.StyleSheet where

import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  universal &@ role @= "button" ? Rule.do
    fontWeight := bold

Open with Try PureScript

Value within list

The ~= operator can be used to find a matching value within a whitespace-delimited list of words. In the following example, the selector will match an element with an attribute class="foo bar baz". (This is, of course, equivalent to a class selector.)

module Example.StyleSheet where

import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  universal &@ class' ~= "bar" ? Rule.do
    display := none

Open with Try PureScript

Code/subcode

Intended primarily for locale tags, the |= operator matches when an attribute value

  • exactly matches the specified value or
  • begins with the specified value followed by a hyphen.

The selector in the following example will match an a element whose hreflang attribute is equal to "en" or "en-US", but not "end":

module Example.StyleSheet where

import Color (rgb)
import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  a &@ hreflang |= "en" ? Rule.do
    color := rgb 255 0 196

Open with Try PureScript

Prefix

You can use the ^= operator to represent an element whose attribute value begins with the specified value. The following example targets insecure links based on their http:// prefix:

module Example.StyleSheet where

import Color (rgb)
import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  a &@ href ^= "http://" ? Rule.do
    color := rgb 255 0 0

Open with Try PureScript

Suffix

The $= operator matches an element with an attribute value ending in the specified value. This can be used to target a link to a PDF, for instance:

module Example.StyleSheet where

import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  a &@ href $= ".pdf" ? Rule.do
    fontWeight := bold

Open with Try PureScript

Substring

To target an element whose attribute value simply contains a given substring, use the *= operator. The following selector matches any image sourced from Wikimedia:

module Example.StyleSheet where

import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  img &@ src *= "wikimedia.org" ? Rule.do
    display := initial

Open with Try PureScript

Pseudo-classes

A pseudo-class can be used to style elements based on their state or position in the DOM tree. You can append a pseudo-class to the end of a selector using the &: operator. For instance, the focus pseudo-class applies a style conditionally when the element has focus:

module Example.StyleSheet where

import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  universal &: focus ? Rule.do
    outlineStyle := solid

Open with Try PureScript

Basic pseudo-classes

The most common pseudo-classes usually consist of a single keyword, such as the following:

  • link targets an unvisited link, i.e. an a element that the user has not yet clicked or visited.
  • visited targets a visited link, i.e. an a element that the user has clicked or visited in the past.
  • hover matches an element while the user's mouse cursor hovers over it.
  • focus matches an element when it has keyboard focus. An element typically receives focus through user interaction, such as clicking on an input field.
  • focusWithin targets an element containing a descendant element that has keyboard focus.
  • active matches an element while it is being clicked, pressed, or activated.
  • target targets an element whose ID matches the current location hash. This is often useful with deep-linking in order to draw the user's attention to the requested section of the page.
  • enabled targets an interactive element (e.g. input, select, or button) that is enabled.
  • disabled targets an interactive element (e.g. input, select, or button) that is disabled.
  • checked matches a radio button, checkbox, or option element that is checked or selected.
  • indeterminate matches a checkbox element in an indeterminate state, i.e. neither checked nor unchecked.
  • root targets the highest-level element in the document, typically an html element.
  • firstChild targets an element with no preceding siblings.
  • lastChild targets an element with no subsequent siblings.
  • firstOfType matches an element with no preceding siblings of the same type.
  • lastOfType matches an element with no subsequent siblings of the same type.
  • onlyChild matches an element with no siblings.
  • onlyOfType matches an element with no siblings of the same type.
  • empty matches an element with no children or that contains only empty text nodes.

The lang pseudo-class

The lang pseudo-class can be used to target an element based on the value of its lang attribute (or the value inherited from an ancestor). The lang pseudo-class is parameterized by a one- or two-part language tag consisting of an ISO 639-1 language code, optionally followed by a hyphen and an ISO 3166-1 alpha-2 country code. To construct the pseudo-class, apply the lang function to the language tag string. For example:

module Example.StyleSheet where

import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  universal &: lang "en-US" ? Rule.do
    display := none

Open with Try PureScript

The not pseudo-class

The not pseudo-class targets an element that does not match the specified selector. You can pass any selector to the not function to construct the pseudo-class. For example, the following selector will match any input element lacking a type attribute:

module Example.StyleSheet where

import Color (rgb)
import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  input &: not (universal &@ type') ? Rule.do
    backgroundColor := rgb 255 0 0

Open with Try PureScript

Nth pseudo-classes

A special group of pseudo-classes allows you to select an element by its position within the parent element. These use a formula of the form an+b where:

  • a determines the frequency of matches. For example, 3n can be interpreted as every third element.
  • b represents an offset, i.e. the index of the first matching element (one-indexed). For example, 2 will match the second element, before the pattern repeats.

These pseudo-classes are

  • nthChild, which selects elements matching the an+b formula within their parent;
  • nthLastChild, which reverses the direction of nthChild, counting from the last child element within a container;
  • nthOfType, which is like a version of nthChild that ignores sibling elements of a different type when evaluating the an+b formula; and
  • nthLastOfType, which reverses the direction of nthOfType, counting from the last child element within a container.

The :nth Tester (CSS-Tricks) offers an interactive way to learn how these pseudo-classes and the an+b formula work.

Constructing these pseudo-classes in Tecton begins with the formula:

  • The even function will select even-numbered elements, equivalent to 2n.
  • The odd function will select odd-numbered elements, equivalent to 2n+1.
  • The #+ operator has two parameters a and b, used to create an an+b formula, e.g. 2 #+ 1.
  • The #- operator has two parameters a and b, used to create an an-b formula, e.g. 2 #- 1.

Apply one of the nth* functions listed above to the result to create the pseudo class.

Here is how nthChild, for instance, can be used to add zebra-striping to a table:

module Example.StyleSheet where

import Color (rgb)
import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  tr &: nthChild even ? Rule.do
    backgroundColor := rgb 240 240 240

Open with Try PureScript

Pseudo-elements

Pseudo-elements are virtual elements that can be styled using CSS but exist outside of the DOM. These offer control and flexibility in design without modifying HTML structure. You can append a pseudo-element to a selector using the &:: operator. For example, the following adds a red asterisk symbol to a required form field label using the after pseudo-element:

module Example.StyleSheet where

import Color (rgb)
import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  universal &. ClassName "required" &:: after ? Rule.do
    content := " *"
    color := rgb 255 0 0

Open with Try PureScript

Note that, once a pseudo-element has been appended to selector, the selector can no longer be modified; otherwise, the resulting CSS would be invalid.

Selector list

A common CSS pattern is a ruleset that targets elements matching any of a number of selectors. This is useful as a performance optimization as well to avoid duplication.

Throughout the library, lists are modeled using nested tuples via the /\ operator. Selector lists are no exception.

Here is an example of a ruleset the applies to buttons as well as hyperlinks (a elements) masquerading as buttons:

module Example.StyleSheet where

import Data.Tuple.Nested ((/\))
import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  button /\ a &. ClassName "button" ? Rule.do
    fontWeight := bold

Open with Try PureScript

See also