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 la page en contient plusieurs. Définissez lang
sur la langue principale de la page.
<html lang="ar,en,fr,pt">...</html>Vous ne pouvez pas utiliser plusieurs langues.
<html lang="ar">...</html>Définissez uniquement la langue principale de la page. Ici, la langue est l'arabe.
Liens
Comme les boutons, les liens obtiennent principalement leur nom accessible à partir de leur contenu textuel. Une bonne astuce lors de la création d'un lien consiste à insérer le texte le plus significatif dans le lien lui-même, plutôt que des mots de remplissage tels que "ici" ou "En savoir plus".
Check out our guide to web performance <a href="/guide">here</a>.
Check out <a href="/guide">our guide to web performance</a>.
Vérifier si une animation déclenche la mise en page
Une animation qui déplace un élément avec autre chose que transform
peut être lente.
Dans l'exemple suivant, j'ai obtenu le même résultat visuel en animant top
et left
, et en utilisant transform
.
.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)); } }
Vous pouvez tester cela dans les deux exemples de Glitch suivants et explorer les performances à l'aide des outils de développement.
Avec le même balisage, nous pouvons remplacer padding-top: 56.25%
par aspect-ratio: 16 / 9
, et définir aspect-ratio
sur un ratio spécifié de width
/ height
.
.container { width: 100%; padding-top: 56.25%; }
.container { width: 100%; aspect-ratio: 16 / 9; }
L'utilisation de aspect-ratio
au lieu de padding-top
est beaucoup plus claire et ne remanie pas la propriété de marge intérieure pour effectuer une action en dehors de son champ d'application habituel.
Oui, c'est exact, j'utilise reduce
pour enchaîner une séquence de promesses. Je suis tellement intelligente. Mais ce codage est un peu très intelligent qu'il vaut mieux ne pas le faire.
Toutefois, lors de la conversion de la fonction ci-dessus en fonction asynchrone, il est tentant de passer 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 extraction ne commence pas tant que ma première exploration n'a pas été entièrement lue, et ainsi de suite. C'est beaucoup plus lent que dans l'exemple des promesses qui effectue les extractions en parallèle. Heureusement, il existe un milieu idéal.
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 un for-loop standard, ennuyeux et lisible.
Écrire des propriétés personnalisées Houdini
Voici un exemple de définition d'une propriété personnalisée (variable CSS, par exemple), mais avec une syntaxe (type), une valeur initiale (remplacement) et une valeur booléenne d'héritage (la valeur de son parent est-elle héritée ou non ?). La méthode actuelle consiste à utiliser CSS.registerProperty()
en JavaScript. Toutefois, dans Chromium 85 et versions ultérieures, la syntaxe @property
sera compatible avec vos fichiers CSS:
CSS.registerProperty({ name: '--colorPrimary', syntax: '', initialValue: 'magenta', inherits: false });
@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 seulement lu sous forme de chaîne. Il a des données !
Le CSS backdrop-filter
applique un ou plusieurs effets à un élément translucide ou transparent. Pour le comprendre, tenez compte des images ci-dessous.
![Triangle superposé sur un cercle. Le cercle ne peut pas être vu à travers le triangle.](https://web.developers.google.cn/static/examples/image/admin/LOqxvB3qqVkbZBmxMmKS.png?hl=fr)
.frosty-glass-pane { backdrop-filter: blur(2px); }
![Triangle superposé sur un cercle. Le triangle est translucide, ce qui permet de voir le cercle à travers.](https://web.developers.google.cn/static/examples/image/admin/VbyjpS6Td39E4FudeiVg.png?hl=fr)
.frosty-glass-pane { opacity: .9; backdrop-filter: blur(2px); }
L'image de gauche montre comment les éléments qui se chevauchent seraient affichés si backdrop-filter
n'était pas utilisé ou accepté. 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 aucun élément à flouter. Il va sans dire que si opacity
est défini sur 1
(entièrement opaque), cela n'aura aucun effet sur l'arrière-plan.
Cependant, contrairement à l'événement unload
, il existe des utilisations légitimes de beforeunload
. Par exemple, lorsque vous souhaitez avertir l'utilisateur qu'il a des modifications non enregistrées, il sera perdu s'il quitte la page. Dans ce cas, nous vous recommandons d'ajouter des écouteurs beforeunload
uniquement lorsqu'un utilisateur a non enregistré des modifications, puis de les supprimer immédiatement après leur enregistrement.
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.
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 lorsque cela est nécessaire (et le supprime dans le cas contraire).
Réduire 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 qui indiquent au navigateur de ne pas stocker la réponse dans un cache HTTP. Il doit être utilisé pour les ressources contenant des informations utilisateur sensibles, par exemple les pages nécessitant une connexion.
L'élément fieldset
, qui contient chaque groupe d'entrée (.fieldset-item
), utilise gap: 1px
pour créer les bordures de contour entre les éléments. Pas de solution de bordure compliquée !
.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); } } }
Enveloppement naturel de la grille
La mise en page la plus complexe a fini par être la mise en page macro, le système de mise en page logique entre <main>
et <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>
L'élément fieldset
, qui contient chaque groupe d'entrée (.fieldset-item
), utilise gap: 1px
pour créer les bordures de contour entre les éléments. Pas de solution de bordure compliquée !
.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); } } }
Mise en page des onglets <header>
La mise en page suivante est presque la même: j'utilise l'flex pour créer un ordre vertical.
<snap-tabs> <header> <nav></nav> <span class="snap-indicator"></span> </header> <section></section> </snap-tabs>
header { display: flex; flex-direction: column; }
Le .snap-indicator
doit se déplacer horizontalement avec le groupe de liens, et cette mise en page d'en-tête permet de définir cette étape. Il n'y a pas d'éléments positionnés de façon absolue ici.
Gentle Flex est une stratégie de centrage uniquement plus efficace. Il est doux et doux, car contrairement à place-content: center
, la taille de la boîte pour les enfants n'est pas modifiée pendant le centrage. Aussi délicatement que possible, tous les éléments sont empilés, centrés et espacés.
.gentle-flex {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 1ch;
}
- Gère uniquement l'alignement, la direction et la distribution
- Modifications et maintenance au même endroit
- L'écart garantit un espacement égal entre n enfants
- La plupart des 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;
}
L'écart peut être transmis d'une longueur, qui sera utilisée à la fois pour la ligne et la colonne.
.grid { display: grid; gap: 10px; }Définir des lignes et des colonnes ensemble à la fois
.grid { display: grid; row-gap: 10px; column-gap: 10px; }
L'écart peut être transmis de deux longueurs, qui seront utilisées pour les lignes et les colonnes.
.grid { display: grid; gap: 10px 5%; }Définir les lignes et les colonnes séparément en même temps
.grid { display: grid; row-gap: 10px; column-gap: 5%; }