Zum Inhalt springen
CASOON

CSS-Carousels und Invoker Commands ohne JavaScript

Die wichtigsten Neuerungen in Chrome 135 für moderne Web-Entwicklung

8 Minuten
CSS-Carousels und Invoker Commands ohne JavaScript
#Chrome #CSS #Web APIs #JavaScript

Chrome 135 markiert einen Wendepunkt: Endlich können Entwickler Carousels, Dialoge und Popovers komplett ohne JavaScript erstellen. Die neuen CSS-Pseudo-Elemente ::scroll-button() und ::scroll-marker() sowie die Invoker Commands API machen tausende Zeilen JS-Code überflüssig – und bringen bessere Accessibility gleich mit.

CSS-Carousels: Der Game-Changer

Jahrelang waren Carousels synonym mit JavaScript-Frameworks wie Swiper, Slick oder Glide. Chrome 135 beendet diese Ära mit CSS Overflow 5 Specification-Features.

Die neuen Pseudo-Elemente

::scroll-button()

Browser-native, interaktive Scroll-Buttons, die automatisch 85% eines Scroll-Bereichs navigieren:

.carousel {
  overflow-x: scroll;
  scroll-snap-type: x mandatory;
}

.carousel::scroll-button(prev) {
  content: "←";
  background: rgba(0, 0, 0, 0.5);
  color: white;
  padding: 1rem;
}

.carousel::scroll-button(next) {
  content: "→";
  background: rgba(0, 0, 0, 0.5);
  color: white;
  padding: 1rem;
}

Vorteile:

  • Stateful: Browser verwaltet Disabled-States (z. B. “Prev” am Anfang)
  • Accessible: ARIA-Rollen und Keyboard-Navigation eingebaut
  • Performant: Native Implementierung, kein JS-Overhead

::scroll-marker()

Visuelle Marker (Dots/Thumbnails) für Navigation und Progress-Tracking:

.carousel::scroll-marker {
  content: "";
  width: 10px;
  height: 10px;
  background: gray;
  border-radius: 50%;
}

.carousel::scroll-marker:checked {
  background: blue;
}

Browser zeigt automatisch, welcher Marker aktiv ist – ohne State-Management in JS.

<div class="carousel">
  <img src="slide1.jpg" alt="Slide 1">
  <img src="slide2.jpg" alt="Slide 2">
  <img src="slide3.jpg" alt="Slide 3">
</div>
.carousel {
  display: flex;
  overflow-x: scroll;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: 1rem;
}

.carousel img {
  scroll-snap-align: center;
  width: 100%;
  flex-shrink: 0;
}

/* Buttons automatisch generiert */
.carousel::scroll-button(prev) { content: "←"; }
.carousel::scroll-button(next) { content: "→"; }

/* Markers automatisch generiert */
.carousel::scroll-marker { content: ""; }

Null Zeilen JavaScript. Volle Accessibility.

Warum das revolutionär ist

Typische JS-Carousel-Libraries haben 10-50 KB Code, hunderte Konfigurationsoptionen und fragile Accessibility-Implementierungen. Chrome 135 macht das Browser-nativ:

  • Carousel Best Practices vom Browser gehandhabt
  • Keyboard-Navigation (Pfeiltasten, Tab, Space) eingebaut
  • Screen-Reader-Support automatisch korrekt
  • Performance durch native Scroll-APIs

Die Accessibility-Teams bei Chrome/Edge haben sichergestellt: Es ist fast unmöglich, ein zugänglicheres Carousel zu bauen als mit diesen Pseudo-Elementen.

Browser-Support

  • Chrome 135+
  • Edge 135+
  • Safari/Firefox: In Entwicklung

Für ältere Browser: Progressive Enhancement via @supports:

@supports selector(::scroll-button(prev)) {
  /* Native carousel */
  .carousel::scroll-button(prev) { content: "←"; }
}

@supports not selector(::scroll-button(prev)) {
  /* Fallback: Zeige basic scrollable container */
  .carousel { overflow-x: auto; }
}

Invoker Commands: Deklarative UI-Logik

Die Invoker Commands API (command + commandfor) erlaubt es, HTML-Elemente direkt zu steuern – ohne onclick-Handler.

Die Basics

HTML-Attribute:

  • commandfor: ID des Ziel-Elements
  • command: Aktion (toggle-popover, show-modal, close, etc.)

Beispiel: Dialog ohne JavaScript

<!-- Trigger-Button -->
<button commandfor="settings-dialog" command="show-modal">
  Einstellungen öffnen
</button>

<!-- Dialog -->
<dialog id="settings-dialog">
  <h2>Einstellungen</h2>
  <p>Inhalt hier...</p>
  <button commandfor="settings-dialog" command="close">
    Schließen
  </button>
</dialog>

Kein dialog.showModal(), kein dialog.close() – Browser übernimmt alles.

Unterstützte Built-in Commands

Dialogs:

  • show-modal: Öffnet Dialog als Modal (Backdrop + Trap-Focus)
  • close: Schließt Dialog

Popovers:

  • toggle-popover: Togglet Popover-Sichtbarkeit
  • show-popover: Zeigt Popover
  • hide-popover: Versteckt Popover

Details/Summary:

  • open: Öffnet <details>-Element
  • close: Schließt <details>-Element

Custom Commands

Mit ---Präfix kannst du eigene Commands definieren:

<button commandfor="menu" command="--explode">
  Explodieren!
</button>

<div id="menu"></div>
document.getElementById('menu').addEventListener('command', (event) => {
  if (event.command === '--explode') {
    // Custom-Logik hier
    event.target.classList.add('exploding');
  }
});

Vorteile:

  • Semantische Trennung: HTML beschreibt Struktur, JS nur Custom-Logic
  • Accessibility: Browser kennt Intent (z. B. Modal öffnen) und handhabt Keyboard/Screen-Reader
  • Wartbarkeit: Keine Event-Listener-Suppe in JS-Files

Browser-Support

Baseline Support erreicht:

  • Chrome 135+ ✅
  • Edge 135+ ✅
  • Opera 120+ ✅
  • Safari 26.2+ ✅
  • Firefox Nightly (in Entwicklung)

Polyfill verfügbar für ältere Browser: GitHub Polyfill

Weitere Chrome 135 Highlights

CSS shape() Function

Neue Funktion für clip-path und offset-path, um komplexe Pfade zu definieren:

.element {
  clip-path: shape(
    from 0% 0%,
    line to 100% 0%,
    arc to 100% 100% of 50%,
    line to 0% 100%,
    close
  );
}

Ersetzt SVG-Pfade in vielen Fällen – einfacher lesbar und wartbar.

MediaStreamTrack in Web Speech API

Websites können jetzt Web Speech API für Remote-Audio nutzen (z. B. Captions für Video-Calls):

const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const recognition = new webkitSpeechRecognition();
recognition.lang = 'de-DE';

// NEU in Chrome 135: MediaStreamTrack Support
const audioTrack = stream.getAudioTracks()[0];
recognition.audioTrack = audioTrack;
recognition.start();

Use-Cases: Live-Untertitel für Remote-Meetings, Transkription von Podcasts, Voice-Control in WebRTC-Apps.

highlightsFromPoint API

Interaktion mit Custom Highlights (z. B. Text-Marker):

const highlights = CSS.highlights.get('search-results');
document.addEventListener('click', (event) => {
  const highlightsAtPoint = CSS.highlightsFromPoint(event.clientX, event.clientY);
  
  if (highlightsAtPoint.includes('search-results')) {
    // User klickte auf markierten Text
    showContextMenu();
  }
});

Ideal für: Annotation-Tools, Kommentar-Systeme, interaktive Tutorials.

Device-Bound Session Credentials

Sichere Session-Bindung an ein Gerät mit automatischer Erneuerung:

// Server fordert Device-Bound Session an
const credential = await navigator.credentials.create({
  publicKey: {
    challenge: serverChallenge,
    rp: { name: "Example Corp" },
    user: { id: userId, name: userName },
    pubKeyCredParams: [{ type: "public-key", alg: -7 }],
    authenticatorSelection: { authenticatorAttachment: "platform" }
  }
});

// Browser erneuert Session automatisch mit Proof-of-Possession

Security-Vorteil: Session-Hijacking wird extrem schwer – selbst bei Token-Diebstahl kann Angreifer ohne Device nicht zugreifen.

setInterval(0) ohne Clamping

Vor Chrome 135: setInterval(..., 0) wurde auf 1ms geclampt.

Ab Chrome 135: 0ms ist wirklich 0ms – wichtig für High-Frequency-Updates (z. B. Game-Loops, Audio-Processing).

// Jetzt wirklich 0ms statt 1ms
setInterval(() => {
  updateGameState();
}, 0);

Chrome Extensions: userScripts.execute()

Neue Methode für einmalige User-Script-Injektion statt permanenter Registrierung:

chrome.userScripts.execute({
  target: { tabId: tab.id },
  func: () => {
    // Einmalige Custom-Logic
    document.body.style.filter = 'invert(1)';
  }
});

Vorteil: Temporäre Scripts ohne Pollution der permanenten Registry.

DevTools-Verbesserungen

Performance Panel:

  • Redesigned UI mit klareren Metrics
  • Bessere Visualisierung von Long Tasks

Accessibility Tree View:

  • Neuer Tab in Elements-Panel
  • Zeigt ARIA-Tree wie Screen-Reader ihn sieht

Empty States:

  • Alle Panels haben jetzt hilfreiche Leer-Zustände mit Tipps

Migration-Tipps

Von JS-Carousels zu CSS

Vorher (Swiper):

new Swiper('.carousel', {
  navigation: { nextEl: '.next', prevEl: '.prev' },
  pagination: { el: '.pagination', clickable: true },
  scrollbar: { el: '.scrollbar' },
});

Nachher (CSS):

.carousel {
  overflow-x: scroll;
  scroll-snap-type: x mandatory;
}
.carousel::scroll-button(prev) { content: "←"; }
.carousel::scroll-button(next) { content: "→"; }
.carousel::scroll-marker { content: ""; }

Gewinn: ~40 KB weniger Bundle, bessere Accessibility, kein JS-Fehler-Risiko.

Von onclick zu Invoker Commands

Vorher:

<button onclick="document.getElementById('modal').showModal()">
  Open
</button>

Nachher:

<button commandfor="modal" command="show-modal">
  Open
</button>

Gewinn: Deklarativ, besser verständlich, Browser optimiert Accessibility.

Fazit: Weniger Code, mehr Browser

Chrome 135 setzt die Trend fort: Platform über Polyfills. Features, die jahrelang JS-Libraries brauchten, werden Browser-nativ – mit besserer Performance und Accessibility.

Was sich ändert:

  1. Carousels: ::scroll-button() + ::scroll-marker() → keine Swiper/Slick mehr nötig
  2. Dialogs/Popovers: Invoker Commands → keine onclick-Handler mehr
  3. Custom Paths: shape() → CSS statt SVG-Pfade
  4. Speech-to-Text: MediaStreamTrack-Support → Remote-Audio-Captions
  5. Security: Device-Bound Sessions → robustere Auth

Nächste Schritte:

  • Experimentieren: Chrome 135+ installieren, neue Features testen
  • Progressive Enhancement: CSS-Carousels mit Fallback für ältere Browser
  • Polyfills nutzen: Invoker Commands Polyfill für breitere Kompatibilität
  • Lighthouse checken: Neue Metrics für CSS Carousels + Invoker Commands

Die Zukunft ist deklarativ. Chrome 135 beweist: Die besten Features brauchen kein JavaScript.


Sources: