BFSG 2025: Ist Ihre Website barrierefrei?
Ab 28. Juni 2025 ist Barrierefreiheit Pflicht für viele Websites. Was das BFSG bedeutet und wie Sie jetzt handeln.
Core Web Vitals Zielwerte 2026: LCP (Largest Contentful Paint) unter 2,5 Sekunden · INP (Interaction to Next Paint) unter 200 Millisekunden · CLS (Cumulative Layout Shift) unter 0,1. Die drei häufigsten Ursachen für schlechte Werte: unkomprimierte Hero-Bilder ohne loading="eager" und fetchpriority="high" (LCP), zu viel JavaScript auf dem Hauptthread (INP), Bilder ohne explizite width und height-Attribute (CLS). Testen: pagespeed.web.dev — kostenlos, kein Account nötig.
Core Web Vitals sind seit 2021 direkter Google-Rankingfaktor. Das ist bekannt. Was weniger bekannt ist: Welche konkreten Code-Änderungen den größten Effekt haben — und welche Maßnahmen Zeit kosten, aber wenig bringen. Dieser Artikel ist ein praktischer Optimierungsguide für Entwickler und technische Website-Verantwortliche. Keine Theorie — sondern konkrete Code-Maßnahmen, geordnet nach Wirkung.
Google misst die Nutzererfahrung einer Website über drei konkrete Messwerte — die Core Web Vitals:
LCP — Largest Contentful Paint
Wann lädt das größte sichtbare Element? Das ist typischerweise das Hero-Bild oder die H1-Überschrift. Nutzer nehmen das als "die Seite ist da" wahr.
INP — Interaction to Next Paint
Wie schnell reagiert die Seite auf Nutzereingaben? Jeder Klick, jede Tastatureingabe, jedes Tippen auf dem Touchscreen — INP misst die Zeit bis die Seite visuell auf diese Interaktion reagiert.
CLS — Cumulative Layout Shift
Wie stark bewegen sich Elemente nach dem ersten Laden? Wenn ein Bild lädt und Text nach unten schiebt — das ist CLS. Nutzer klicken auf den falschen Button weil sich die Seite verschoben hat.
Die Zielwerte im Überblick:
| Metrik | Gut | Verbesserung nötig | Schlecht |
|---|---|---|---|
| LCP | < 2,5s | 2,5–4,0s | > 4,0s |
| INP | < 200ms | 200–500ms | > 500ms |
| CLS | < 0,1 | 0,1–0,25 | > 0,25 |
Google bewertet eine Website im Core Web Vitals Report nur dann als "Gut", wenn alle drei Metriken den Schwellenwert erreichen. Zwei gute Werte und ein schlechter — immer noch "Verbesserungsbedarf".
LCP ist der wichtigste der drei Werte — und der, bei dem die meisten Websites den größten Nachholbedarf haben.
Zuerst: Welches Element ist Ihr LCP-Element? In Chrome DevTools:
// In der Browser-Konsole
new PerformanceObserver((list) => {
const entries = list.getEntries();
const lastEntry = entries[entries.length - 1];
console.log('LCP Element:', lastEntry.element);
console.log('LCP Zeit:', lastEntry.startTime);
}).observe({type: 'largest-contentful-paint', buffered: true});
Das ist die einzeln wirkungsvollste LCP-Optimierung — und sie wird überraschend häufig falsch gemacht.
<img src="hero.jpg" alt="Hero" loading="lazy">
// Browser wartet auf JS, dann lazy-load → schlechter LCP
<img src="hero.webp"
alt="Ihr Hauptbild"
width="1200"
height="600"
loading="eager"
fetchpriority="high"
decoding="async">
Drei kritische Attribute:
loading="eager" — kein Lazy Loading für das LCP-Bildfetchpriority="high" — Browser lädt dieses Bild vor allem anderendecoding="async" — Dekodierung blockiert nicht den HauptthreadExterne CSS-Dateien sind render-blocking — der Browser kann die Seite erst rendern, wenn CSS geladen ist. LCP-relevante Styles sollten inline im <head> stehen:
<head>
<!-- Kritisches CSS inline — verhindert render-blocking -->
<style>
body { margin: 0; font-family: 'DM Sans', sans-serif; }
.hero { min-height: 60vh; background: var(--ink); }
.hero h1 { color: #fff; font-size: clamp(2rem, 5vw, 4rem); }
nav { position: sticky; top: 0; z-index: 100; }
</style>
<!-- Restliches CSS non-blocking laden -->
<link rel="preload" href="/css/main.css" as="style"
onload="this.onload=null;this.rel='stylesheet'">
</head>
Eine hohe TTFB macht alle anderen Optimierungen zunichte. Hosting in Deutschland: Bei Hetzner (Nürnberg oder Falkenstein) liegt die TTFB für Nutzer aus Deutschland typischerweise bei 20–50ms. US-Hosting: 150–300ms. Das allein kann LCP um 100–250ms verbessern.
# PHP Opcache aktivieren (in php.ini)
opcache.enable=1
opcache.memory_consumption=256
opcache.max_accelerated_files=10000
opcache.revalidate_freq=0
// WordPress Transient Cache (functions.php)
function get_cached_query($key, $callback, $expiry = 3600) {
$cached = get_transient($key);
if ($cached !== false) return $cached;
$result = $callback();
set_transient($key, $result, $expiry);
return $result;
}
# HTTP/2 in nginx.conf aktivieren
http2 on; # Nginx 1.25.1+
WebP ist 25–34% kleiner als JPEG bei gleicher Qualität. Automatische Konvertierung beim Upload:
// Automatische WebP-Konvertierung (WordPress functions.php)
add_filter('wp_handle_upload', function($file) {
if (in_array($file['type'], ['image/jpeg', 'image/png'])) {
$source = $file['file'];
$dest = preg_replace('/\.(jpe?g|png)$/i', '.webp', $source);
$image = imagecreatefromstring(file_get_contents($source));
imagewebp($image, $dest, 85);
imagedestroy($image);
}
return $file;
});
<!-- HTML mit WebP und Fallback -->
<picture>
<source srcset="hero.webp" type="image/webp">
<img src="hero.jpg" alt="Beschreibung"
width="1200" height="600"
loading="eager" fetchpriority="high">
</picture>
<!-- Responsive Images mit srcset -->
<img src="hero-600.webp"
srcset="hero-600.webp 600w, hero-900.webp 900w,
hero-1200.webp 1200w, hero-1800.webp 1800w"
sizes="(max-width: 600px) 100vw,
(max-width: 1200px) 80vw, 1200px"
alt="Beschreibung"
width="1200" height="600">
INP hat 2024 FID als Core Web Vital ersetzt. Es ist die schwieriger zu optimierende Metrik. INP misst nicht nur den ersten Klick, sondern alle Interaktionen während des Seitenbesuchs.
<script src="analytics.js"></script>
<script src="chat-widget.js"></script>
<script src="analytics.js" defer></script>
<script src="chat-widget.js" defer></script>
// Für nicht-kritische externe Scripts:
window.addEventListener('load', function() {
const script = document.createElement('script');
script.src = 'https://chat.service.com/widget.js';
document.body.appendChild(script);
});
// main.js
const worker = new Worker('heavy-calculation.js');
worker.onmessage = function(e) {
document.getElementById('result').textContent = e.data;
};
document.getElementById('calculate').addEventListener('click', () => {
worker.postMessage({data: inputData});
});
// ✓ Wartet 300ms nach letzter Eingabe
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
const debouncedSearch = debounce(fetchSearchResults, 300);
searchInput.addEventListener('input', function() {
debouncedSearch(this.value);
});
CLS ist oft das einfachste Problem zu lösen — und das am häufigsten übersehene.
<img src="produkt.webp" alt="Produkt">
<img src="produkt.webp" alt="Produkt"
width="400" height="300">
// Automatisch in WordPress (functions.php)
add_filter('wp_get_attachment_image_attributes', function($attr, $attachment) {
if (!isset($attr['width']) || !isset($attr['height'])) {
$metadata = wp_get_attachment_metadata($attachment->ID);
if ($metadata) {
$attr['width'] = $metadata['width'];
$attr['height'] = $metadata['height'];
}
}
return $attr;
}, 10, 2);
// ❌ Banner erscheint nachträglich → schiebt Inhalt runter
setTimeout(() => {
document.body.insertAdjacentHTML('afterbegin', '<div class="cookie-banner">...</div>');
}, 2000);
/* ✓ Platz reservieren bevor Inhalt da ist */
.cookie-banner-placeholder {
min-height: 80px; /* Platz reserviert, kein Layout-Shift */
}
/* ✓ size-adjust gleicht Unterschied zwischen Fallback und Web Font aus */
@font-face {
font-family: 'Outfit';
src: url('/fonts/outfit.woff2') format('woff2');
font-display: swap;
size-adjust: 103%; /* Anpassen bis Fallback und Webfont identisch wirken */
}
body {
font-family: 'Outfit', 'Arial', sans-serif;
}
loading="eager" und fetchpriority="high"width und height Attributensrcset für verschiedene Bildschirmbreiten<head>rel="preload" non-blocking ladendefer oder asyncload-Eventpassive: true wo möglichwidth und height Attributenfont-display: swap und size-adjustposition/top/left/right verändern (stattdessen transform)Jede Website, die Hawd Design entwickelt, wird vor Go-Live gegen diese Checkliste geprüft:
Das ist nicht unser Premiumangebot — es ist unser Standard.
Kostenloser PageSpeed-Check in 2 Minuten: pagespeed.web.dev — Ihre URL eingeben. Wenn der Mobile-Score unter 85 liegt, können wir helfen. Audit innerhalb 48h, Festpreis ab 500 €.