Skip to content

cls.unconstrained carousel

github-actions[bot] edited this page Sep 7, 2026 · 2 revisions

cls.unconstrained-carousel

Rule ID: cls.unconstrained-carousel Severity: WARN Category: cls Target Standards: W3C Cumulative Layout Shift (CLS) Metric Specification, W3C CSS Scroll Snap Module Level 1, W3C CSS Box Sizing Module Level 4 (aspect-ratio)


1. Overview & Core Invariant

Warns when carousel or slider containers lack bounded height or slide aspect-ratio constraints

Core Invariant:

"Carousel and slider viewport tracks must constrain container height or bind slide items to fixed aspect ratios to prevent vertical reflow during slide transitions."


2. Technical Grounding & Engine Realities

Horizontal scrolling tracks and carousels render dynamic collections of cards, banners, or images.

When the carousel track lacks an explicit height (e.g. 'h-64' or 'min-h-[300px]') and slides do not have locked aspect ratios, incoming slides with varying image proportions or dynamic text will force the entire container to expand or collapse vertically.

Fixing the container height or assigning 'aspect-video' / 'aspect-square' to slide items ensures layout stability throughout horizontal panning.

Interactive control sliders (e.g. Radix '') and security verification challenge widgets (e.g. Cerberus '') are disambiguated and exempted from this rule.


3. Vulnerability & Risk Taxonomy

Risk Vector Severity Impact
Vertical Container Height Jitter MEDIUM Slide transitions with varying content heights push subsequent page content up and down.
Cumulative Layout Shift (CLS) HIGH Carousel height adjustments contribute cumulative shift points during user scrolling.

4. Non-Compliant Code Patterns (Bad Examples)

TSX (Horizontal snap container without container height or slide aspect-ratio):

<div className="flex overflow-x-auto snap-x">
  {slides.map(s => <img key={s.id} src={s.url} alt={s.title} />)}
</div>

5. Compliant Implementation Patterns (Good Examples)

TSX (Carousel container with explicit height constraint):

<div className="flex overflow-x-auto snap-x h-64 md:h-96 w-full">
  {slides.map(s => (
    <div key={s.id} className="snap-center shrink-0 w-full h-full">
      <img src={s.url} alt={s.title} className="w-full h-full object-cover" />
    </div>
  ))}
</div>

TSX (Carousel slide items locked with aspect-video utility):

<div className="flex overflow-x-auto snap-x w-full">
  {slides.map(s => (
    <div key={s.id} className="snap-center shrink-0 w-80 aspect-video">
      <img src={s.url} alt={s.title} className="w-full h-full object-cover" />
    </div>
  ))}
</div>

TSX (Interactive verification challenge slider is recognized as a control slider and safely exempted):

<ChallengeSlider
  onSolve={solveChallenge}
  onCancel={handleCancel}
  solved={isSolved}
/>

6. How to Suppress (Ignore Directives)

If this pattern is required for an intentional exception, suppress the diagnostic using the canonical Charites Rule ID:

<!-- charites:ignore cls.unconstrained-carousel intentional exception -->
// charites:ignore cls.unconstrained-carousel intentional exception

7. Configuration Reference (charites.yaml)

rules:
  cls.unconstrained-carousel:
    severity: warn # error | warn | info | off

8. Architectural Domain & Verification Reference


Rule Categories

A11y (16 rules)
Browser (12 rules)
Cls (16 rules)
Design (1 rules)
Ergonomy (5 rules)
Inp (16 rules)
Lcp (16 rules)
Mobile (5 rules)
Performance (16 rules)
Pwa (10 rules)
Responsive (18 rules)
Semantic (1 rules)
Theme (32 rules)
Ux (20 rules)

Clone this wiki locally