CSS Advanced

Advanced Selectors and CSS Variables

Imran Nadwi
118 views 45 min read

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