CSS Selectors
CSS selectors are essential tools for styling HTML elements. They allow precise targeting of elements in the DOM, based on type, class, ID, attributes, state, or position.
Main categories of selectors
- Simple selectors – select elements based on name, class, or ID
- Attribute selectors – select elements based on attributes and their values
- Pseudo-classes – select elements in a certain state (hover, focus, etc.)
- Pseudo-elements – select part of the content of an element (::before, ::after, etc.)
- Combinators – define relationships between elements (child, sibling, etc.)
- Multiple selectors – apply styles to several elements simultaneously
1. Simple selectors
Classic example: selecting all p and div elements.
Modern selectors: :is() and :where()
Allow grouping of selectors. :is() keeps specificity, :where() has zero specificity.
2. Attribute selectors
Attribute selectors allow targeting elements based on HTML attributes and their values. They are extremely
useful in modern applications, especially when using custom data-* attributes.
2.a Exact match
- [atr] – selects all elements that have the attribute “atr”
- [atr=val] – selects elements where the attribute value is exactly “val”
- [atr~=val] – selects elements where the attribute value contains the word “val” in a space-separated list
2.b Partial match (substring)
- [atr^=val] – value starts with “val”
- [atr$=val] – value ends with “val”
- [atr*=val] – value contains “val”
- [atr|=val] – value is “val” or starts with “val-” (ideal for
lang="en-US")
☞ The data-* attributes are useful for storing custom
information in HTML. They can be easily accessed with JavaScript and are often used in modern applications.
3. Pseudo-classes
Pseudo-classes are added at the end of selectors with a colon (:) and allow styling of elements in
a certain state (e.g., hover, focus, visited).
The order of applying pseudo-classes for links is important: LVHA –
:link → :visited → :hover → :active. Changing the order can lead to unpredictable behavior.
☞ Only :link and :visited are dedicated to links.
:hover, :focus, and :active are dynamic pseudo-classes and can be used
on any HTML element.
4. Pseudo-elements
Pseudo-elements are similar to pseudo-classes, but are preceded by double colons (::) and allow
styling a specific part of an element, such as the first word, line, or adding content before/after.
Classic example with ::before and ::after:
Example with ::marker and ::placeholder
5. Combinators and multiple selectors
Combinators define relationships between HTML elements. Using the letters A and B, we can understand how elements are connected to each other:
| Name | Syntax | Selects |
|---|---|---|
| Multiple selectors | A, B | All A and/or B elements |
| Descendant | A B | B elements inside A |
| Direct child | A > B | B elements directly under A |
| Adjacent sibling | A + B | B element immediately after A |
| General sibling | A ~ B | All B elements that follow A |
☞ There are some elements like a, button, input and textarea
that have a default focus state. We can extend this state to any HTML5 element using tabindex or
contenteditable (with caution). The default focus style (dotted outline) comes from the browser's
stylesheet and can be customized with CSS, but it must be kept or replaced carefully to maintain
accessibility.
🧠 Best practice recommendations
- Use pseudo-elements for decoration, not for essential content.
- Respect the LVHA order for links:
:link → :visited → :hover → :active. - Do not completely remove
outlineon focus — replace it with something visible. - Test combinators in real contexts to understand DOM relationships.
- Use
:is()and:where()for efficient grouping of selectors. - Explore
:has()for conditional selections (supported in most modern browsers).
