A CSS selector describes which elements a styling rule matches. It can constrain an element's type, HTML attributes, structural relationships or state. The declarations in a rule then apply to matching elements, subject to the CSS cascade; matching and choosing a winning declaration are separate operations.[ref]
For example, p.warning matches a paragraph whose class list contains warning. Writing p .warning instead uses a descendant CSS combinator: it matches a classed element inside a paragraph, rather than requiring the paragraph itself to carry that class. The space is therefore meaningful syntax.
A child CSS combinator changes the relationship again. article > p.warning matches warning paragraphs directly inside an article, while article p.warning also permits intervening elements. A comma-separated selector list can describe alternatives, and a CSS pseudo-class such as :hover can test an element's state.[ref]
A successful match says nothing by itself about whether one declaration defeats another. If both p.warning and #notice match an element, CSS specificity and earlier cascade priorities help choose the result. A CSS selector should also be distinguished from a CSS pseudo-element, which can address an abstract part or generated box rather than simply selecting another existing HTML element.
A CSS combinator specifies a structural relationship between parts of a CSS selector. A descendant space permits any depth, > requires an immediate child, + requires the next element sibling, and ~ permits a later element sibling. These operators determine which elements match; they contribute no CSS specificity of their own.[ref]
Consider <section><h2>Title</h2><p>A</p><div><p>B</p></div><p>C</p></section>. The selector section p matches all three paragraphs. section > p matches A and C, since B has the div as its immediate parent. h2 + p matches A, the next element sibling of the heading. h2 ~ p matches A and C, the paragraph siblings following that heading.
Whitespace text between tags does not count as an intervening element sibling for the + relation. Likewise, ~ stays within one parent; it does not search arbitrarily far through the document for any later paragraph. This makes the distinction between document order and sibling relationships concrete.
A change in a combinator can therefore change a rule's scope without changing its selector counts. article p.warning and article > p.warning have the same CSS specificity but can match different paragraphs. Debugging a style rule requires checking the relationship it requests as well as the priority of the declarations it contains.
A CSS pseudo-element represents an abstract styling target associated with an element, such as a typographic portion or generated content. Examples include ::first-line, ::before and ::after. It allows CSS to style parts of the rendering that need not be separate HTML elements in the ordinary document tree.[ref]
For example, p::before { content: "Note: "; font-weight: bold; } can generate a bold prefix before a paragraph's content. The prefix participates in the rendering under the pseudo-element's rules, while the paragraph's ordinary text nodes remain unchanged. Reading the paragraph's textContent is therefore not a general way to recover every word a user sees on screen.
A typographic example is p::first-line. Which characters belong to the first rendered line depends on layout width, fonts and wrapping. Changing the width can move text into or out of that pseudo-element without inserting or deleting any DOM text nodes. Pseudo-elements also differ in which properties apply to them.[ref]
A CSS pseudo-class instead adds a matching condition such as focus or sibling position. The visual similarity of their names does not make the two mechanisms interchangeable. Modern pseudo-element syntax uses a double colon; some older single-colon spellings persist for compatibility, so a spelling alone should be interpreted using the specified selector rules.
A CSS pseudo-class matches an element using a condition beyond an ordinary type, class or attribute selector. Conditions can concern interaction state, control state or position among siblings. Its syntax uses a colon, as in :hover, :focus or :nth-child(2n). It refines matching of the element rather than creating another ordinary DOM node.[ref]
For example, button:focus matches a button with focus, while button:hover concerns the pointing-device interaction state defined by that pseudo-class. A focused button need not be hovered. A control's :checked state can also change through interaction, so matching is not limited to the exact attribute spelling in the original source.
For a structural example, li:nth-child(2n) matches list-item elements in even positions among element siblings. Text nodes and comments do not occupy counted positions. However, another kind of element sibling does count, so the expression is not automatically equivalent to selecting every second li while ignoring all other element types.[ref]
Most CSS pseudo-classes contribute to the class component of CSS specificity, but functional forms have explicit exceptions. :where(...) contributes zero, while :is(...) uses the greatest specificity in its argument list. Matching semantics and priority rules must therefore both be checked when a functional pseudo-class changes a rule's behavior.

Articles by others on the same topic (0)

There are currently no matching articles.