Advertisement

Content-Aware Cards

| by Vladimir | 2 min read | code by Zach Handing
A11y Ready Intermediate

See the Pen Content-Aware Cards.

Tech & Dependencies

HTML SCSS JavaScript
bootstrap

Features

  • CSS :has()
  • Dynamic Layout
  • DOM Manipulation

Browser Support

Chrome 105+ Edge 105+ Firefox 121+ Safari 15.4+

Core

This is a Content-Aware Bootstrap Card. It uses the structural :has() pseudo-class to dynamically alter its internal layout, background, and typography based solely on the presence of an image node. Its function is to provide an adaptable, self-managing container that eliminates the need for redundant state-tracking classes in your JavaScript logic.

Specs

  • Weight: ~3 KB (HTML/CSS/JS). Relies on Bootstrap custom properties for button styling.
  • Performance: High. State reactions are natively handled by the CSS engine, bypassing expensive JavaScript layout recalculations.
  • Theming / Customization: Governed by SCSS variables ($spacing, $background) and structural geometry.
  • Responsiveness: Fluid grid controlled by flex-basis breakpoints scaling from 1 to 4 columns.
  • Graceful Degradation: [!] In older browsers without :has() support, cards will render their content but fail to apply the specific empty-state typography and layout shifts, requiring traditional utility classes to fix visual inconsistencies.

Anatomy

  • HTML: A semantic <section> wrapper containing multiple card <div> elements. Cards hold a mix of <img>, text nodes (<h2>, <p>), and CTA buttons.
  • CSS (SCSS): The architectural core. Flexbox handles the grid structure. The defining logic lives within the &:has(img) and &:not(:has(img)) blocks, which dictate spatial distribution based on the DOM tree.
  • JS: A minimal operational trigger. An event listener attached to the .btn-close button simply injects or removes the <img> element from the DOM.

Logic

The architectural strength of this snippet is the complete decoupling of state logic from JavaScript.

div {
  // if image does not exist
  &:not(:has(img)) {
    padding-top: $spacing;
    justify-content: center;
    background: repeating-linear-gradient(-45deg, darken($background, 7.5%), $background 30px);
    
    h2 { font-size: 2.5rem; }
    
    .btn-close {
      transform: rotate(45deg);
    }
  }
}

Instead of JavaScript toggling CSS classes (.card--no-image), the script strictly handles data operations (adding/removing the node). The CSS engine watches the DOM in real-time. When the <img> is removed, CSS instantly applies the fallback architecture — injecting a patterned gradient, centering the text, scaling the typography, and rotating the button into a ‘+’. The component acts as a reactive state machine.

Feel

Autonomous and solid. Toggling the image causes the entire card to instantly snap into a new geometric configuration. The interaction doesn’t feel like a visual trick; it feels like the container is physically aware of its contents. The transformation of the ‘x’ button into a ‘+’ provides sharp, mechanical feedback, making the UI feel logically engineered.

Advertisement