Click any selector to expand the explanation and examples.
π― Basic Selectors
element, .class, #id, * basics
p { } /* All paragraphs */
.card { } /* Class */
#header { } /* ID */
* { } /* Everything */
/* Combine /
p.intro { } / Paragraphs with class βintroβ /
div.card.active { } / div with both classes */
π Combinators
A B β descendant combinator
/* Any link inside nav, no matter how deep */
nav a { color: blue; }
/* Any span inside .card */
.card span { font-weight: bold; }
A > B β direct child combinator
/* Only direct li children of ul */
ul > li { list-style: none; }
/* Direct paragraphs in .content, not nested ones */
.content > p { margin-bottom: 1em; }
A + B β adjacent sibling combinator
/* Paragraph right after an h2 */
h2 + p { font-size: 1.2em; }
/* Input right after a label */
label + input { margin-left: 0.5em; }
A ~ B β general sibling combinator
/* All paragraphs after an h2 (same parent) */
h2 ~ p { color: gray; }
π Attribute Selectors
[attr], [attr=val], [attr*=val] attribute
[href] { } /* Has href attribute */
[type="text"] { } /* Exact match */
[class~="card"] { } /* Contains word "card" */
[href^="https"] { } /* Starts with "https" */
[href$=".pdf"] { } /* Ends with ".pdf" */
[href*="example"] { } /* Contains "example" */
[data-theme="dark" i] { } /* Case-insensitive match */
/* Practical examples */
a[href^="http"] { } /* External links */
a[href$=".pdf"]::after { /* PDF icon after PDF links */
content: " π";
}
input[type="email"] { } /* Email inputs */
[data-active="true"] { } /* Custom data attributes */
π Pseudo-Classes
:hover, :focus, :active state
a:hover { color: red; }
a:active { color: darkred; } /* While clicking */
/* Focus styles (accessibility!) /
input:focus { outline: 2px solid blue; }
button:focus-visible { outline: 2px solid blue; }
/ focus-visible = only keyboard focus, not mouse clicks */
:disabled { opacity: 0.5; }
:enabled { }
:checked { } /* Checked checkboxes/radios */
:required { border-color: red; }
:valid { border-color: green; }
:invalid { border-color: red; }
::placeholder { color: gray; }
:first-child, :last-child, :nth-child() structural
li:first-child { }
li:last-child { }
li:nth-child(2) { } /* Second item */
li:nth-child(odd) { } /* 1st, 3rd, 5th... */
li:nth-child(even) { } /* 2nd, 4th, 6th... */
li:nth-child(3n) { } /* Every 3rd (3, 6, 9...) */
li:nth-child(3n+1) { } /* 1st, 4th, 7th... */
li:nth-last-child(2) { } /* 2nd from end */
li:only-child { } /* Only child of parent */
/* Type variants (only count same element type) */
p:first-of-type { }
p:last-of-type { }
p:nth-of-type(2) { }
/* Practical: zebra stripes */
tr:nth-child(even) { background: #f5f5f5; }
/* Remove border from last item */
li:last-child { border-bottom: none; }
:not() β negation logic
/* All inputs except submit buttons */
input:not([type="submit"]) { border: 1px solid gray; }
/* All links except those with class βnavβ */
a:not(.nav) { text-decoration: underline; }
/* Can chain */
li:not(:first-child):not(:last-child) { }
:is() and :where() β grouping modern
/* Without :is() β repetitive */
header a, nav a, footer a { color: blue; }
/* With :is() β clean */
:is(header, nav, footer) a { color: blue; }
/* Nested */
.card :is(h1, h2, h3) { margin-top: 0; }
/* :where() is the same but with 0 specificity /
:where(header, nav, footer) a { color: blue; }
/ Easy to override because specificity is 0 */
:has() β parent selector modern
/* Card that contains an image */
.card:has(img) { padding: 0; }
/* Form with invalid input */
form:has(:invalid) { border: 2px solid red; }
/* Section that has an h2 */
section:has(> h2) { padding-top: 2em; }
/* Label when its input is focused */
label:has(+ input:focus) { color: blue; }
/* Page with dark mode toggle checked */
body:has(#dark-mode:checked) { background: #1a1a1a; }
β¨ Pseudo-Elements
::before, ::after pseudo
/* Add content before/after an element */
.required::after {
content: " *";
color: red;
}
/* Decorative elements */
.quote::before {
content: """;
font-size: 3em;
color: gray;
}
/* Clearfix */
.container::after {
content: "";
display: table;
clear: both;
}
::before and ::after require the content property (even if empty).
::first-line, ::first-letter, ::selection pseudo
/* Style first line of a paragraph */
p::first-line { font-weight: bold; }
/* Drop cap */
p::first-letter {
font-size: 3em;
float: left;
line-height: 1;
margin-right: 0.1em;
}
/* Custom text selection color */
::selection {
background: #3b82f6;
color: white;
}
/* Style placeholder text */
input::placeholder { color: #9ca3af; }
π Specificity Quick Reference
How specificity works reference
* β (0, 0, 0) p β (0, 0, 1) p.intro β (0, 1, 1) #header β (1, 0, 0) #header .nav li β (1, 1, 1) #header .nav li.active β (1, 2, 1) style="..." β wins over everything !important β wins over inline stylesHigher specificity wins. If equal, the last rule wins.
:is() takes the specificity of its most specific argument. :where() always has 0 specificity.