Introduction: What are CSS Selectors?
CSS selectors are patterns used to select and style HTML elements. They are the bridge between your HTML content and CSS styling, allowing you to precisely target specific elements or groups of elements. Mastering selectors is crucial for efficient styling, reducing code redundancy, and creating maintainable stylesheets.
Basic Selectors
| Selector | Syntax | Description | Example |
|---|---|---|---|
| Universal | * | Selects all elements | * { margin: 0; } |
| Type/Element | element | Selects all instances of specified element | p { color: blue; } |
| Class | .classname | Selects elements with specified class | .highlight { background: yellow; } |
| ID | #idname | Selects element with specified ID | #header { position: fixed; } |
| Group | selector1, selector2 | Applies same style to multiple selectors | h1, h2, h3 { font-family: Arial; } |
Combinator Selectors
| Selector | Syntax | Description | Example |
|---|---|---|---|
| Descendant | ancestor descendant | Selects all descendants | div p { line-height: 1.5; } |
| Child | parent > child | Selects direct children only | ul > li { list-style: none; } |
| Adjacent Sibling | element + sibling | Selects element immediately after | h2 + p { font-weight: bold; } |
| General Sibling | element ~ siblings | Selects all siblings after | h2 ~ p { color: gray; } |
Attribute Selectors
| Selector | Syntax | Description | Example |
|---|---|---|---|
| Has Attribute | [attr] | Elements with specified attribute | [disabled] { opacity: 0.5; } |
| Exact Match | [attr="value"] | Attribute equals value | [type="checkbox"] { margin: 0; } |
| Contains Word | [attr~="value"] | Attribute contains word | [class~="btn"] { padding: 5px; } |
| Begins With | [attr^="value"] | Attribute begins with value | [href^="https"] { color: green; } |
| Ends With | [attr$="value"] | Attribute ends with value | [src$=".jpg"] { border: 1px solid; } |
| Contains Substring | [attr*="value"] | Attribute contains substring | [class*="col"] { float: left; } |
| Hyphen-Separated | `[attr | =”value”]` | Attribute starts with value followed by hyphen |
| Case Insensitive | [attr="value" i] | Case-insensitive matching | [type="text" i] { border: none; } |
Pseudo-Class Selectors
Link & User Interaction
| Selector | Description | Example |
|---|---|---|
:link | Unvisited links | a:link { color: blue; } |
:visited | Visited links | a:visited { color: purple; } |
:hover | Element being hovered | button:hover { background: lightgray; } |
:active | Element being activated | a:active { color: red; } |
:focus | Element with focus | input:focus { border-color: blue; } |
:focus-within | Element containing focused element | form:focus-within { background: #f9f9f9; } |
:focus-visible | Element with keyboard focus | button:focus-visible { outline: 2px solid blue; } |
Form States
| Selector | Description | Example |
|---|---|---|
:checked | Checked inputs | input:checked + label { font-weight: bold; } |
:disabled | Disabled elements | button:disabled { cursor: not-allowed; } |
:enabled | Enabled elements | input:enabled { background: white; } |
:required | Required inputs | input:required { border-color: red; } |
:optional | Optional inputs | input:optional { border-color: gray; } |
:valid | Valid inputs | input:valid { border-color: green; } |
:invalid | Invalid inputs | input:invalid { border-color: red; } |
:in-range | Input value within range | input:in-range { color: green; } |
:out-of-range | Input value outside range | input:out-of-range { color: red; } |
:placeholder-shown | Input showing placeholder text | input:placeholder-shown { font-style: italic; } |
Structural Pseudo-Classes
| Selector | Description | Example |
|---|---|---|
:root | Document root element | :root { --main-color: blue; } |
:first-child | First child of parent | li:first-child { font-weight: bold; } |
:last-child | Last child of parent | li:last-child { border-bottom: none; } |
:nth-child(n) | Matches nth child | tr:nth-child(odd) { background: #f2f2f2; } |
:nth-last-child(n) | Matches nth child from end | li:nth-last-child(2) { color: red; } |
:only-child | Only child of parent | li:only-child { list-style: none; } |
:first-of-type | First element of type | p:first-of-type { font-size: larger; } |
:last-of-type | Last element of type | img:last-of-type { margin-bottom: 0; } |
:nth-of-type(n) | Matches nth element of type | div:nth-of-type(3n) { margin-right: 0; } |
:nth-last-of-type(n) | Matches nth element of type from end | p:nth-last-of-type(2) { font-style: italic; } |
:only-of-type | Only element of type | h1:only-of-type { text-align: center; } |
:empty | Element with no children | p:empty { display: none; } |
Negation & Matching
| Selector | Description | Example |
|---|---|---|
:not(selector) | Elements not matching selector | input:not([type="checkbox"]) { width: 100%; } |
:is(selectors) | Matches any of the selectors | :is(h1, h2, h3) { color: blue; } |
:where(selectors) | Like :is() but with 0 specificity | :where(section, article) p { line-height: 1.5; } |
:has(selector) | Elements containing matching elements | div:has(> img) { padding: 10px; } |
Pseudo-Element Selectors
| Selector | Description | Example |
|---|---|---|
::before | Creates content before element | p::before { content: "»"; color: red; } |
::after | Creates content after element | a::after { content: " ↗"; font-size: small; } |
::first-line | Styles first line of text | p::first-line { font-weight: bold; } |
::first-letter | Styles first letter of text | p::first-letter { font-size: 2em; } |
::selection | Styles selected text | ::selection { background: yellow; color: black; } |
::placeholder | Styles input placeholder text | input::placeholder { color: #999; } |
::marker | Styles list item markers | li::marker { color: red; } |
::backdrop | Styles backdrop of full-screen elements | dialog::backdrop { background: rgba(0,0,0,0.5); } |
Specificity & Cascade
Specificity Hierarchy (lowest to highest)
- Universal selectors (
*) – 0,0,0,0 - Element/type selectors (
div,p) – 0,0,0,1 - Class selectors (
.class), attribute selectors ([attr]), pseudo-classes (:hover) – 0,0,1,0 - ID selectors (
#id) – 0,1,0,0 - Inline styles (
style="...") – 1,0,0,0 - !important (overrides all) – Not counted in specificity, but takes precedence
Specificity Calculation Examples
| Selector | Calculation | Specificity Value |
|---|---|---|
p | 1 element | 0,0,0,1 |
p.intro | 1 element, 1 class | 0,0,1,1 |
#nav a | 1 ID, 1 element | 0,1,0,1 |
.header .nav li a:hover | 2 classes, 2 elements, 1 pseudo-class | 0,0,3,2 |
[type="text"] | 1 attribute | 0,0,1,0 |
button.btn:not(.large) | 1 element, 2 classes, 1 pseudo-class | 0,0,3,1 |
Common Challenges & Solutions
Managing Specificity
Challenge: CSS conflicts due to high specificity selectors
Solutions:
- Use classes instead of IDs when possible
- Avoid deeply nested selectors
- Use BEM or other naming conventions
- Consider CSS custom properties for shared values
- Use
:where()to reduce specificity
Targeting Specific Elements
Challenge: Difficulty targeting elements in complex structures
Solutions:
- Use child combinators (
>) instead of descendant selectors - Leverage attribute selectors for unique targeting
- Use
:nth-child()or:nth-of-type()for positional selection - Apply the
:not()pseudo-class to exclude elements - Use the
:has()relational pseudo-class (with appropriate browser support checking)
Browser Compatibility
Challenge: Newer selectors not supported in all browsers
Solutions:
- Check compatibility on Can I Use
- Provide fallbacks for critical styling
- Use feature detection when necessary
- Consider using polyfills for essential features
- Progressive enhancement: use basic selectors first, enhance with advanced ones
Best Practices & Tips
- Prefer classes for styling: They provide good reusability without excessive specificity
- Keep selectors simple: Aim for 2-3 levels deep maximum for better performance
- Use semantic selectors: Target what an element is, not what it looks like
- Avoid using ID selectors for styling: Reserve them for JavaScript hooks and anchors
- Leverage the cascade: Use inheritance when appropriate instead of repeating styles
- Think mobile-first: Structure selectors to prioritize mobile styling first
- Comment complex selectors: Explain why a complicated selector is necessary
- Use selector performance tools: Analyze and optimize selector efficiency
- Organize selectors logically: Group related selectors together in your stylesheet
- Test across browsers: Verify selectors work across your supported browser range
Resources for Further Learning
- MDN Web Docs: CSS Selectors
- CSS-Tricks: The Skinny on CSS Attribute Selectors
- W3Schools: CSS Selector Reference
- Learn CSS Selectors – Interactive game
- CSS Diner – Practice CSS selectors
- Selectors Explained – Translates CSS selectors to plain English
- CSS Specificity Calculator
- Can I Use – Browser compatibility checker
Interactive Tools
- CSS Selector Tester
- RegExr – Helpful for complex attribute selectors
- Selectors Level 4 Playground
- CSS Specificity Graph Generator
This cheatsheet covers all essential CSS selectors, providing a comprehensive reference for styling web pages with precision and efficiency.
