Webentwicklung ist heute viel einfacher geworden (und kaum jemand hat es bemerkt)
Viele Features, die früher Hacks und Workarounds erforderten, werden jetzt von allen Browsern nativ unterstützt. Wir werfen einen Blick auf sie.
Jetzt, wo der Support mit Sicherheitsupdates für den Internet Explorer 11 offiziell beendet ist und nur noch in Langzeit-Support-Umgebungen für Unternehmen eine Rolle spielt, ist der IE für den normalen Endnutzer endgültig tot. Alle übrigen Browser mit einem nennenswerten Marktanteil erhalten regelmäßig automatische Updates. Sogar Apple führt nun im Laufe des Jahres durch kleinere Safari-Updates die Unterstützung für neue Webfunktionen ein und stellt größere Safari-Updates auch für einige ältere macOS-Versionen zur Verfügung.
Für Webentwickler:innen heißt das, dass sie nur die letzten beiden Hauptversionen aller Browser unterstützen müssen und trotzdem sicher sein können, dass die große Mehrheit ihrer User abgedeckt ist. Natürlich ist es ratsam, die Browsernutzung Ihrer Nutzer:innen in Ihrem Analytics-Tool selbst zu überprüfen, bevor Sie die unternehmensrelevante Entscheidung treffen, den Support für bestimmte Browser einzustellen.
Mit neuen Versions-Updates unterstützen Browser regelmäßig neue Web-Funktionen, was oft zu Gedanken wie “Schön, das in fünf Jahren benutzen zu können, wenn es von allen Browsern unterstützt wird” führt. Der Zeitpunkt, an dem der übergreifende Browser-Support dann tatsächlich da ist, bleibt jedoch in der alltäglichen Menge von WebDev-News und neuen JavaScript-Frameworks oft unbemerkt. Wenn Sie also nicht regelmäßig die Changelogs aller relevanten Browser durchgehen, ist die Wahrscheinlichkeit groß, dass Sie Funktionen verpasst haben, die inzwischen problemlos verwendet werden können und sich dadurch das Leben schwerer machen, als es sein müsste.
Als ich kürzlich caniuse.com durchstöberte, war ich angenehm überrascht, welche Funktionen bereits durchgängig unterstützt werden, denn viele von ihnen können uns eine Menge Arbeit ersparen und maßgeschneiderte Lösungen für häufige Probleme, die bislang eine Menge Hacks, Workarounds oder Libraries erforderten, mit einem Einzeiler ersetzen. Cool! Schauen wir uns einige davon an.
Webfonts
Font-Formate
Erinnern Sie sich noch an Artikel wie die bulletproof font-face syntax? In den frühen 2010er Jahren waren bis zu fünf verschiedene Dateiformate nötig, um eigene Webfonts in allen gängigen Browsern anzuzeigen, und damit eine komplizierten Kette von Schriftdatei-URLs, die sich niemand merken konnte, so dass wir Tools nutzen mussten, um sie für uns zu erstellen. Irgendwann wurde dann einfach Google Fonts verwendet, das neben den Schriftdateien selbst auch das passende CSS für die Schriftart zur Verfügung stellt, je nachdem von welchem Browser der Request kommt.
Es gibt jedoch legitime Gründe, Ihre Web-Fonts selbst zu hosten, was zum Glück jetzt viel einfacher ist, da WOFF2, das wohl leistungsfähigste Web-Font-Format, jetzt von allen wichtigen Browsern unterstützt wird.
Möglicherweise brauchen Sie auch nicht mehr unterschiedliche WOFF2-Dateien für verschiedene Schriftschnitte oder -stile, denn es gibt jetzt Variable Fonts, und sie werden auch von allen Browsern unterstützt.
Wenn Sie also bislang einen Webfont in drei Schnitten oder Varianten mit jeweils fünf Dateiformaten hatten, waren also 15 Font-Dateien plus CSS erforderlich, um diese korrekt zu laden. Jetzt brauchen Sie nur noch eine.
Laden von Webfonts
Selbst wenn wir uns nur um eine Font-Datei kümmern müssen, ist das immer noch eine zusätzliche Ressource, die vom Browser heruntergeladen werden muss. Vor ein paar Jahren war es noch nicht ohne Weiteres möglich zu kontrollieren, was beim Laden von Schriftarten passiert. Es war nicht ungewöhnlich, dass auf einer Webseite überhaupt kein Text zu sehen war, bis die Webfonts fertig heruntergeladen wurden (auch FOIT = Flash of Invisible Text genannt). Dies ist eine suboptimale User Experience und führt dazu, dass sich das Laden der Webseite insgesamt langsamer anfühlt als es tatsächlich ist.
Den Nutzer:innen fiel das negativ auf, und so entstanden mehrere Skripte von Drittanbietern, mit denen man das Ladeverhalten von Schriften steuern konnte. Dies bedeutete jedoch eine Menge blocking JavaScript-Code, den Sie in Ihre Seite einbetten mussten, was wiederum die Ladezeit Ihrer Seite erhöhte. Heute ist das alles nicht mehr nötig. Wir haben jetzt die font-display-Regel, die dem Browser mitteilt, wie er sich verhalten soll, bis ein Webfont geladen ist. Eine sinnvolle Voreinstellung ist font-display: swap
, die sofort die Fallback-Schriftart anzeigt und dann zum Webfont wechselt, sobald dieser geladen wurde. Auf diese Weise kann man den Text auf der Seite so schnell wie möglich lesen.
Verschiedene Schriftfamilien haben unterschiedliche Buchstabenbreiten, so dass es zu einer Verschiebung des Inhalts kommen kann, wenn die Schriftart gewechselt wird. Um dies zu verhindern, können wir die Fallback-Schriftgröße mit CSS so genau wie möglich an unseren Webfont anpassen. Font Style Matcher ist eine sehr nützliche Webseite, mit der man Schriftarten schnell und einfach visuell aufeinander abstimmen kann.
Nun müssen wir aber wissen, wann das Laden unseres Webfonts abgeschlossen ist, um die Größenanpassung für den Fallback-Font zu entfernen. Es gibt jetzt eine native Font Loading API, die uns mitteilt, wann ein Font fertig geladen ist. Auf diese Weise können wir ein nutzerfreundliches Verhalten beim Laden von Schriftarten mit nur wenigen Codezeilen implementieren:
// in Ihrem JavaScript:
await document.fonts.ready;
document.body.classList.add('font-loaded');
// in Ihrem CSS:
@font-face {
font-family: 'MyFont';
src: url('fonts/my-font.woff2') format('woff2-variations');
font-weight: 400 700;
font-display: 'swap';
}
body {
font-family: 'MyFont', Arial, sans-serif;
}
body:not(.font-loaded) {
/* passt die Schriftart Arial an, um eine Textblockgröße ähnlich der
von "MyFont" zu erhalten, um Sprünge im Layout zu vermeiden, wenn
"MyFont" fertig geladen wurde */
letter-spacing: -0.05em;
word-spacing: 0.02em;
}
Laden und Anzeigen von Bildern
Bilder sind meist die Ressourcen, die den größten Teil des Traffics zur Anzeige einer Webseite ausmachen. Je nach Bildgröße und Geschwindigkeit der Internetverbindung kann es einige Zeit dauern, bis alle Bilder vollständig heruntergeladen sind.
Eine unschöne Eigenschaft von Bildern im Web ist, dass der Browser die Größe eines Bilds erst dann kennt, wenn die Header des Bilds heruntergeladen wurden. Wenn Sie die Bildgröße nicht manuell per CSS angeben, hat das Bild eine Höhe von Null bis seine Abmessungen bekannt sind, was dazu führen kann, dass Teile der Seite plötzlich nach unten springen, wenn die darüber liegenden Bilder geladen werden. Dieser so genannte “Cumulative Layout Shift” sorgt für eine schlechte User Experience und kann sogar dazu führen, dass User auf etwas ganz anderes klicken, als sie eigentlich wollten, wenn sich zwischen dem Drücken und Loslassen der Maustaste Teile der Seite verschoben haben (Nicken Sie jetzt im Geiste, falls Sie sich schon einmal darüber geärgert haben).
Beim Laden von Bildern müssen wir im Allgemeinen vier Dinge beachten:
- Es sollten nur Bilder geladen werden, die im Viewport sind oder bald sichtbar werden, um keinen Traffic zu verschwenden (sogenanntes Lazy Loading)
- Die Bilder sollten nur in der Größe heruntergeladen werden, in der sie angezeigt werden
- Das Bild wird in der richtigen Größe für den aktuellen Viewport angezeigt
- Beim Herunterladen eines Bilds sollte es keine Sprünge auf der Seite geben
Für das Lazy-Loading von Bildern fügten Webentwickler:innen früher eigenen JavaScript-Code ein, der regelmäßig prüfte, wann ein Bild im Viewport sichtbar wurde, um erst dann die URL der Bildquelle festzulegen, so dass die Browser mit dem Herunterladen des eigentlichen Bildes begannen.
Heutzutage fügt man einfach das Attribut loading="lazy"
zum Image-Tag hinzu. Es ist kein JavaScript mehr erforderlich.
Um ein Springen der Seite beim Herunterladen eines Bilds zu vermeiden, kann seine Größe vorab manuell festgelegt werden, vorausgesetzt sie ist bekannt. In responsiven Designs wollen wir die Größe von Bildern oft basierend auf der Größe des Viewports festlegen, z.B. auf 100% der Breite des Content-Bereichs unter Beibehaltung des Seitenverhältnisses. Eine Skalierung unter Berücksichtigung des Seitenverhältnisses war bis vor kurzem nicht so einfach zu erreichen.
Mit CSS konnte dies mit einem Hack erreicht werden, der die Tatsache ausnutzt, dass sich ein prozentualer Padding-Wert immer auf die Breite eines Elements bezieht, auch wenn das Padding auf der vertikalen Achse angewendet wird. Dadurch konnte man die Größe eines Bildes wie folgt festlegen, sodass das Verhältnis 16 zu 9 erhalten bleibt:
width: 100%;
height: 0;
padding-top: 56.25%; /* 9 / 16 * 100 */
Die Höhe von Null und das Padding konnten jedoch in Kombination mit anderen Stilen Probleme verursachen, so dass dies nie eine wirklich gute Lösung war.
Heute können wir einfach die Eigenschaft aspect-ratio verwenden:
width: 100%;
aspect-ratio: 16 / 9;
Das ist deutlich einfacher zu lesen und zu verstehen und hat auch noch weniger Begleiterscheinungen. Super!
Bei manchen responsiven Layouts wollen wir ein Bild vielleicht in einem anderen als seinem ursprünglichen Seitenverhältnis anzeigen. Das war lange Zeit mit <img>
-Tags nicht möglich, da das Bild sonst gestreckt oder verzerrt dargestellt wurde. Entwickler:innen nutzten stattdessen einfach Divs und setzten das Bild als Hintergrund, dessen Darstellung mit den Attributen background-size
und background-position
gesteuert werden konnte. Hinsichtlich der Semantik und Barrierefreiheit ist dies jedoch keine gute Lösung für Bilder, die Content der Seite und nicht nur Dekoration sind.
Heute können wir für Bilder einfach die Eigenschaften object-fit und object-position setzen, um das gleiche Verhalten zu erreichen.
Auch bei den Bildformaten hat es einige Fortschritte gegeben. Während das <picture>
-Element schon seit langem unterstützt wird, um das am besten geeignete Bildformat für den Browser zu laden, gibt es zwei Bereiche, in denen fast altertümliche Bildformate im heutigen Web immer noch weit verbreitet sind: Favicons und animierte Bilder.
Das favicon.ico ist ein Relikt, das wir anscheinend kaum loswerden können. Nicht nur ist das ICO-Format in seinen Möglichkeiten sehr begrenzt (begrenzte Farbpalette, keine Alpha-Transparenz), auch die Komprimierung ist sehr schwach. Viele Favicon-Generatoren erzeugen .ico-Dateien, die alle Größenvarianten des Favicons zusammen enthalten: 16x16px, 32x32px und 48x48px. Das kann manchmal eine Datei von bis zu 100 KB Größe erzeugen, nur um ein winziges Icon darzustellen. Welche Favicon-Formate heutzutage wirklich noch benötigt werden, wird unter Entwickler:innen ziemlich regelmäßig diskutiert, oft mit unterschiedlichen Ergebnissen.
Ein kurzer Test meinerseits mit allen aktuellen Browsern hat gezeigt, dass alle ein 32x32px großes PNG-Favicon einwandfrei anzeigen. Das sollte alles sein, was wir brauchen, wenn wir keine exotischen Clients unterstützen müssen. Dadurch haben wir eine viel kleinere Datei mit besserer Bildqualität als die gute alte ICO-Datei und wir müssen uns nicht auf Drittanbieter-Webseiten verlassen, um mehrere Favicon-Dateien für uns zu generieren.
Wenn Sie großen Wert auf die Bildqualität legen, können auch SVG-Favicons sehr nützlich sein, da sie sich durch ein wenig CSS in der SVG-Datei adaptiv an einen Dark Mode anpassen können. Leider werden sie von Safari erst ab Version 16 unterstützt, die noch nicht sehr weit verbreitet ist.
Für animierte Bilder gibt es seit langem das GIF-Format (oder wird es JIF ausgesprochen? 😜), aber wie ICO ist das Format in vielerlei Hinsicht stark limitiert: es hat eine geringe Farbtiefe, keine Alpha-Transparenz und eine begrenzte Dauer und Framerate.
Sowohl APNG als auch WebP sind deutlich bessere Alternativen, die beide von allen Browsern unterstützt werden. Sogar Giphy (trotz seines Namens) liefert jetzt standardmäßig WebP-Dateien in allen wichtigen Browsern aus. Die Tools zur Erzeugung dieser modernen Bildformate sind seltener als zur GIF-Erstellung, aber sie existieren.
Sofern Sie nicht gerade Video-Footage in animierte Bilder umwandeln wollen, könnten auch SVG-Animationen eine gute Option mit einer potentiell viel kleineren Dateigröße sein.
Scroll-Effekte
Irgendwann in den 2010er-Jahren wurden Scroll-Effekte auf vielen Webseiten en vogue, vor allem auf Marketing-Websites wie Agentur-Websites oder Produktseiten, welche jeweils eine Menge Teaser anzeigten, die den Viewport ausfüllten, während sie das native Scroll-Verhalten außer Kraft setzten und es den Nutzer:innen nur erlaubten, den vorherigen oder nächsten Teaser in den Viewport zu scrollen. Ähnlich, aber weniger nervig waren Content-Slider auf vielen Websites, die jeweils nur einen einzelnen Inhalt anzeigten und durch die man (oft horizontal) navigieren konnte, um neue Inhalte herein- und die vorherigen Inhalte wegzuschieben.
Da es nie eine Standardimplementierung für beide Patterns gab, entstanden viele verschiedene, oft fehlerbehaftete oder schwerfällige Implementierungen, die jede Menge eigenen JavaScript-Code oder aufgeblähte Libraries verwendeten.
Grundsätzlich sollten Sie es unterlassen, das native Scrollverhalten zu überschreiben und den Usern die Möglichkeit zu nehmen, frei zu scrollen, aber wenn sie es tun müssen, können Sie jetzt die CSS Scroll Snap-Attribute dafür nutzen, mit denen Sie festlegen können, zu welchem Teil eines Elements gescrollt werden soll und ob die Scrollposition immer auf dem Element einrasten soll oder nur dann, wenn der Benutzer in die unmittelbare Nähe des Elements gescrollt hat.
Auch Content-Slider lassen sich mit dieser Technologie einfacher realisieren.
Eine weitere Funktion, die man regelmäßig braucht, ist das animierten Scrollen zu einem bestimmten Punkt der Website nach einer Nutzerinteraktion, z.B. nach dem Drücken eines “zurück zum Seitenanfang”-Buttons. Dies kann nun leicht mit einer Zeile Code mit Element.scrollIntoView() erreicht werden:
document.body.scrollIntoView({ block: 'start', behavior: 'smooth' });
Beachten Sie, dass Smooth Scrolling in Safari erst ab Version 16 unterstützt wird. In früheren Versionen wird auch zum Ziel gescrollt, es wird aber nicht animiert.
Seitenlayout
Gaps in Flex Layouts
Glücklicherweise müssen wir uns seit Flex- und Grid-Layouts keine Gedanken mehr darüber machen, wie man die Elemente einfach zentriert, aber einige Dinge waren bisher weiterhin ziemlich schwierig.
Einheitliche Abstände zwischen Elementen in einem Flex-Layout konnten sich als nervig erweisen, insbesondere in responsiven Layouts, in denen Elemente in manchen Viewports umbrechen können. Eine recht flexible Möglichkeit bestand darin, einheitliche Margins in alle Richtungen auf die Flex-Elemente anzuwenden. Dies würde jedoch auch einen Abstand zum Rand des Containers erzeugen, was oft unerwünscht ist, so dass negative Margins auf den Container angewandt werden mussten, um die Margins der Flex-Elemente visuell auszugleichen. Dies wiederum könnte jedoch zu Problemen mit dem Parent-Element des Flex-Containers führen.
Im CSS Grid Layout wurde später die Eigenschaft gap
eingeführt, die dieses Problem löste, da sie Abstände nur zwischen den Grid-Elementen, nicht aber am Anfang und Ende der Grid-Achsen hinzufügte. Manchmal ist die Verwendung von Grids für einfache Layouts ein wenig übertrieben, zum Glück hat die Eigenschaft gap inzwischen aber auch im Flexbox-Layout browserübergreifend Einzug gehalten.
Intrinsische Elementgrößen
Eine weitere Verbesserung, die mit dem CSS Grid Layout eingeführt wurde und nun auch außerhalb davon verfügbar ist, sind Intrinsische Elementgrößen. Dieser etwas komplizierte Begriff bedeutet, dass Sie jetzt die Abmessungen eines Elements auf die Größe einstellen können, die sein Inhalt einnimmt. Schauen wir uns das anhand der width
-Eigenschaft an:
width: max-content
ist die Breite, die der Inhalt einnehmen würde, ohne in mehrere Zeilen umzubrechenwidth: min-content
ist die Mindestbreite, die der Inhalt inklusive Umbrüchen einnehmen kann, was in der Regel der Breite des längsten Worts entspricht (wenn die Silbentrennung deaktiviert ist)width: fit-content
verwendet die jeweils kleinere Breite aus “max-content” und der Breite des Containers
Dies ist besonders nützlich, wenn Sie wiederverwendbare Komponenten mit variablem Inhalt erstellen, dessen Länge Sie im Voraus nicht kennen können.
Richtungsabhängige Größen und Abstände
Wenn Sie schon einmal an einem internationalisierten Produkt gearbeitet haben, das Sprachen mit unterschiedlichen Textrichtungen unterstützen muss, wissen Sie, dass CSS-Layouts dadurch viel komplizierter werden. Angenommen, Sie haben einen Button mit einem Textlabel und einem optionalen Icon vor dem Label und möchten einen kleinen Abstand zwischen Icon und Textlabel einfügen.
Wenn Sie nicht die gap
-Eigenschaft in Grid- oder Flex-Layouts nutzen können und stattdessen margin
and padding
verwenden müssen, würde die Verwendung von margin-right
für das Icon scheinbar ausreichen, aber das gilt nur für Sprachen wie Deutsch, die erst von links nach rechts und dann von oben nach unten gelesen werden. Bei arabischem Text, der von rechts nach links und dann oben nach unten gelesen wird, würde das Icon rechts vom Label erscheinen, so dass der Abstand auf der falschen Seite wäre. Bei Japanisch, das erst von oben nach unten und dann rechts nach links gelesen wird, wäre es nochmal anders.
Man könnte die Richtung der Margins für die verschiedenen Sprachen überschreiben, aber das für jedes Element zu tun, erhöht die Komplexität des Codes enorm. Zum Glück gibt es jetzt CSS-Eigenschaften, die die Textrichtung berücksichtigen:
margin-inline-start
und margin-inline-end
funktionieren in der Hauptleserichtung des Textes, d.h. in einer links nach rechts, dann oben nach unten-Sprache wie Deutsch würden sie margin-left
und margin-right
entsprechen. Umgekehrt funktionieren margin-block-start
und margin-block-end
auf der anderen Achse, sie würden also margin-top
und margin-bottom
im Deutschen entsprechen. Somit braucht man nichts mehr zu überschreiben, da sich die Abstände automatisch an die Leserichtung anpassen, z.B. wäre margin-inline-start
gleichbedeutend mit margin-top
anstelle von margin-left
im Japanischen.
Für die Größe von Elementen gibt es ähnliche Attribute: inline-size
und block-size
können die Eigenschaften width
bzw. height
ersetzen.
Environment-Variablen
Als Apple 2017 das erstes iPhone mit einer Notch vorstellte, erzeugte das die Herausforderung, dass die Notch Teile einer Webseite verdecken konnte, wenn diese im Vollbildmodus im Querformat angezeigt wurde. Standardmäßig verkleinerte Apple den Viewport im Querformat einfach horizontal, gab aber Entwickler:innen die Möglichkeit, mit einem speziellen Viewport-Meta-Tag den gesamten Platz des Displays zu nutzen. Um die Notch zu berücksichtigen, führte Apple CSS-Konstanten ein, um die Einzüge für den sicheren Bereich innerhalb des Viewports bereitzustellen, der nicht verdeckt wird.
Daraus hat sich der offizielle CSS Environment Variables-Standard entwickelt, der inzwischen von allen wichtigen Browsern unterstützt wird. Er kann auch für Progressive Web Apps verwendet werden, die auf Desktop-Computern in einem eigenen Fenster gestartet werden, um die Fenstersteuerungs-Buttons in der Titelleiste zu berücksichtigen.
Fazit
Wir haben uns mit einigen neuen Webfunktionen in den Bereichen Webfonts, Bildoptimierung, Scroll-Effekte und Seitenlayouts vertraut gemacht, die seit kurzem browserübergreifend unterstützt werden und nun problemlos in Webprojekten eingesetzt werden können.
Ich hoffe, dass diese Tipps nützlich waren und Ihnen helfen, bei Ihrem nächsten Projekt einige Probleme schneller und mit weniger Code zu lösen.
Da der Artikel bereits ziemlich lang geworden ist, konnte ich keine weiteren HTML- und CSS-Neuerungen mit aktueller Cross-Browser-Unterstützung aufnehmen, insbesondere neue CSS-Selektoren, Formularelemente und Theming-Möglichkeiten, die eventuell Teil eines weiteren zukünftigen Artikels werden.