Vergleichen &vergleichen

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.

Don'ts
<html lang="ar,en,fr,pt">...</html>
Mehrere Sprachen werden nicht unterstützt.
Das sollten Sie tun:
<html lang="ar">...</html>
Lege nur die Hauptsprache der Seite fest. In diesem Fall ist die Sprache Arabisch.

Ä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.

Nicht aussagekräftig 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, 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.

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);
  }
}
Das sollten Sie tun:
.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.

„Padding-oben“ verwenden
.container {
  width: 100%;
  padding-top: 56.25%;
}
Verwendung des Seitenverhältnisses
.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:

Nicht empfohlen – 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.
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 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:

Separate JavaScript-Datei (Chromium 78)
CSS.registerProperty({
  name: '--colorPrimary',
  syntax: '',
  initialValue: 'magenta',
  inherits: false
});
In der CSS-Datei (Chromium 85) enthalten
@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.

Keine Transparenz im Vordergrund
Ein Dreieck überlagert einen Kreis. Der Kreis kann nicht durch das Dreieck gesehen werden.
.frosty-glass-pane {
  backdrop-filter: blur(2px);
}
Transparenz im Vordergrund
Ein Dreieck überlagert einen Kreis. Das Dreieck ist durchscheinend, sodass der Kreis durch es hindurchzublicken ist.
.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.

Don'ts
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.
Das sollten Sie tun:
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!

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

  & > .fieldset-item {
    background: var(--bg-surface-2);
  }
}
Rahmen-Trick
.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>.

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 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!

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

  & > .fieldset-item {
    background: var(--bg-surface-2);
  }
}
Rahmen-Trick
.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.

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-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;
}
Vorteile
  • Übernimmt nur Ausrichtung, Richtung und Verteilung
  • Änderungen und Pflege an einem Ort
  • Der Abstand garantiert gleichmäßige Abstände zwischen n untergeordneten Elementen.
Nachteile
  • 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.

Kurzschrift
.grid {
  display: grid;
  gap: 10px;
}
Zeilen und Spalten gleichzeitig gemeinsam festlegen
Maximiert
.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.

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