Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Mastering CSS Logical Pseudo-Classes: :is, :where, :not, and :has

Tech May 8 3

The :is() pseudo-class function accepts a selector list and matches any element that can be selected by one of the selectors in that list. This reduces repetition when applying identical styles to different elements under various contexts.

/* Target navigation links in multiple regions without repetition */
:is(.site-header, .page-footer, .sidebar) a {
  text-decoration-thickness: 2px;
  text-underline-offset: 4px;
}

Unlike comma-separated selectors, :is() forgives invalid selectors in the list, continuing to match valid ones rather than invalidating the entire rule. Specificity calculates based on the most specific selector in the list.

The :where() pseudo-class functions identically to :is() in matching behavior but contributes zero specificity to the overall selector. This proves invaluable for reset stylesheets and library code where minimal specificity impact prevents unintentional overrides.

/* Apply zero-specificity base styles that are easily overridden */
:where(button, input[type="submit"], .cta-button) {
  padding: 0.75rem 1.5rem;
  border-radius: 0.375rem;
  cursor: pointer;
}

Developers can nest :where() to create complex conditional scopes without bloating specificity weights, making it ideal for theming systems where contextual overrides must remain lightweight.

The :not() negation pseudo-class excludes elements matching its selector argument. CSS Selectors Level 4 expanded this to accept complex selecter lists, enabling sophisticated filtering previously requiring multiple rules.

/* Select list items that are neither active nor disabled */
.menu-item:not(.is-active, [aria-disabled="true"]) {
  opacity: 0.8;
  transition: opacity 0.2s ease;
}

Note that :not() itself adds specificity equal to its argument. Chaining multiple negations or combining with high-specificity selectors can create brittle cascade dependencies, so reserve it for targeted exceptions rather than broad architectural patterns.

The :has() relational pseudo-class—often termed the "parent selector"—targets elements containing descendants that match its arguement. This eliminates previous limitations requiring JavaScript DOM traversal for parent-element styling.

/* Style cards differently when they contain media elements */
.card:has(> img, > video) {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

/* Highlight form groups with invalid inputs */
.form-group:has(input:invalid) {
  border-left: 3px solid #dc2626;
  padding-left: 1rem;
}

While :has() offers powerful document traversal capabilities, implementers should consider performance implications on large documents, as browsers evaluate these selectors against complete subtree structures. As of 2024, all modern browsers support these Level 4 selectors, though legacy environments require progressive enhancement strategies or polyfills for equivalent functionality.

Related Articles

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

SBUS Signal Analysis and Communication Implementation Using STM32 with Fus Remote Controller

Overview In a recent project, I utilized the SBUS protocol with the Fus remote controller to control a vehicle's basic operations, including movement, lights, and mode switching. This article is aimed...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.