Confronta e compareCaption

All'attributo lang può essere associata una sola lingua. Ciò significa che l'attributo <html> può avere una sola lingua, anche se nella pagina sono presenti più lingue. Imposta lang sulla lingua principale della pagina.

Cosa non fare
<html lang="ar,en,fr,pt">...</html>
Non sono supportate più lingue.
Cosa fare
<html lang="ar">...</html>
Imposta solo la lingua principale della pagina. In questo caso, la lingua è l'arabo.

Come per i pulsanti, i link ottengono il nome accessibile principalmente dal testo. Un bel trucco per creare un link è inserire il testo più significativo nel link stesso, anziché parole di riempimento come "Qui" o "Leggi di più".

Non sufficientemente descrittivo
Check out our guide to web performance <a href="/guide">here</a>.
Contenuti utili.
Check out <a href="/guide">our guide to web performance</a>.

Verificare se un'animazione attiva il layout

Un'animazione che sposta un elemento utilizzando un'altra proprietà diversa da transform è probabile che sia lenta. Nell'esempio seguente ho ottenuto lo stesso risultato visivo animando top e left e utilizzando transform.

Cosa non fare
.box {
  position: absolute;
  top: 10px;
  left: 10px;
  animation: move 3s ease infinite;
}

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

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

Puoi testarlo nei due seguenti esempi di Glitch e esplorare le prestazioni utilizzando DevTools.

Con lo stesso markup, possiamo sostituire padding-top: 56.25% con aspect-ratio: 16 / 9, impostando aspect-ratio su un rapporto specificato di width / height.

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

L'utilizzo di aspect-ratio anziché padding-top è molto più chiaro e non rivede la proprietà padding per fare qualcosa al di fuori del suo ambito abituale.

Sì, è corretto, sto utilizzando reduce per concatenare una sequenza di promesse. Sono tanto intelligente. Tuttavia, si tratta di un codice così intelligente che è meglio evitare.

Tuttavia, quando si converte il codice precedente in una funzione asincrona, è facile cadere nella tentazione di procedere in modo troppo sequenziale:

Non consigliato: troppo sequenziale
async function logInOrder(urls) {
  for (const url of urls) {
    const response = await fetch(url);
    console.log(await response.text());
  }
}
Sembra molto più ordinato, ma il secondo recupero non inizia finché il primo non è stato completamente letto e così via. Questa operazione è molto più lenta rispetto all'esempio di promise che esegue i recuperi in parallelo. Fortunatamente, esiste una soluzione intermedia ideale.
Consigliato: ben parallelo
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 questo esempio, gli URL vengono recuperati e letti in parallelo, ma il bit reduce "intelligente" viene sostituito da un ciclo for standard, noioso e leggibile.

Scrittura di proprietà personalizzate Houdini

Ecco un esempio di impostazione di una proprietà personalizzata (ad es. una variabile CSS), ma ora con una sintassi (tipo), un valore iniziale (valore predefinito) e un booleano di ereditarietà (eredita il valore dall'elemento principale o meno?). Il modo attuale per farlo è tramite CSS.registerProperty() in JavaScript, ma in Chromium 85 e versioni successive, la sintassi CSS.registerProperty() sarà supportata nei file CSS:@property

File JavaScript separato (Chromium 78)
CSS.registerProperty({
  name: '--colorPrimary',
  syntax: '',
  initialValue: 'magenta',
  inherits: false
});
Incluso nel file CSS (Chromium 85)
@property --colorPrimary {
  syntax: '';
  initial-value: magenta;
  inherits: false;
}

Ora puoi accedere a --colorPrimary come a qualsiasi altra proprietà CSS personalizzata tramite var(--colorPrimary). Tuttavia, la differenza è che --colorPrimary non viene solo letto come stringa. Contiene dati.

CSS backdrop-filter applica uno o più effetti a un elemento semitrasparente o trasparente. Per comprendere questo concetto, guarda le immagini di seguito.

Nessuna trasparenza in primo piano
Un triangolo sovrapposto a un cerchio. Il cerchio non può essere visto attraverso il triangolo.
.frosty-glass-pane {
  backdrop-filter: blur(2px);
}
Trasparenza in primo piano
Un triangolo sovrapposto a un cerchio. Il triangolo è traslucido, quindi il cerchio è visibile.
.frosty-glass-pane {
  opacity: .9;
  backdrop-filter: blur(2px);
}

L'immagine a sinistra mostra come verrebbero visualizzati gli elementi sovrapposti se backdrop-filter non fosse utilizzato o supportato. L'immagine a destra applica un effetto di sfocatura utilizzando backdrop-filter. Tieni presente che utilizza opacity oltre a backdrop-filter. Senza opacity, non ci sarebbe nulla a cui applicare la sfocatura. È quasi scontato che se opacity è impostato su 1 (completamente opaco), non avrà alcun effetto sullo sfondo.

Tuttavia, a differenza dell'evento unload, esistono utilizzi legittimi per beforeunload. Ad esempio, quando vuoi avvisare l'utente che ha modifiche non salvate che perderà se esce dalla pagina. In questo caso, ti consigliamo di aggiungere gli ascoltatori beforeunload solo quando un utente ha modifiche non salvate e di rimuoverli immediatamente dopo il salvataggio delle modifiche non salvate.

Cosa non fare
window.addEventListener('beforeunload', (event) => {
  if (pageHasUnsavedChanges()) {
    event.preventDefault();
    return event.returnValue = 'Are you sure you want to exit?';
  }
});
Il codice riportato sopra aggiunge un ascoltatore beforeunload incondizionatamente.
Cosa fare
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);
});
Il codice riportato sopra aggiunge l'ascoltatore beforeunload solo quando è necessario (e lo rimuove quando non lo è).

Riduci al minimo l'utilizzo di Cache-Control: no-store

Cache-Control: no-store è un'intestazione HTTP che i server web possono impostare sulle risposte per indicare al browser di non memorizzare la risposta in alcuna cache HTTP. Deve essere utilizzato per le risorse contenenti informazioni sensibili degli utenti, ad esempio le pagine protette da un login.

L'elemento fieldset, che contiene ogni gruppo di input (.fieldset-item), utilizza gap: 1px per creare i bordi sottili tra gli elementi. Nessuna soluzione complicata per i confini.

Spazio vuoto riempito
.grid {
  display: grid;
  gap: 1px;
  background: var(--bg-surface-1);

  & > .fieldset-item {
    background: var(--bg-surface-2);
  }
}
Trucchetto per i bordi
.grid {
  display: grid;

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

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

Aggiunta di righe aggiuntive alla griglia naturale

Il layout più complesso è risultato essere il layout macro, il sistema di layout logico tra <main> e <form>.

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

L'elemento fieldset, che contiene ogni gruppo di input (.fieldset-item), utilizza gap: 1px per creare i bordi sottili tra gli elementi. Nessuna soluzione complicata per i confini.

Spazio vuoto riempito
.grid {
  display: grid;
  gap: 1px;
  background: var(--bg-surface-1);

  & > .fieldset-item {
    background: var(--bg-surface-2);
  }
}
Trucchetto per i bordi
.grid {
  display: grid;

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

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

Layout <header> schede

Il layout successivo è quasi uguale: utilizzo flex per creare l'ordinamento verticale.

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

Il .snap-indicator deve scorrere orizzontalmente con il gruppo di link e questo layout dell'intestazione aiuta a impostare questa fase. Nessun elemento con posizionamento assoluto.

La strategia Gentle Flex è una strategia di centratura soltanto più realistica. È morbido e delicato, perché, diversamente da place-content: center, le dimensioni delle caselle per bambini non vengono modificate durante il centratura. Con la massima delicatezza possibile, tutti gli elementi vengono impilati, centrati e distanziati.

.gentle-flex {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1ch;
}
Pro
  • Gestisce solo allineamento, direzione e distribuzione
  • Modifiche e manutenzione sono tutte in un unico posto
  • La spaziatura garantisce una spaziatura uguale tra n bambini
Contro
  • Maggior numero di righe di codice

Ideale sia per i layout macro che micro.

Utilizzo

gap accetta come valore qualsiasi lunghezza o percentuale CSS.

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


A Gap può essere passata una lunghezza di 1, che verrà utilizzata sia per la riga che per la colonna.

Stenografia
.grid {
  display: grid;
  gap: 10px;
}
Impostare contemporaneamente insieme righe e colonne
Espanso
.grid {
  display: grid;
  row-gap: 10px;
  column-gap: 10px;
}


A Gap possono essere passati due valori di lunghezza, che verranno utilizzati per la riga e la colonna.

Stenografia
.grid {
  display: grid;
  gap: 10px 5%;
}
Impostare contemporaneamente righe e colonne separatamente
Espanso
.grid {
  display: grid;
  row-gap: 10px;
  column-gap: 5%;
}