CSS selector types, combinators, pseudo-classes, pseudo-elements, and specificity reference
Selects all elements
* { box-sizing: border-box; }Selects all elements of a given type
p { color: gray; }
h1 { font-size: 2rem; }Selects elements with a specific class
.btn { padding: 0.5rem 1rem; }
.btn.primary { background: blue; }Selects a single element by unique ID
#header { position: sticky; top: 0; }Selects elements based on attribute presence or value
[disabled] { opacity: 0.5; }
[type="text"] { border: 1px solid #ccc; }
[href^="https"] { color: green; }
[src$=".png"] { border: 1px solid red; }
[class*="icon"] { display: inline-flex; }Selects all matching descendants
nav a { text-decoration: none; }
/* All <a> inside <nav> */Selects direct children only
ul > li { list-style: disc; }
/* Only direct <li> children of <ul> */Selects the immediately following sibling
h2 + p { margin-top: 0; }
/* First <p> right after <h2> */Selects all following siblings
h2 ~ p { color: gray; }
/* All <p> after a <h2> at same level */Select elements based on their position in the DOM
li:first-child { font-weight: bold; }
li:last-child { border-bottom: none; }
li:nth-child(2n) { background: #f5f5f5; }
li:nth-child(odd) { background: #fff; }
p:only-child { margin: 0; }React to user interaction states
a:hover { color: blue; }
button:focus { outline: 2px solid blue; }
input:active { border-color: blue; }
a:visited { color: purple; }Target form elements by their state
input:checked { accent-color: blue; }
input:disabled { opacity: 0.5; }
input:required { border-color: red; }
input:valid { border-color: green; }
input:invalid { border-color: red; }
input:placeholder-shown { border-style: dashed; }Logical pseudo-classes for advanced filtering
a:not(.btn) { text-decoration: underline; }
:is(h1, h2, h3) { font-weight: bold; }
:where(header, main, footer) p { line-height: 1.6; }Parent selector — select based on containing a child
/* Card with an image gets extra padding */
.card:has(img) { padding-top: 0; }
/* Form with invalid input */
form:has(input:invalid) .submit-btn { opacity: 0.5; }Insert content before or after element content
.required::after {
content: " *";
color: red;
}
.icon::before {
content: url(icon.svg);
margin-right: 0.5rem;
}Style input placeholder text
input::placeholder {
color: #9ca3af;
font-style: italic;
}Style text highlighted by the user
::selection {
background: #3b82f6;
color: white;
}Style the first line or letter of a block
p::first-letter {
font-size: 2em;
float: left;
line-height: 1;
}
p::first-line { font-weight: bold; }Style elements differently based on color-scheme preference
/* Using prefers-color-scheme */
@media (prefers-color-scheme: dark) {
body { background: #1a1a1a; color: #f5f5f5; }
}
/* Using a data attribute (JS-toggled) */
[data-theme="dark"] .card {
background: #1e293b;
color: #e2e8f0;
}Show focus ring only for keyboard navigation, not mouse clicks
/* Remove default outline for mouse users */
button:focus:not(:focus-visible) {
outline: none;
}
/* Show clear outline for keyboard users */
button:focus-visible {
outline: 2px solid #3b82f6;
outline-offset: 2px;
}Alternate row colors in a table
tr:nth-child(even) {
background-color: #f9fafb;
}
tr:nth-child(odd) {
background-color: #ffffff;
}
tr:hover {
background-color: #eff6ff;
}Style an element differently when it has no children
.list:empty::after {
content: "No items yet.";
color: #9ca3af;
font-style: italic;
}
/* Or hide it entirely */
.notification-badge:empty {
display: none;
}Keep specificity low — prefer classes over IDs to avoid specificity wars
Use :is() to deduplicate long selector lists without raising specificity
Prefer :focus-visible over :focus to avoid removing outlines for mouse users
Use :has() as a parent selector — widely supported since 2023
Avoid deep descendant selectors — they are slow and tightly couple HTML structure to CSS