Comparer & CompareCaption

L'attribut lang ne peut être associé qu'à une seule langue. Cela signifie que l'attribut <html> ne peut avoir qu'une seule langue, même si plusieurs langues sont utilisées sur la page. Définissez lang sur la langue principale de la page.

À éviter
<html lang="ar,en,fr,pt">...</html>
Les langues multiples ne sont pas acceptées.
À faire
<html lang="ar">...</html>
Définissez uniquement la langue principale de la page. Dans ce cas, la langue est l'arabe.

Comme pour les boutons, le nom accessible des liens provient principalement de leur contenu textuel. Lorsque vous créez un lien, il est judicieux de placer le texte le plus pertinent dans le lien lui-même, plutôt que d'utiliser des mots de remplissage comme "Ici" ou "En savoir plus".

Pas assez descriptif
Check out our guide to web performance <a href="/guide">here</a>.
Contenu utile !
Check out <a href="/guide">our guide to web performance</a>.

Vérifier si une animation déclenche une mise en page

Une animation qui déplace un élément à l'aide d'un autre élément que transform est susceptible d'être lente. Dans l'exemple suivant, j'ai obtenu le même résultat visuel en animant top et left, et en utilisant transform.

À éviter
.box {
  position: absolute;
  top: 10px;
  left: 10px;
  animation: move 3s ease infinite;
}

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

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

Vous pouvez le tester dans les deux exemples Glitch suivants et explorer les performances à l'aide de DevTools.

Avec le même balisage, nous pouvons remplacer padding-top: 56.25% par aspect-ratio: 16 / 9, en définissant aspect-ratio sur un ratio spécifié de width / height.

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

L'utilisation de aspect-ratio au lieu de padding-top est beaucoup plus claire et ne révise pas la propriété de marge intérieure pour effectuer une action en dehors de son champ d'application habituel.

Oui, c'est bien cela. J'utilise reduce pour enchaîner une séquence de promesses. Je suis tellement intelligent. Mais il s'agit d'un code trop intelligent dont vous pouvez vous passer.

Toutefois, lorsque vous convertissez ce code en fonction asynchrone, il est tentant d'être trop séquentiel:

Non recommandé : trop séquentiel
async function logInOrder(urls) {
  for (const url of urls) {
    const response = await fetch(url);
    console.log(await response.text());
  }
}
Cela semble beaucoup plus propre, mais ma deuxième récupération ne commence pas tant que la première n'a pas été entièrement lue, et ainsi de suite. Cette approche est beaucoup plus lente que l'exemple de promesses qui effectue les récupérations en parallèle. Heureusement, il existe un juste milieu idéal.
Recommandé : bien parallèle
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);
  }
}
Dans cet exemple, les URL sont récupérées et lues en parallèle, mais le bit reduce "intelligent" est remplacé par une boucle for standard, ennuyeuse et lisible.

Écrire des propriétés personnalisées Houdini

Voici un exemple de définition d'une propriété personnalisée (pensez à une variable CSS), mais avec une syntaxe (type), une valeur initiale (valeur de remplacement) et une valeur booléenne d'héritage (hérite-t-elle de la valeur de son parent ou non ?). La méthode actuelle consiste à utiliser CSS.registerProperty() en JavaScript, mais à partir de Chromium 85, la syntaxe @property sera prise en charge dans vos fichiers CSS:

Fichier JavaScript distinct (Chromium 78)
CSS.registerProperty({
  name: '--colorPrimary',
  syntax: '',
  initialValue: 'magenta',
  inherits: false
});
Inclus dans le fichier CSS (Chromium 85)
@property --colorPrimary {
  syntax: '';
  initial-value: magenta;
  inherits: false;
}

Vous pouvez désormais accéder à --colorPrimary comme à n'importe quelle autre propriété CSS personnalisée, via var(--colorPrimary). Cependant, la différence ici est que --colorPrimary n'est pas simplement lu comme une chaîne. Il contient des données !

CSS backdrop-filter applique un ou plusieurs effets à un élément translucide ou transparent. Pour comprendre cela, regardez les images ci-dessous.

Aucune transparence au premier plan
Triangle superposé à un cercle. Le cercle ne peut pas être vu à travers le triangle.
.frosty-glass-pane {
  backdrop-filter: blur(2px);
}
Transparence au premier plan
Triangle superposé à un cercle. Le triangle est translucide, ce qui permet de voir le cercle à travers lui.
.frosty-glass-pane {
  opacity: .9;
  backdrop-filter: blur(2px);
}

L'image de gauche montre comment les éléments se chevauchant seraient affichés si backdrop-filter n'était pas utilisé ou n'était pas compatible. L'image de droite applique un effet de floutage à l'aide de backdrop-filter. Notez qu'il utilise opacity en plus de backdrop-filter. Sans opacity, il n'y aurait rien à flouter. Il va presque de soi que si opacity est défini sur 1 (entièrement opaque), l'arrière-plan n'est pas affecté.

Cependant, contrairement à l'événement unload, beforeunload peut être utilisé de manière légitime. Par exemple, lorsque vous souhaitez avertir l'utilisateur qu'il a des modifications non enregistrées qu'il perdra s'il quitte la page. Dans ce cas, nous vous recommandons de n'ajouter des écouteurs beforeunload que lorsqu'un utilisateur a des modifications non enregistrées, puis de les supprimer immédiatement après l'enregistrement des modifications non enregistrées.

À éviter
window.addEventListener('beforeunload', (event) => {
  if (pageHasUnsavedChanges()) {
    event.preventDefault();
    return event.returnValue = 'Are you sure you want to exit?';
  }
});
Le code ci-dessus ajoute un écouteur beforeunload sans condition.
À faire
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);
});
Le code ci-dessus n'ajoute l'écouteur beforeunload que lorsqu'il est nécessaire (et le supprime lorsqu'il ne l'est pas).

Minimiser l'utilisation de Cache-Control: no-store

Cache-Control: no-store est un en-tête HTTP que les serveurs Web peuvent définir sur les réponses pour indiquer au navigateur de ne pas stocker la réponse dans un cache HTTP. Cette valeur doit être utilisée pour les ressources contenant des informations utilisateur sensibles, par exemple les pages derrière une connexion.

L'élément fieldset, qui contient chaque groupe d'entrée (.fieldset-item), utilise gap: 1px pour créer les bordures fines entre les éléments. Aucune solution de bordure délicate !

Espace rempli
.grid {
  display: grid;
  gap: 1px;
  background: var(--bg-surface-1);

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

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

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

Retour à la ligne naturel dans la grille

La mise en page la plus complexe s'est avérée être la mise en page macro, le système de mise en page logique entre <main> et <form>.

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

L'élément fieldset, qui contient chaque groupe d'entrée (.fieldset-item), utilise gap: 1px pour créer les bordures fines entre les éléments. Aucune solution de bordure délicate !

Espace rempli
.grid {
  display: grid;
  gap: 1px;
  background: var(--bg-surface-1);

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

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

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

Mise en page <header> des onglets

La mise en page suivante est presque identique: j'utilise flex pour créer un ordre vertical.

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

.snap-indicator doit se déplacer horizontalement avec le groupe de liens, et cette mise en page d'en-tête permet de le faire. Aucun élément positionné de manière absolue ici !

Gentle Flex est une stratégie de centrage uniquement plus fidèle. Il est doux et délicat, car contrairement à place-content: center, aucune taille de boîte enfant n'est modifiée lors du centrage. Tous les éléments sont empilés, centrés et espacés aussi délicatement que possible.

.gentle-flex {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1ch;
}
Avantages
  • Ne gère que l'alignement, l'orientation et la distribution
  • Les modifications et la maintenance sont toutes au même endroit
  • L'espacement garantit un espacement égal entre les n enfants.
Inconvénients
  • Nombre le plus élevé de lignes de code

Idéal pour les mises en page macro et micro.

Utilisation

gap accepte n'importe quelle longueur ou pourcentage CSS comme valeur.

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


Vous pouvez transmettre une longueur de 1 pour l'espace, qui sera utilisée à la fois pour la ligne et la colonne.

Sténographie
.grid {
  display: grid;
  gap: 10px;
}
Définir les lignes et les colonnes ensemble à la fois
Développé
.grid {
  display: grid;
  row-gap: 10px;
  column-gap: 10px;
}


Gap peut transmettre deux longueurs, qui seront utilisées pour les lignes et les colonnes.

Sténographie
.grid {
  display: grid;
  gap: 10px 5%;
}
Définir les lignes et les colonnes séparément à la fois
Développé
.grid {
  display: grid;
  row-gap: 10px;
  column-gap: 5%;
}