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
.disabledbuttons 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/querySelectorAllfor 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
querySelectorovergetElementByIdfor consistency - Use
closest()for finding parent elements - Use
matches()to test if element matches selector
element.closest('.container');
element.matches('.active'); - Prefer