Go beyond basic selectors. Use combinators, attribute selectors, pseudo-classes, and more to target elements with surgical precision.
Combinators
Use combinators to target elements based on their relationship to
others:
Descendant, Child, Sibling,
Adjacent.
/* Descendant - all p inside .container */
.container p { color: blue; }
/* Child - only direct children */
.container > p { color: red; }
/* Adjacent Sibling - p immediately after h2 */
h2 + p { font-weight: bold; }
/* General Sibling - all p after h2 */
h2 ~ p { margin-top: 1rem; }
Try it - Combinator examples
Descendant - styled
Nested descendant - also styled
Descendant - styled
Direct child - red
Nested - not red
Attribute Selectors
Target elements based on attributes. Match exact values, partial strings, prefixes, suffixes.
/* Has attribute */
[disabled] { opacity: 0.5; }
/* Exact value */
input[type="text"] { border: 1px solid blue; }
/* Contains word */
[class~="active"] { font-weight: bold; }
/* Starts with */
a[href^="https"] { color: green; }
/* Ends with */
a[href$=".pdf"] { background: red; }
/* Contains substring */
a[href*="example"] { color: purple; }
Try it - Attribute selectors
Pseudo-Elements
Style specific parts of elements: ::before,
::after, ::first-line,
::first-letter, ::selection.
/* Add content before element */
.icon::before {
content: "→ ";
color: var(--primary);
font-weight: bold;
}
/* Add content after element */
.note::after {
content: " [Note]";
color: gray;
}
/* First letter - drop cap */
p::first-letter {
font-size: 2em;
font-weight: bold;
color: var(--primary);
}
/* First line styling */
p::first-line {
font-weight: bold;
}
Try it - Pseudo-elements in action
This is a note
The first line of this paragraph is styled differently. Notice how only the first line gets the special treatment.
This paragraph has a drop cap on the first letter. Try selecting and highlighting the text to see the selection color.
Specificity
CSS applies based on specificity. Inline styles (1000) beat IDs (100) beat classes (10) beat elements (1). Chain selectors to increase specificity.
/* Specificity = 1 (element) */
p { color: black; }
/* Specificity = 10 (class) - WINS */
.text { color: blue; }
/* Specificity = 100 (ID) - WINS OVER CLASS */
#intro { color: red; }
/* Specificity = 11 (1 element + 1 class) */
p.highlight { color: yellow; }
/* Specificity = 101 (1 ID + 1 element) - WINS */
#header p { color: green; }
/* Avoid: Specificity = 1000 (inline) - NEVER USE */
<p style="color: purple;">Don't do this</p>
Try it - Specificity in action
Element selector (1)
Class selector (10)
ID selector (100)
Element + Class (11)
CSS applies the most specific rule. Higher specificity wins.
Selector Specificity Chart
| Selector | Specificity | Example |
|---|---|---|
| Element | 1 | p, div |
| Class | 10 | .button, [type="text"] |
| ID | 100 | #header |
| Inline Style | 1000 | style="color: red;" |
| !important | Highest | color: red !important; |
| Element + Class | 11 | p.highlight |
| Descendant Chain | Sum of all | .header .nav .link = 30 |
Summary
-
Combinators target elements based on
relationships:
>,+,~. -
Attribute selectors match elements by attributes:
[attr],[attr="value"]. - ::before and ::after add content and styling to elements.
- Specificity determines which CSS rule applies when conflicts occur.
- Chain selectors to increase specificity when needed.
- Avoid !important - it breaks cascading and causes issues.
- Combine techniques for powerful, precise targeting.