Vergleichen &vergleichen

Dem Attribut „lang“ kann nur eine Sprache zugeordnet werden. Das bedeutet, dass das <html>-Attribut nur eine Sprache haben kann, auch wenn die Seite mehrere Sprachen enthält. Legen Sie für lang die primäre Sprache der Seite fest.

Don'ts
<html lang="ar,en,fr,pt">...</html>
Mehrere Sprachen werden nicht unterstützt.
Do
<html lang="ar">...</html>
Legen Sie nur die primäre Sprache der Seite fest. In diesem Fall ist die Sprache Arabisch.

Ähnlich wie bei Schaltflächen wird der für Screenreader zugängliche Name von Links hauptsächlich aus dem Textinhalt abgeleitet. 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 „Weitere Informationen“ zu verwenden.

Nicht prägnant genug
Check out our guide to web performance <a href="/guide">here</a>.
Nützliche Inhalte!
Check out <a href="/guide">our guide to web performance</a>.

Prüfen, ob eine Animation das Layout auslöst

Eine Animation, bei der ein Element nicht mit transform verschoben wird, ist wahrscheinlich langsam. Im folgenden Beispiel habe ich dasselbe visuelle Ergebnis erzielt, indem ich top und left animiert und transform verwendet habe.

Don'ts
.box {
  position: absolute;
  top: 10px;
  left: 10px;
  animation: move 3s ease infinite;
}

@keyframes move {
  50% {
     top: calc(90vh - 160px);
     left: calc(90vw - 200px);
  }
}
Do
.box {
  position: absolute;
  top: 10px;
  left: 10px;
  animation: move 3s ease infinite;
}

@keyframes move {
  50% {
     transform: translate(calc(90vw - 200px), calc(90vh - 160px));
  }
}

Sie können dies in den folgenden beiden Glitch-Beispielen testen und die Leistung mit den Entwicklertools analysieren.

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 ÷ height festlegen.

padding-top verwenden
.container {
  width: 100%;
  padding-top: 56.25%;
}
„aspect-ratio“ verwenden
.container {
  width: 100%;
  aspect-ratio: 16 / 9;
}

Die Verwendung von aspect-ratio anstelle von padding-top ist viel verständlicher und die Eigenschaft „padding“ wird nicht überarbeitet, um etwas außerhalb ihres üblichen Umfangs zu tun.

Ja, das ist richtig. Ich verwende reduce, um eine Abfolge von Versprechen zu verketten. Ich bin so klug. Aber das ist ein bisschen zu smart, um es zu verwenden.

Bei der Umwandlung in eine asynchrone Funktion ist es jedoch verlockend, zu sequentiell vorzugehen:

Nicht empfohlen – zu sequentiell
async function logInOrder(urls) {
  for (const url of urls) {
    const response = await fetch(url);
    console.log(await response.text());
  }
}
Sieht viel übersichtlicher aus, aber der zweite Abruf beginnt erst, wenn der erste Abruf vollständig gelesen wurde, und so weiter. Das ist viel langsamer als das Beispiel mit Promises, bei dem die Abrufe parallel ausgeführt werden. Glücklicherweise gibt es einen idealen Mittelweg.
Empfohlen – schön parallel
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 standardmäßige, langweilige, lesbare For-Schleife ersetzt.

Benutzerdefinierte Houdini-Eigenschaften schreiben

Hier ein Beispiel für die Einstellung einer benutzerdefinierten Property (vergleichbar mit einer CSS-Variablen), jetzt aber mit einer Syntax (Typ), einem Anfangswert (Fallback) und einer booleschen Vererbung (wird der Wert vom übergeordneten Element übernommen oder nicht?). Derzeit ist dies nur über CSS.registerProperty() in JavaScript möglich. Ab Chromium 85 wird die @property-Syntax jedoch auch in CSS-Dateien unterstützt:

Separate JavaScript-Datei (Chromium 78)
CSS.registerProperty({
  name: '--colorPrimary',
  syntax: '',
  initialValue: 'magenta',
  inherits: false
});
In der CSS-Datei enthalten (Chromium 85)
@property --colorPrimary {
  syntax: '';
  initial-value: magenta;
  inherits: false;
}

Sie können jetzt wie bei jeder anderen benutzerdefinierten CSS-Eigenschaft über var(--colorPrimary) auf --colorPrimary zugreifen. Der Unterschied besteht jedoch darin, dass --colorPrimary nicht nur als String gelesen wird. Es gibt Daten!

Mit CSS backdrop-filter werden ein oder mehrere Effekte auf ein Element angewendet, das durchscheinend oder transparent ist. Die folgenden Bilder veranschaulichen das.

Keine Transparenz im Vordergrund
Ein Dreieck, das auf einem Kreis liegt. Der Kreis ist durch das Dreieck nicht zu sehen.
.frosty-glass-pane {
  backdrop-filter: blur(2px);
}
Transparenz im Vordergrund
Ein Dreieck, das auf einem Kreis liegt. Das Dreieck ist durchscheinend, sodass der Kreis hindurch sichtbar ist.
.frosty-glass-pane {
  opacity: .9;
  backdrop-filter: blur(2px);
}

Das Bild auf der linken Seite zeigt, wie sich überlappende Elemente darstellen würden, wenn backdrop-filter nicht verwendet oder unterstützt würde. Auf dem Bild rechts wurde mit backdrop-filter ein Weichzeichnereffekt angewendet. Beachten Sie, dass neben backdrop-filter auch opacity verwendet wird. Ohne opacity gäbe es nichts, auf das die Unkenntlichmachung angewendet werden könnte. Wenn opacity auf 1 (vollkommen opak) gesetzt ist, hat das natürlich keine Auswirkungen auf den Hintergrund.

Im Gegensatz zum unload-Ereignis gibt es jedoch legitime Verwendungsmöglichkeiten für beforeunload. Beispielsweise, wenn Sie den Nutzer warnen möchten, dass seine nicht gespeicherten Änderungen verloren gehen, wenn er die Seite verlässt. In diesem Fall empfehlen wir, beforeunload-Listener nur hinzuzufügen, wenn ein Nutzer nicht gespeicherte Änderungen hat, und sie dann sofort wieder zu entfernen, nachdem die nicht gespeicherten Änderungen gespeichert wurden.

Don'ts
window.addEventListener('beforeunload', (event) => {
  if (pageHasUnsavedChanges()) {
    event.preventDefault();
    return event.returnValue = 'Are you sure you want to exit?';
  }
});
Mit dem Code oben wird ein beforeunload-Listener ohne Bedingungen hinzugefügt.
Do
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);
});
Im obigen Code wird der beforeunload-Listener nur hinzugefügt, wenn er benötigt wird, und entfernt, wenn er nicht benötigt wird.

Nutzung von Cache-Control: no-store minimieren

Cache-Control: no-store ist ein HTTP-Header, den Webserver in Antworten festlegen können, um den Browser anzuweisen, die Antwort nicht in einem HTTP-Cache zu speichern. Dieser sollte für Ressourcen verwendet werden, die vertrauliche Nutzerinformationen enthalten, z. B. Seiten, die durch eine Anmeldung geschützt sind.

Das Element fieldset, das jede Eingabegruppe (.fieldset-item) enthält, verwendet gap: 1px, um die Haarstrichränder zwischen den Elementen zu erstellen. Keine komplizierte Lösung für den Rahmen!

Geschlossene Lücke
.grid {
  display: grid;
  gap: 1px;
  background: var(--bg-surface-1);

  & > .fieldset-item {
    background: var(--bg-surface-2);
  }
}
Rahmentrick
.grid {
  display: grid;

  & > .fieldset-item {
    background: var(--bg-surface-2);

    &:not(:last-child) {
      border-bottom: 1px solid var(--bg-surface-1);
    }
  }
}

Natürlicher Rasterumbruch

Das komplexeste Layout war das Makro-Layout, das logische Layoutsystem zwischen <main> und <form>.

Eingabe
<input
  type="checkbox"
  id="text-notifications"
  name="text-notifications"
>
Label
<label for="text-notifications">
  <h3>Text Messages</h3>
  <small>Get notified about all text messages sent to your device</small>
</label>

Das Element fieldset, das jede Eingabegruppe (.fieldset-item) enthält, verwendet gap: 1px, um die Haarstrichränder zwischen den Elementen zu erstellen. Keine komplizierte Lösung für Rahmen!

Geschlossene Lücke
.grid {
  display: grid;
  gap: 1px;
  background: var(--bg-surface-1);

  & > .fieldset-item {
    background: var(--bg-surface-2);
  }
}
Rahmentrick
.grid {
  display: grid;

  & > .fieldset-item {
    background: var(--bg-surface-2);

    &:not(:last-child) {
      border-bottom: 1px solid var(--bg-surface-1);
    }
  }
}

<header>-Layout für Tabs

Das nächste Layout ist fast identisch: Ich verwende Flex, um eine vertikale Anordnung zu erstellen.

HTML
<snap-tabs>
  <header>
    <nav></nav>
    <span class="snap-indicator"></span>
  </header>
  <section></section>
</snap-tabs>
CSS
header {
  display: flex;
  flex-direction: column;
}

Das .snap-indicator sollte horizontal mit der Gruppe von Links wandern. Dieses Kopfzeilenlayout trägt dazu bei, diese Bühne zu schaffen. Hier gibt es keine absolut positionierten Elemente.

„Sanftes Flexen“ ist eine Strategie, bei der nur das Zentrieren im Vordergrund steht. Die Animation ist sanft und dezent, da im Gegensatz zu place-content: center die Größe der Kinderfelder während der Zentrierung nicht geändert wird. Alle Elemente werden so schonend wie möglich gestapelt, zentriert und platziert.

.gentle-flex {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1ch;
}
Vorteile
  • Nur Ausrichtung, Richtung und Verteilung
  • Änderungen und Wartung an einem Ort
  • Mit „Gap“ wird ein gleichmäßiger Abstand zwischen n untergeordneten Elementen garantiert.
Nachteile
  • Die meisten Codezeilen

Gut geeignet für Makro- und Mikrolayouts.

Nutzung

gap akzeptiert als Wert jede CSS-Länge oder Prozentzahl.

.gap-example {
  display: grid;
  gap: 10px;
  gap: 2ch;
  gap: 5%;
  gap: 1em;
  gap: 3vmax;
}


Für „Gap“ kann eine Länge von „1“ übergeben werden, die sowohl für Zeilen als auch für Spalten verwendet wird.

Kurzschreibweise
.grid {
  display: grid;
  gap: 10px;
}
So legen Sie sowohl Zeilen als auch Spalten gleichzeitig fest
Maximiert
.grid {
  display: grid;
  row-gap: 10px;
  column-gap: 10px;
}


Für „Lücke“ können zwei Längen übergeben werden, die für Zeile und Spalte verwendet werden.

Kurzschreibweise
.grid {
  display: grid;
  gap: 10px 5%;
}
Zeilen und Spalten separat gleichzeitig festlegen
Maximiert
.grid {
  display: grid;
  row-gap: 10px;
  column-gap: 5%;
}