Advanced Selectors and CSS Variables
Advanced CSS Selectors - Beyond the Basics
Once you've mastered basic selectors, advanced selectors unlock powerful techniques for writing more efficient, maintainable CSS. These selectors help you target elements with precision without adding extra classes to your HTML.
Attribute Selectors
Target elements based on their attributes:
/* Select inputs with type="email" */
input[type="email"] {
border-left: 4px solid #4CAF50;
}
/* Select links that start with https:// */
a[href^="https"] {
padding-left: 20px;
}
/* Select links that end with .pdf */
a[href$=".pdf"] {
background-image: url(pdf-icon.svg);
}
/* Select elements with data-* attributes */
[data-theme="dark"] {
background-color: #333;
color: #fff;
}
/* Select elements with a specific attribute (any value) */
[required] {
border-color: red;
}
Common Attribute Selector Patterns:
[attr] /* Has attribute */
[attr="value"] /* Exact match */
[attr^="value"] /* Starts with */
[attr$="value"] /* Ends with */
[attr*="value"] /* Contains */
[attr~="value"] /* Contains word */
[attr|="value"] /* Starts with word followed by hyphen */
Pseudo-classes - Element State
Select elements based on their state or position:
/* First child */
li:first-child {
font-weight: bold;
}
/* Last child */
li:last-child {
border-bottom: none;
}
/* Every other element */
li:nth-child(even) {
background-color: #f5f5f5;
}
/* Based on type (ignore non-li elements) */
li:nth-of-type(2n) {
background-color: #f5f5f5;
}
/* Elements with no children */
div:empty {
display: none;
}
/* Disabled form elements */
input:disabled {
opacity: 0.5;
cursor: not-allowed;
}
/* Form elements with invalid input */
input:invalid {
border-color: red;
}
/* Focus state (accessibility important!) */
button:focus {
outline: 2px solid blue;
}
Pseudo-elements - Create Virtual Elements
Create visual elements without adding HTML:
/* Add content before element */
.quote::before {
content: """;
font-size: 2em;
color: #999;
}
/* Add content after element */
.quote::after {
content: """;
font-size: 2em;
color: #999;
}
/* Style first line of text */
p::first-line {
font-weight: bold;
}
/* Style first letter */
p::first-letter {
font-size: 2em;
font-weight: bold;
}
/* Create highlighted text selection */
::selection {
background-color: #4CAF50;
color: white;
}
Real Example: Decorative Elements Without HTML
.card::before {
content: "";
position: absolute;
top: -10px;
left: 20px;
width: 30px;
height: 30px;
background-color: #4CAF50;
border-radius: 50%;
z-index: -1;
}
Combinators - Combining Selectors
Child Combinator (>)
/* Select only direct children */
.menu > li {
padding: 10px;
}
/* Not grandchildren */
.menu > li > a {
color: blue;
}
Adjacent Sibling Combinator (+)
/* Select element immediately after another */
h2 + p {
font-weight: bold; /* First paragraph after h2 */
}
General Sibling Combinator (~)
/* Select all siblings after another */
h2 ~ p {
margin-bottom: 20px; /* All paragraphs after h2 */
}
CSS Variables (Custom Properties)
Define reusable values that can be changed dynamically. This is one of the most powerful features in modern CSS:
:root {
/* Global variables available everywhere */
--primary-color: #4a9eff;
--secondary-color: #48bb78;
--spacing-unit: 8px;
--border-radius: 4px;
--font-stack: 'Roboto', sans-serif;
}
/* Use variables with var() */
button {
background-color: var(--primary-color);
padding: var(--spacing-unit) * 3; /* Cannot do math directly */
border-radius: var(--border-radius);
}
a {
color: var(--primary-color);
}
.card {
border-radius: var(--border-radius);
}
Scoped Variables
Variables can be scoped to specific selectors:
/* Dark theme variables */
[data-theme="dark"] {
--background-color: #1a1a1a;
--text-color: #e9ecef;
--border-color: #4a5568;
}
/* Light theme variables */
[data-theme="light"] {
--background-color: #ffffff;
--text-color: #333;
--border-color: #ddd;
}
/* Use the same CSS with different variables */
body {
background-color: var(--background-color);
color: var(--text-color);
border: 1px solid var(--border-color);
}
Variable Fallbacks
color: var(--custom-color, blue); /* Use blue if variable not defined */
color: var(--custom-color, var(--fallback-color, black)); /* Multiple fallbacks */
Dynamic Variables with JavaScript
/* CSS */
:root {
--primary-color: #4a9eff;
}
/* JavaScript - change variables at runtime */
document.documentElement.style.setProperty("--primary-color", "#ff6b6b");
/* This changes the color everywhere it's used! */
CSS Containment - Performance Optimization
Tell the browser which elements are independent to improve performance:
.card {
contain: layout style paint; /* This element doesn't affect others */
}
.widget {
contain: strict; /* Maximum isolation and performance */
}
BEM Naming Convention
A popular naming system for writing maintainable CSS:
/* Block - main component */
.card { }
/* Element - part of the block */
.card__header { }
.card__body { }
.card__footer { }
/* Modifier - variation */
.card--featured { }
.card--dark { }
.card__header--sticky { }
Real Example:
.button {
padding: 10px 20px;
background-color: blue;
}
.button--primary {
background-color: #4a9eff;
}
.button--secondary {
background-color: #48bb78;
}
.button__icon {
margin-right: 10px;
}
Efficient CSS Architecture
SMACSS (Scalable and Modular Architecture)
Organize CSS into categories:
- Base: Element defaults (p, a, button)
- Layout: Page structure (.sidebar, .main)
- Module: Reusable components (.card, .button)
- State: Dynamic states (.is-active, .is-hidden)
- Theme: Color and styling variations
CSS Performance Tips
- Avoid deep nesting: Selectors deeper than 3 levels are slow
- Use classes, not IDs: Classes are reusable and have lower specificity
- Minimize specificity wars: Use well-organized class systems
- Use shorthand properties: margin: 10px 20px is smaller than separate declarations
- Remove unused CSS: Tools like PurgeCSS help
- Minify your CSS: Remove whitespace in production
- Load CSS before JS: CSS should block rendering, JS shouldn't
Summary
You now understand:
- Advanced selectors for precise element targeting
- Pseudo-classes and pseudo-elements for state and virtual content
- CSS variables for dynamic, reusable values
- CSS containment for performance
- BEM and SMACSS naming conventions
- CSS architecture best practices