Advanced Selectors
Advanced CSS selectors target elements by their relationships and state instead of just their class or tag, using combinators like > and ~ , attribute selectors such as [type="email"] , and pseudo-classes like :nth-child() to style markup precisely without extra classes.
Part of the free HTML & CSS course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
What You'll Learn
💡 Think of It Like This
Basic selectors are like addressing a letter to "John". Advanced selectors are like saying "the third John who lives on Main Street, but only when he's at home." They give you surgical precision — you can target any element based on its state, position, attributes, or relationship to other elements.
1. Pseudo-classes — Targeting Element States
Pseudo-classes select elements based on their current state — whether they're hovered, focused, the first child, or match a pattern.
Category
Selector
What It Targets
Interactive
:hover
Mouse is over element
:focus
Element has keyboard focus
:active
Element is being clicked
:visited
Link has been visited
Position
:first-child
First child of parent
:last-child
Last child of parent
:nth-child(n)
Nth child (odd, even, 3n, 2n+1)
:not(selector)
Everything except the selector
Form
:checked
Checked checkbox/radio
:valid / :invalid
Form validation state
:disabled
Disabled form element
2. Pseudo-elements — Virtual Content
Pseudo-elements create virtual elements that don't exist in the HTML. They're perfect for decorative content, icons, and styling parts of text.
Pseudo-element
What It Does
::before
Inserts content before element (requires content )
::after
Inserts content after element (requires content )
::first-letter
Styles only the first letter of text
::first-line
Styles only the first line of a paragraph
::selection
Styles highlighted/selected text
3. Combinators — Relationship Selectors
Combinators target elements based on their relationship to other elements in the DOM tree.
Combinator
Syntax
Targets
Descendant
div p
All p elements inside div (any depth)
Child
div > p
Only direct child p elements of div
Adjacent sibling
h2 + p
First p immediately after h2
General sibling
h2 ~ p
All p elements after h2 (same parent)
4. Attribute Selectors
Target elements based on their HTML attributes — incredibly useful for styling links, inputs, and data attributes.
Matches
Example Use
[href]
Has the attribute
Any element with href
[type="email"]
Exact match
Email inputs only
[href*="youtube"]
Contains substring
Links containing "youtube"
[href^="https"]
Starts with
Secure links
[href$=".pdf"]
Ends with
PDF download links
⚠️ Common Mistakes
- Confusing : and :: — Single colon :hover is a pseudo-class (state). Double colon ::before is a pseudo-element (virtual content).
- Forgetting content for ::before/::after — These pseudo-elements require the content property, even if it's empty: content: "";
- Over-specific selectors — div.container ul li a:hover is overly specific and fragile. Keep selectors as short as possible.
- Using :nth-child when you mean :nth-of-type — :nth-child(2) targets the 2nd child regardless of type. :nth-of-type(2) targets the 2nd element of that specific type.
🎉 Lesson Complete
You now have surgical precision when targeting CSS elements:
- ✅ Pseudo-classes target states: :hover, :focus, :nth-child, :not()
- ✅ Pseudo-elements create virtual content: ::before, ::after, ::first-letter
- ✅ Combinators target relationships: child (>), sibling (+, ~)
- ✅ Attribute selectors target by attribute: [href$=".pdf"], [type="email"]
Practice quiz
What is the difference between a single colon and a double colon, as in :hover vs ::before?
- They are interchangeable
- Double colons are invalid CSS
- A single colon marks a pseudo-class (state); a double colon marks a pseudo-element (virtual content)
- Single colons only work on links
Answer: A single colon marks a pseudo-class (state); a double colon marks a pseudo-element (virtual content). Pseudo-classes (:hover, :focus) target a state; pseudo-elements (::before, ::after) create virtual content.
What does the child combinator div > p select?
- Only p elements that are direct children of div
- All p elements anywhere inside div
- The first p after a div
- All p elements that follow div
Answer: Only p elements that are direct children of div. The > combinator matches only direct (immediate) child p elements of div, not deeper descendants.
What does the descendant combinator div p (with a space) select?
- Only direct child p elements
- The p immediately after div
- div elements inside p
- All p elements inside div at any depth
Answer: All p elements inside div at any depth. A space is the descendant combinator: it matches all p inside div regardless of nesting depth.
What does the adjacent sibling combinator h2 + p select?
- All p siblings after h2
- The first p immediately after an h2 (same parent)
- Every p inside h2
- The p before h2
Answer: The first p immediately after an h2 (same parent). h2 + p matches the single p that immediately follows an h2 and shares its parent.
What does the general sibling combinator h2 ~ p select?
- All p elements after h2 that share the same parent
- Only the first p after h2
- p elements inside h2
- The p directly before h2
Answer: All p elements after h2 that share the same parent. h2 ~ p matches every p that comes after an h2 and has the same parent.
Which attribute selector matches links whose href ends with .pdf?
$= matches values that end with the substring, so [href$=".pdf"] targets PDF links.
Which attribute selector matches links whose href starts with https?
^= matches values that start with the substring, so [href^="https"] targets secure links.
Which attribute selector matches an href that contains the substring 'youtube' anywhere?
*= matches values containing the substring anywhere within them.
What must you always include for a ::before or ::after pseudo-element to render?
- A width property
- The content property (even if empty: content: "")
- A position value
- A z-index
Answer: The content property (even if empty: content: ""). ::before and ::after require the content property; without it they do not render at all.
What is the difference between :nth-child(2) and :nth-of-type(2)?
- They are identical
- :nth-of-type counts from the end
- :nth-child(2) targets the 2nd child of any type; :nth-of-type(2) targets the 2nd element of that specific type
- :nth-child only works on lists
Answer: :nth-child(2) targets the 2nd child of any type; :nth-of-type(2) targets the 2nd element of that specific type. :nth-child counts among all siblings; :nth-of-type counts only siblings of the same element type.
Continue this course
- Previous: CSS Animations & Transitions
- Next: CSS Transforms & 3D