Dem Attribut "lang" kann nur eine Sprache zugewiesen werden. Das bedeutet, dass das Attribut <html>
nur eine Sprache haben kann, auch wenn die Seite mehrere Sprachen enthält. Legen Sie lang
auf die primäre Sprache der Seite fest.
<html lang="ar,en,fr,pt">...</html>Mehrere Sprachen werden nicht unterstützt.
<html lang="ar">...</html>Lege nur die Hauptsprache der Seite fest. In diesem Fall ist die Sprache Arabisch.
Links
Ähnlich wie bei Schaltflächen geht der barrierefreie Name bei Links hauptsächlich aus den Textinhalten hervor. Ein guter Trick beim Erstellen eines Links besteht darin, den aussagekräftigsten Text in den Link selbst einzufügen, anstatt Füllwörter wie „Hier“ oder „Mehr erfahren“ zu verwenden.
Check out our guide to web performance <a href="/guide">here</a>.
Check out <a href="/guide">our guide to web performance</a>.
Prüfen, ob eine Animation das Layout auslöst
Eine Animation, die ein Element mit einem anderen Wert als transform
bewegt, ist wahrscheinlich langsam.
Im folgenden Beispiel habe ich dasselbe visuelle Ergebnis mit der Animation von top
und left
und der Verwendung von transform
erzielt.
.box { position: absolute; top: 10px; left: 10px; animation: move 3s ease infinite; } @keyframes move { 50% { top: calc(90vh - 160px); left: calc(90vw - 200px); } }
.box { position: absolute; top: 10px; left: 10px; animation: move 3s ease infinite; } @keyframes move { 50% { transform: translate(calc(90vw - 200px), calc(90vh - 160px)); } }
Du kannst dies in den folgenden zwei Glitch-Beispielen testen und die Leistung mit den Entwicklertools untersuchen.
Mit demselben Markup können wir padding-top: 56.25%
durch aspect-ratio: 16 / 9
ersetzen und aspect-ratio
auf ein bestimmtes Verhältnis von width
zu height
setzen.
.container { width: 100%; padding-top: 56.25%; }
.container { width: 100%; aspect-ratio: 16 / 9; }
Die Verwendung von aspect-ratio
anstelle von padding-top
ist wesentlich übersichtlicher und das Padding-Attribut wird nicht geändert, um Aktionen außerhalb des üblichen Umfangs auszuführen.
Ja, das stimmt. Ich verwende reduce
, um eine Reihe von Versprechen zu verketten. Ich bin sehr schlau. Aber diese Programmierung ist so clever, auf die Sie verzichten sollten.
Wenn Sie den obigen Befehl jedoch in eine asynchrone Funktion umwandeln, ist es verlockend, zu sequenziell:
async function logInOrder(urls) { for (const url of urls) { const response = await fetch(url); console.log(await response.text()); } }Sieht viel ordentlicher aus, aber der zweite Abruf beginnt erst, wenn der erste Abruf vollständig gelesen wurde usw. Dies ist viel langsamer als das Promise-Beispiel, bei dem die Abrufe parallel ausgeführt werden. Zum Glück gibt es einen idealen Mittelweg.
function markHandled(...promises) { Promise.allSettled(promises); } async function logInOrder(urls) { // fetch all the URLs in parallel const textPromises = urls.map(async (url) => { const response = await fetch(url); return response.text(); }); markHandled(...textPromises); // log them in sequence for (const textPromise of textPromises) { console.log(await textPromise); } }In diesem Beispiel werden die URLs parallel abgerufen und gelesen, aber das „intelligente“
reduce
-Bit wird durch eine langweilige, lesbare For-Schleife ersetzt.
Benutzerdefinierte Houdini-Eigenschaften schreiben
Hier sehen Sie ein Beispiel für das Festlegen einer benutzerdefinierten Eigenschaft (z. B. CSS-Variable), allerdings mit einer Syntax (Typ), einem Ausgangswert (Fallback) und einer booleschen Vererbung (übernimmt dann der Wert des übergeordneten Elements oder nicht?). Aktuell erfolgt dies über CSS.registerProperty()
in JavaScript, aber in Chromium 85 und höher wird die @property
-Syntax in Ihren CSS-Dateien unterstützt:
CSS.registerProperty({ name: '--colorPrimary', syntax: '', initialValue: 'magenta', inherits: false });
@property --colorPrimary { syntax: ''; initial-value: magenta; inherits: false; }
Jetzt können Sie wie auf jede andere benutzerdefinierte CSS-Eigenschaft über var(--colorPrimary)
auf --colorPrimary
zugreifen. Der Unterschied besteht jedoch darin, dass --colorPrimary
nicht einfach als String gelesen wird. Es hat Daten!
Mit CSS backdrop-filter
werden ein oder mehrere Effekte auf ein Element angewendet, das durchscheinend oder transparent ist. Sehen Sie sich dazu die folgenden Bilder an.
![Ein Dreieck überlagert einen Kreis. Der Kreis kann nicht durch das Dreieck gesehen werden.](https://web.developers.google.cn/static/examples/image/admin/LOqxvB3qqVkbZBmxMmKS.png?hl=de)
.frosty-glass-pane { backdrop-filter: blur(2px); }
![Ein Dreieck überlagert einen Kreis. Das Dreieck ist durchscheinend, sodass der Kreis durch es hindurchzublicken ist.](https://web.developers.google.cn/static/examples/image/admin/VbyjpS6Td39E4FudeiVg.png?hl=de)
.frosty-glass-pane { opacity: .9; backdrop-filter: blur(2px); }
Das Bild links zeigt, wie sich überlappende Elemente gerendert würden, wenn backdrop-filter
nicht verwendet oder unterstützt würde. Im Bild rechts wird mit backdrop-filter
ein Unkenntlichmachungseffekt angewendet. Sie sehen, dass opacity
zusätzlich zu backdrop-filter
verwendet wird. Ohne opacity
gäbe es nichts, was unkenntlich gemacht werden könnte. Selbstverständlich gibt es keine Auswirkungen auf den Hintergrund, wenn opacity
auf 1
(völlig undurchsichtig) festgelegt ist.
Im Gegensatz zum unload
-Ereignis kann beforeunload
jedoch zu legitimen Zwecken verwendet werden. Wenn Sie beispielsweise den Nutzer warnen möchten, dass nicht gespeicherte Änderungen verloren gehen, wenn er die Seite verlässt. In diesem Fall empfiehlt es sich, beforeunload
-Listener nur dann hinzuzufügen, wenn ein Nutzer nicht gespeicherte Änderungen hat, und sie anschließend zu entfernen, sobald die nicht gespeicherten Änderungen gespeichert wurden.
window.addEventListener('beforeunload', (event) => { if (pageHasUnsavedChanges()) { event.preventDefault(); return event.returnValue = 'Are you sure you want to exit?'; } });Der obige Code fügt bedingungslos einen
beforeunload
-Listener hinzu.
function beforeUnloadListener(event) { event.preventDefault(); return event.returnValue = 'Are you sure you want to exit?'; }; // A function that invokes a callback when the page has unsaved changes. onPageHasUnsavedChanges(() => { window.addEventListener('beforeunload', beforeUnloadListener); }); // A function that invokes a callback when the page's unsaved changes are resolved. onAllChangesSaved(() => { window.removeEventListener('beforeunload', beforeUnloadListener); });Mit dem Code oben wird der
beforeunload
-Listener nur bei Bedarf hinzugefügt und entfernt.
Verwendung von Cache-Control: no-store
minimieren
Cache-Control: no-store
ist ein HTTP-Header, den Webserver für Antworten festlegen können. Er weist den Browser an, die Antwort nicht in einem HTTP-Cache zu speichern. Dies sollte für Ressourcen verwendet werden, die vertrauliche Nutzerdaten enthalten, z. B. Seiten, für die eine Anmeldung erforderlich ist.
Das fieldset
-Element, das alle Eingabegruppen (.fieldset-item
) enthält, verwendet gap: 1px
, um die Haarlinienränder zwischen den Elementen zu erstellen. Keine schwierige Rahmenlösung!
.grid { display: grid; gap: 1px; background: var(--bg-surface-1); & > .fieldset-item { background: var(--bg-surface-2); } }
.grid { display: grid; & > .fieldset-item { background: var(--bg-surface-2); &:not(:last-child) { border-bottom: 1px solid var(--bg-surface-1); } } }
Natürliches Raster
Das komplexeste Layout war schließlich das Makro-Layout, das logische Layoutsystem zwischen <main>
und <form>
.
<input type="checkbox" id="text-notifications" name="text-notifications" >
<label for="text-notifications"> <h3>Text Messages</h3> <small>Get notified about all text messages sent to your device</small> </label>
Das fieldset
-Element, das alle Eingabegruppen (.fieldset-item
) enthält, verwendet gap: 1px
, um die Haarlinienränder zwischen den Elementen zu erstellen. Keine schwierige Rahmenlösung!
.grid { display: grid; gap: 1px; background: var(--bg-surface-1); & > .fieldset-item { background: var(--bg-surface-2); } }
.grid { display: grid; & > .fieldset-item { background: var(--bg-surface-2); &:not(:last-child) { border-bottom: 1px solid var(--bg-surface-1); } } }
Tab-Layout (<header>
)
Das nächste Layout ist fast dasselbe: Ich verwende Flex, um eine vertikale Reihenfolge zu erzeugen.
<snap-tabs> <header> <nav></nav> <span class="snap-indicator"></span> </header> <section></section> </snap-tabs>
header { display: flex; flex-direction: column; }
Das .snap-indicator
-Element sollte sich horizontal mit der Gruppe von Links bewegen. Dieses Header-Layout hilft dabei, diesen Bereich festzulegen. Keine absolut positionierten Elemente vorhanden!
Gentle Flex ist eine Strategie, die sich ausschließlich auf die Zentrierung konzentriert. Es ist weich und sanft, da im Gegensatz zu place-content: center
die Größe der Kinderverpackungen während der Zentrierung nicht geändert wird. So vorsichtig wie möglich werden alle Elemente gestapelt, zentriert und mit Abstand angeordnet.
.gentle-flex {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 1ch;
}
- Übernimmt nur Ausrichtung, Richtung und Verteilung
- Änderungen und Pflege an einem Ort
- Der Abstand garantiert gleichmäßige Abstände zwischen n untergeordneten Elementen.
- Die meisten Codezeilen
Ideal für Makro- und Mikro-Layouts.
Nutzung
gap
akzeptiert beliebige CSS-Werte length oder percentage als Wert.
.gap-example {
display: grid;
gap: 10px;
gap: 2ch;
gap: 5%;
gap: 1em;
gap: 3vmax;
}
Die Lücke kann mit einer Länge übergeben werden, die sowohl für die Zeile als auch für die Spalte verwendet wird.
.grid { display: grid; gap: 10px; }Zeilen und Spalten gleichzeitig gemeinsam festlegen
.grid { display: grid; row-gap: 10px; column-gap: 10px; }
Es können 2 Längen übergeben werden, die für die Zeile und die Spalte verwendet werden.
.grid { display: grid; gap: 10px 5%; }Zeilen und Spalten separat gleichzeitig festlegen
.grid { display: grid; row-gap: 10px; column-gap: 5%; }