a11ytip Dokumentation— Veröffentlicht am
Veröffentlicht am
a11ytip Dokumentation
Offizielle a11ytip Dokumentation
Eine einfache Zoom-Funktion für bessere Accessibility durch Tailwind @custom-variant
12% der Menschen haben eine Form von Sehbeeinträchtigung. Durch den demografischen Wandel nutzen auch immer mehr ältere Menschen das Internet, für die eine größere Schrift hilfreich ist. Die Browser-Zoom-Funktion hilft, ist aber auf mobilen Browsern nicht vorhanden. Außerdem haben Entwickler keine Kontrolle darüber, was und wie vergrößert wird. Eine integrierte Website-Zoom-Funktion ermöglicht die volle Kontrolle über das Nutzererlebnis.
Mehr Accessibility durch Zoom-Funktion. Elegant und skalierbar realisiert mit Tailwind CSS Custom Variants.
Durch die @custom-variant Directive in Tailwind CSS können wir eigene Präfix-Varianten definieren. Ähnlich wie dark:
oder hover:, aber für unsere spezifischen Bedürfnisse. Das bedeutet: Wir können eine zoom: Variante erstellen, die
nur dann aktiv wird, wenn der Zoom-Modus eingeschaltet ist.
Beispiel:
<div class="zoom:text-xl zoom:p-8 p-4 text-base">Text größer im Zoom-Modus</div>
Ein bisschen CSS, ein bisschen JavaScript, ein bisschen Markup. Fertig.
Genau wie dark: für Dark Mode kannst du eine zoom: Variant definieren:
@custom-variant zoom (&:where(.zoom, .zoom *));
Alternative mit Data-Attribut:
@custom-variant zoom (&:where([data-zoom="true"], [data-zoom="true"] *));
Diese Zeile aktiviert Tailwind-Klassen wie zoom:text-xl nur, wenn das HTML-Tag die entsprechende Klasse oder das
Data-Attribut hat.
So sieht meine komplette Implementierung in CSS aus:
@custom-variant zoom (&:where(.zoom, .zoom *));
:root {
--zoom-factor: 1;
}
:root.zoom {
--zoom-factor: 1.125;
/* Spezielle Styles für tailwindcss/typography */
.prose-base {
font-size: calc(1rem * var(--zoom-factor, 1));
line-height: calc(1.75 * var(--zoom-factor, 1));
}
/* Trick 18 für z. B. SVGs */
svg {
transform: scale(var(--zoom-factor, 1));
}
}
/* Das Herzstück. Wir überschreiben die Tailwind v4 Variablen ganz gezielt */
@theme {
--text-xs: calc(0.75rem * var(--zoom-factor, 1));
--text-xs--line-height: calc(1.33 * var(--zoom-factor, 1));
--text-sm: calc(0.875rem * var(--zoom-factor, 1));
--text-sm--line-height: calc(1.43 * var(--zoom-factor, 1));
--text-base: calc(1rem * var(--zoom-factor, 1));
--text-base--line-height: calc(1.5 * var(--zoom-factor, 1));
--text-lg: calc(1.125rem * var(--zoom-factor, 1));
--text-lg--line-height: calc(1.56 * var(--zoom-factor, 1));
--text-xl: calc(1.25rem * var(--zoom-factor, 1));
--text-xl--line-height: calc(1.4 * var(--zoom-factor, 1));
--text-2xl: calc(1.5rem * var(--zoom-factor, 1));
--text-2xl--line-height: calc(1.33 * var(--zoom-factor, 1));
--text-3xl: calc(1.875rem * var(--zoom-factor, 1));
--text-3xl--line-height: calc(1.2 * var(--zoom-factor, 1));
--text-4xl: calc(2.25rem * var(--zoom-factor, 1));
--text-4xl--line-height: calc(1.11 * var(--zoom-factor, 1));
--text-5xl: calc(3rem * var(--zoom-factor, 1));
--text-5xl--line-height: calc(1 * var(--zoom-factor, 1));
--text-6xl: calc(3.75rem * var(--zoom-factor, 1));
--text-6xl--line-height: calc(1 * var(--zoom-factor, 1));
--text-7xl: calc(4.5rem * var(--zoom-factor, 1));
--text-7xl--line-height: calc(1 * var(--zoom-factor, 1));
--text-8xl: calc(6rem * var(--zoom-factor, 1));
--text-8xl--line-height: calc(1 * var(--zoom-factor, 1));
--text-9xl: calc(8rem * var(--zoom-factor, 1));
--text-9xl--line-height: calc(1 * var(--zoom-factor, 1));
}
Durch die Neudefinition der Variablen im @theme werden alle Utility-Klassen automatisch mit den neuen Werten
berechnet.
Simples Beispiel:
<button data-zoom-toggle class="zoom:hidden" aria-label="Vergrößern">
<ZoomInIcon />
Vergrößern
</button>
<button data-zoom-toggle class="zoom:flex hidden" aria-label="Verkleinern">
<ZoomOutIcon />
Verkleinern
</button>
<script>
function updateZoom(isZoomed) {
document.documentElement.classList.toggle("zoom", isZoomed);
localStorage.setItem("zoom", isZoomed ? "true" : "false");
}
function initializeZoom() {
const savedZoom = localStorage.getItem("zoom");
const isZoomed = savedZoom === "true";
updateZoom(isZoomed);
}
initializeZoom();
// Attach event listener to all zoom toggles
document.querySelectorAll("[data-zoom-toggle]").forEach((button) => {
button.addEventListener("click", () => {
const isZoomed = document.documentElement.classList.contains("zoom");
updateZoom(!isZoomed);
});
});
// Keyboard shortcut: Shift + Control + Z for zoom toggle
document.addEventListener("keydown", (event) => {
if (event.shiftKey && event.ctrlKey && event.key === "Z") {
const isZoomed = document.documentElement.classList.contains("zoom");
updateZoom(!isZoomed);
event.preventDefault();
}
});
</script>
<article class="prose zoom:prose-lg">
<h1 class="zoom:text-4xl text-3xl">Titel wird größer</h1>
<p class="zoom:text-lg zoom:leading-loose text-base leading-relaxed">Text wird besser lesbar.</p>
</article>
:root.zoom-small {
--zoom-factor: 1.0625;
}
:root.zoom-medium {
--zoom-factor: 1.125;
}
:root.zoom-large {
--zoom-factor: 1.25;
}
const ZOOM_LEVELS = ["", "zoom-small", "zoom-medium", "zoom-large"];
let currentLevel = 0;
const cycleZoom = () => {
document.documentElement.className = document.documentElement.className.replace(/zoom-\w+/g, "");
currentLevel = (currentLevel + 1) % ZOOM_LEVELS.length;
if (ZOOM_LEVELS[currentLevel]) {
document.documentElement.classList.add(ZOOM_LEVELS[currentLevel]);
}
};
@media (max-width: 768px) {
:root.zoom {
--zoom-factor: 1.25; /* Stärkerer Zoom auf Mobile */
}
}
:root.zoom {
/* Navigation bleibt kompakt */
.nav-item {
--zoom-factor: 1.05;
}
/* Content wird stark vergrößert */
.content-area {
--zoom-factor: 1.2;
}
/* Buttons bekommen mehr Padding */
.btn {
padding: calc(0.5rem * var(--zoom-factor, 1)) calc(1rem * var(--zoom-factor, 1));
}
}
Moderne Browser: Vollständige Unterstützung für Custom Properties und Custom Variants.
Fallback für ältere Browser:
if (!CSS.supports("--custom: property")) {
// Fallback: Klassen-basierte Lösung
const zoomClasses = {
"text-base": "text-lg",
"p-4": "p-6",
// ...
};
const applyZoom = () => {
document.querySelectorAll("[data-zoomable]").forEach((el) => {
// Klassen direkt austauschen
});
};
}
Dank Tailwind @custom-variant ist es Junior-Developer-leicht, eine skalierbare, performante und barrierefreie Zoom-Funktion in eine Website zu integrieren. Durch einmaliges Setup kann man mit gewohnten Tailwind-Utilities responsive Zoom-Verhalten implementieren. Easy peasy lemon squeezy.