Tailwind CSS 4: @theme, Oxide Engine & Container Queries in der Praxis
Was sich mit Tailwind CSS 4 wirklich ändert: CSS-first Konfiguration mit @theme, der Oxide Compiler, Container Queries, color-mix() und die Migration von v3.
Rechtliches & Info
Technischer Deep-Dive in Astro 6: Islands Architecture, Server Islands für dynamische Inhalte, die neue Content Layer API und View Transitions mit ClientRouter.
Astro ist seit Version 3 ein fester Bestandteil moderner Static-Site-Generatoren — aber Astro 6 verändert die Architektur grundlegend. Wer bisher mit der Islands-Idee gearbeitet hat, findet in Version 6 drei signifikante Erweiterungen: Server Islands, die stabile Content Layer API und einen überarbeiteten ClientRouter. Dieser Artikel erklärt die Konzepte technisch und zeigt, wo die Unterschiede zu früheren Versionen liegen.
Das Island-Konzept beschreibt eine Seite als statisches HTML, in das einzelne interaktive Bereiche — die “Inseln” — eingebettet werden. Jede Insel ist unabhängig und wird nur dann hydratisiert, wenn sie sichtbar oder bereit ist.
---
// Atom-Ebene: kein JavaScript, keine Hydratisierung
import StaticCard from '../components/atoms/StaticCard.astro';
// Insel: React-Komponente mit clientseitigem State
import LiveCounter from '../components/molecules/LiveCounter.jsx';
---
<StaticCard title="Statischer Inhalt" />
<!-- Nur dieser Teil wird im Browser hydratisiert -->
<LiveCounter client:visible />
Die client:-Direktiven steuern wann die Hydratisierung erfolgt:
| Direktive | Auslöser |
|---|---|
client:load | Sofort beim Laden der Seite |
client:idle | Wenn der Browser idle ist |
client:visible | Wenn die Komponente in den Viewport scrollt |
client:media | Bei einem bestimmten Media Query |
client:only | Nur clientseitig, kein SSR |
Das Modell liefert exzellente Core Web Vitals, weil der initiale HTML-Payload kein JavaScript-Bundle enthält — der Browser muss nichts parsen und ausführen, bevor der erste sichtbare Inhalt erscheint.
Astro 6 führt Server Islands als stabilisiertes Feature ein. Das Konzept dreht die Frage um: Nicht “Welche Teile der Seite brauchen Client-JS?”, sondern “Welche Teile der Seite müssen serverseitig gerendert werden, obwohl der Rest statisch ist?”
Ein typisches Szenario: eine statisch generierte Marketing-Seite mit einem personalisierten Header (eingeloggter Nutzername, Warenkorb-Zähler). Bisher bedeutete das entweder vollständiges SSR oder einen separaten API-Call nach dem Load.
Mit Server Islands rendert Astro den personalisierten Teil auf dem Server — aber isoliert vom statischen Build:
---
// Server Island: wird pro Request serverseitig gerendert
import UserGreeting from '../components/UserGreeting.astro';
---
<!-- Statischer Teil aus dem CDN -->
<main>
<h1>Willkommen bei Wender Media Wissen</h1>
<!-- Server Island: dynamisch, aber kein Client-JS -->
<UserGreeting server:defer>
<span slot="fallback">Laden...</span>
</UserGreeting>
</main>
Das server:defer-Attribut weist Astro an, diesen Bereich via Streaming nachzuladen. Der Vorteil: der statische Shell ist sofort vom CDN verfügbar, der dynamische Teil folgt ohne zusätzliches JavaScript im Browser. Für Datenschutz-Szenarien (kein Tracking ohne Consent) ist das eine elegante Lösung.
Server Islands setzen einen SSR-Adapter voraus. Für Netlify:
npx astro add netlify
In der astro.config.mjs:
import netlify from '@astrojs/netlify';
export default defineConfig({
output: 'static',
adapter: netlify(),
});
Der Modus output: 'static' bleibt gesetzt — Astro generiert weiterhin einen statischen Build, nutzt aber den Adapter für Server-Island-Requests.
Die Content Layer API ist die bedeutsamste Architektur-Änderung in Astro 6. Sie abstrahiert Datenquellen — ob Markdown-Dateien, CMS-APIs oder Datenbanken — hinter einer einheitlichen defineCollection-Schnittstelle.
// src/content/config.ts
import { defineCollection, z } from 'astro:content';
const blog = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
description: z.string(),
pubDate: z.date(),
category: z.enum(['Webdesign', 'SEO', 'Performance', 'BFSG']),
readingTime: z.number(),
featured: z.boolean().optional().default(false),
}),
});
export const collections = { blog };
Ab Astro 6 kann eine Collection auch von einer externen API laden:
import { defineCollection, z } from 'astro:content';
import { glob } from 'astro/loaders';
// Lokale Dateien via Glob-Loader
const blog = defineCollection({
loader: glob({ pattern: '**/*.mdx', base: './src/content/blog' }),
schema: z.object({ /* ... */ }),
});
// Externer CMS-Loader (hypothetisch)
const news = defineCollection({
loader: async () => {
const res = await fetch('https://api.example.com/articles');
return res.json();
},
schema: z.object({
id: z.string(),
title: z.string(),
body: z.string(),
}),
});
Der Loader kann auch inkrementell laden — context.store.set() speichert Einträge in einem persistenten Cache, sodass bei erneutem Build nur geänderte Einträge neu geladen werden.
---
import { getCollection, render } from 'astro:content';
const articles = await getCollection('blog');
const sorted = articles.sort(
(a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime()
);
---
Das render()-Ergebnis liefert die Content-Komponente sowie ein headings-Array — nützlich für automatisch generierte Inhaltsverzeichnisse.
Astro 6 überarbeitet den <ViewTransitions />-Mechanismus und benennt ihn in <ClientRouter /> um, um klarer zu signalisieren, dass es sich um ein clientseitiges Routing-Verhalten handelt.
---
// layouts/Layout.astro
import { ClientRouter } from 'astro:transitions';
---
<html>
<head>
<ClientRouter />
</head>
<body>
<slot />
</body>
</html>
<!-- Persistente Elemente über Seitenübergänge hinweg -->
<nav transition:persist>...</nav>
<!-- Benannte Übergänge für morphende Elemente -->
<img src={article.image} transition:name={`hero-${article.slug}`} />
Auf der Zielseite muss das gleiche transition:name gesetzt sein — Astro führt dann automatisch eine View Transition zwischen den beiden Elementen durch.
import { navigate } from 'astro:transitions/client';
document.addEventListener('astro:page-load', () => {
// Läuft nach jeder Navigation (initial + SPA)
initAnalytics();
});
document.addEventListener('astro:before-swap', (event) => {
// Vor dem DOM-Swap — z.B. Scroll-Position sichern
event.newDocument.querySelector('main')?.classList.add('entering');
});
Alle drei Features — Server Islands, Content Layer API und ClientRouter — sind so konzipiert, dass sie die Kern-Performance-Architektur von Astro nicht verschlechtern.
Astro 6 macht das Framework tauglich für Szenarien, die bisher einen vollständigen Next.js-Stack erfordert hätten: personalisierte Bereiche, externe Datenquellen mit Typsicherheit und seitenübergreifende Animationen.
Wer ein bestehendes Astro-Projekt migriert, sollte mit der Content Layer API beginnen — sie ist rückwärtskompatibel zu Collections aus Astro 4/5 und bietet sofortigen Mehrwert durch besseres Loader-Caching.
Weiterführende Artikel auf Wender Media Wissen:
Haben Sie Fragen zur Astro-Architektur für Ihr Projekt? Wender Media begleitet technische Webprojekte von der Konzeption bis zum Launch — kontaktieren Sie uns unter info@wendermedia.info.
Wender Media unterstützt Sie bei der praktischen Umsetzung — von der technischen Konzeption bis zum Launch. Schreiben Sie uns, wir antworten innerhalb von 24 Stunden.
Jetzt Beratung anfragenKostenlos & unverbindlich — info@wendermedia.info
Was sich mit Tailwind CSS 4 wirklich ändert: CSS-first Konfiguration mit @theme, der Oxide Compiler, Container Queries, color-mix() und die Migration von v3.
TypeScript strict vollständig in Astro-Projekten nutzen: das strict-Flag, der satisfies-Operator, typsichere Props mit Generics und das Typsystem der Content Collections.
Die Atomic Design Methodik konsequent in Astro umsetzen: Hierarchie-Regeln, Import-Grenzen, Slot-Komposition und häufige Fallstricke beim Aufbau eines Komponentensystems.