CSS DOM Selectors
Basic Selectors
Element Selector
// Select all <p> elements
document.getElementsByTagName('p');
document.querySelectorAll('p');
p { /* styles */ }
Class Selector
// Select elements with class="highlight"
document.getElementsByClassName('highlight');
document.querySelectorAll('.highlight');
.highlight { /* styles */ }
ID Selector
// Select element with id="header"
document.getElementById('header');
document.querySelector('#header');
#header { /* styles */ }
Combination Selectors
Descendant Selector
// Select all <p> elements inside <div>
document.querySelectorAll('div p');
div p { /* styles */ }
Child Selector
// Select all direct <p> children of <div>
document.querySelectorAll('div > p');
div > p { /* styles */ }
Adjacent Sibling
// Select <p> immediately after <h2>
document.querySelectorAll('h2 + p');
h2 + p { /* styles */ }
General Sibling
// Select all <p> elements that follow <h2>
document.querySelectorAll('h2 ~ p');
h2 ~ p { /* styles */ }
Attribute Selectors
Has Attribute
// Select elements with 'data-type' attribute
document.querySelectorAll('[data-type]');
[data-type] { /* styles */ }
Exact Attribute Value
// Select elements with type="text"
document.querySelectorAll('[type="text"]');
[type="text"] { /* styles */ }
Contains Word
// Select elements with class containing "btn"
document.querySelectorAll('[class~="btn"]');
[class~="btn"] { /* styles */ }
Starts With
// Select elements with href starting with "https"
document.querySelectorAll('[href^="https"]');
[href^="https"] { /* styles */ }
Ends With
// Select elements with src ending in ".pdf"
document.querySelectorAll('[src$=".pdf"]');
[src$=".pdf"] { /* styles */ }
Contains Substring
// Select elements with href containing "example"
document.querySelectorAll('[href*="example"]');
[href*="example"] { /* styles */ }
Pseudo-classes
State Pseudo-classes
// Select all checked inputs
document.querySelectorAll('input:checked');
input:checked { /* styles */ }
Position Pseudo-classes
// Select first paragraph
document.querySelector('p:first-child');
// Select last paragraph
document.querySelector('p:last-child');
// Select specific numbered element
document.querySelector('p:nth-child(2)');
p:first-child { /* styles */ }
p:last-child { /* styles */ }
p:nth-child(2) { /* styles */ }
Pattern Pseudo-classes
// Select even paragraphs
document.querySelectorAll('p:nth-child(even)');
// Select odd paragraphs
document.querySelectorAll('p:nth-child(odd)');
p:nth-child(even) { /* styles */ }
p:nth-child(odd) { /* styles */ }
Multiple Selectors
// Select multiple elements
document.querySelectorAll('h1, .highlight, #header');
h1, .highlight, #header { /* styles */ }
CSS Advanced Selectors: :has
, :not
, :is
, :where
These powerful CSS pseudo-class selectors help simplify styling logic and improve maintainability.
:has()
– Parent Selector (CSS Relational Selector)
💡 Selects an element that contains a specific child element.
✅ Example: Style a <div>
that has an <img>
inside
div:has(img) {
border: 2px solid blue;
}
📌 Effect:
- Adds a blue border only to
<div>
elements that contain an<img>
.
🚀 More Examples:
/* Highlight a <label> if its <input> is checked */
label:has(input:checked) {
color: green;
font-weight: bold;
}
/* Style a card only if it has a button */
.card:has(button) {
background-color: lightgray;
}
:not()
– Exclude Elements
💡 Selects elements that do NOT match a certain selector.
✅ Example: Select all <button>
elements except those with .disabled
button:not(.disabled) {
background-color: blue;
color: white;
}
📌 Effect:
- All enabled buttons get blue styling, but
.disabled
buttons stay unchanged.
🚀 More Examples:
/* Select all list items except the first one */
li:not(:first-child) {
margin-left: 10px;
}
/* Select all paragraphs except those inside a .container */
p:not(.container p) {
font-size: 16px;
}
:is()
– Grouping Selectors (Better Readability & Performance)
💡 Simplifies multiple selectors into one.
✅ Example: Apply same styles to <h1>
, <h2>
, and <h3>
:is(h1, h2, h3) {
color: red;
}
📌 Effect:
- All
<h1>
,<h2>
, and<h3>
elements will be red.
🚀 More Examples:
/* Apply padding to all input types except checkbox & radio */
:is(input, textarea):not([type="checkbox"], [type="radio"]) {
padding: 10px;
}
/* Style links differently inside nav */
nav :is(a, button) {
color: white;
font-weight: bold;
}
:where()
– Works Like :is()
, But Lower Specificity
💡 Same as :is()
, but without affecting specificity.
✅ Best for utility classes & overrides.
✅ Example: Style multiple elements without increasing specificity
:where(h1, h2, h3) {
margin: 0;
padding: 0;
}
📌 Effect:
- Works like
:is()
, but allows easier overriding later.
🚀 More Examples:
/* Form input styling with low specificity */
:where(input, select, textarea) {
font-size: 16px;
border-radius: 5px;
}
/* Navigation links with low specificity */
nav :where(a, button) {
text-decoration: none;
}
🔥 Summary Table
Selector | Purpose | Example |
---|---|---|
:has() | Selects parent if it contains a specific child | div:has(img) {} |
:not() | Excludes elements from selection | button:not(.disabled) {} |
:is() | Groups multiple selectors (affects specificity) | :is(h1, h2, h3) {} |
:where() | Groups selectors (low specificity) | :where(input, textarea) {} |
🚀 Best Practices
✔ Use :has()
for parent-child relationships (currently limited browser support).
✔ Use :not()
to exclude elements from styling.
✔ Use :is()
for cleaner selector grouping.
✔ Use :where()
for utility styles with low specificity.
Browser Support
- ✅
:not()
,:is()
,:where()
– Widely supported - ⚠️
:has()
– Supported in modern browsers (Chrome, Edge, Safari 15+), but not in Firefox (yet)
Best Practices
-
Use
querySelector
/querySelectorAll
for modern applications- More flexible and powerful than older methods
- Supports all CSS selector syntax
- Returns static NodeList (won't auto-update)
-
Performance Considerations
- ID selectors are fastest (#id)
- Class selectors are next fastest (.class)
- Complex selectors are slowest (div > p:nth-child(2))
-
Specificity Order (most to least specific)
- ID selectors (#id)
- Class selectors (.class)
- Element selectors (p)
-
Modern Usage Tips
- Prefer
querySelector
overgetElementById
for consistency - Use
closest()
for finding parent elements - Use
matches()
to test if element matches selector
element.closest('.container');
element.matches('.active'); - Prefer