El atributo lang solo puede tener un idioma asociado. Esto significa que el atributo <html>
solo puede tener un idioma, incluso si hay varios idiomas en la página. Establece lang
en el idioma principal de la página.
<html lang="ar,en,fr,pt">...</html>
<html lang="ar">...</html>
Vínculos
Al igual que los botones, los vínculos obtienen su nombre accesible principalmente de su contenido de texto. Un buen truco cuando creas un vínculo es colocar el texto más significativo en el vínculo en sí, en lugar de palabras de relleno como "Aquí" o "Más información".
Check out our guide to web performance <a href="/guide">here</a>.
Check out <a href="/guide">our guide to web performance</a>.
Verifica si una animación activa el diseño
Es probable que una animación que mueva un elemento con algo que no sea transform
sea lenta.
En el siguiente ejemplo, obtuve el mismo resultado visual animando top
y left
, y usando 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)); } }
Puedes probar esto en los siguientes dos ejemplos de Glitch y explorar el rendimiento con DevTools.
Con el mismo lenguaje de marcado, podemos reemplazar padding-top: 56.25%
por aspect-ratio: 16 / 9
y configurar aspect-ratio
en una proporción especificada de width
/ height
.
.container { width: 100%; padding-top: 56.25%; }
.container { width: 100%; aspect-ratio: 16 / 9; }
Usar aspect-ratio
en lugar de padding-top
es mucho más claro y no revisa la propiedad de padding para hacer algo fuera de su alcance habitual.
Sí, así es, estoy usando reduce
para encadenar una secuencia de promesas. Soy muy inteligente. Pero esta es una codificación tan inteligente que es mejor no usarla.
Sin embargo, cuando convertimos lo anterior en una función asíncrona, es tentador generar demasiadas secuencias:
async function logInOrder(urls) { for (const url of urls) { const response = await fetch(url); console.log(await response.text()); } }
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); } }
reduce
“inteligente” se reemplaza por un bucle for estándar, aburrido y legible.
Cómo escribir propiedades personalizadas de Houdini
Este es un ejemplo de cómo establecer una propiedad personalizada (piense en una variable de CSS), pero ahora con una sintaxis (tipo), un valor inicial (reemplazo) y un valor booleano de herencia (¿hereda el valor de su elemento superior o no?). La forma actual de hacerlo es a través de CSS.registerProperty()
en JavaScript, pero en Chromium 85 y versiones posteriores, la sintaxis @property
será compatible con tus archivos CSS:
CSS.registerProperty({ name: '--colorPrimary', syntax: '' , initialValue: 'magenta', inherits: false });
@property --colorPrimary { syntax: '' ; initial-value: magenta; inherits: false; }
Ahora puedes acceder a --colorPrimary
como a cualquier otra propiedad personalizada de CSS a través de var(--colorPrimary)
. Sin embargo, la diferencia aquí es que --colorPrimary
no solo se lee como una cadena. Tiene datos.
CSS backdrop-filter
aplica uno o más efectos a un elemento que es translúcido o transparente. Para comprenderlo, observa las siguientes imágenes.

.frosty-glass-pane { backdrop-filter: blur(2px); }

.frosty-glass-pane { opacity: .9; backdrop-filter: blur(2px); }
En la imagen de la izquierda, se muestra cómo se renderizarían los elementos superpuestos si no se usara o no se admitiera backdrop-filter
. La imagen de la derecha aplica un efecto de desenfoque con backdrop-filter
. Observa que usa opacity
además de backdrop-filter
. Sin opacity
, no habría nada a lo que aplicar el desenfoque. No hace falta decir que, si opacity
se establece como 1
(totalmente opaco), no habrá efecto en el fondo.
Sin embargo, a diferencia del evento unload
, existen usos legítimos para beforeunload
. Por ejemplo, cuando quieras advertirle al usuario que tiene
cambios no guardados que perderá si sale de la página. En este caso, se recomienda que solo agregues objetos de escucha beforeunload
cuando un usuario tenga cambios no guardados y, luego, quítalos inmediatamente después de que se guarden.
window.addEventListener('beforeunload', (event) => { if (pageHasUnsavedChanges()) { event.preventDefault(); return event.returnValue = 'Are you sure you want to exit?'; } });
beforeunload
de forma incondicional.
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); });
beforeunload
cuando es necesario (y
lo quita cuando no lo es).
Minimiza el uso de Cache-Control: no-store
Cache-Control: no-store
es un encabezado HTTP que los servidores web pueden configurar en las respuestas para indicarle al navegador que no almacene la respuesta en ninguna caché HTTP. Se debe usar para recursos que contengan información sensible del usuario, por ejemplo, páginas protegidas por un acceso.
El elemento fieldset
, que contiene cada grupo de entrada (.fieldset-item
), usa gap: 1px
para crear los bordes de línea fina entre los elementos. No hay una solución de borde complicada.
.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); } } }
Ajuste de cuadrícula natural
El diseño más complejo resultó ser el diseño macro, el sistema de diseño lógico entre <main>
y <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>
El elemento fieldset
, que contiene cada grupo de entrada (.fieldset-item
), usa gap: 1px
para crear los bordes de línea fina entre los elementos. No hay una solución de borde complicada.
.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); } } }
Diseño <header>
de pestañas
El siguiente diseño es casi el mismo: uso flex para crear un orden vertical.
<snap-tabs> <header> <nav></nav> <span class="snap-indicator"></span> </header> <section></section> </snap-tabs>
header { display: flex; flex-direction: column; }
El .snap-indicator
debe desplazarse horizontalmente con el grupo de vínculos, y este diseño de encabezado ayuda a establecer esa etapa. No hay elementos con posicionamiento absoluto aquí.
La Flexibilidad suave es una estrategia más auténtica de solo centrado. Es suave y gentil, ya que, a diferencia de place-content: center
, no se cambian los tamaños de los cuadros de los elementos secundarios durante el centrado. Todos los elementos se apilan, centran y espacian de la manera más cuidadosa posible.
.gentle-flex {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 1ch;
}
- Solo controla la alineación, la dirección y la distribución.
- Las ediciones y el mantenimiento se encuentran en un solo lugar
- El espacio garantiza un espaciado igual entre n elementos secundarios.
- Mayor cantidad de líneas de código
Excelente para diseños macro y micro.
Uso
gap
acepta cualquier longitud o porcentaje de CSS como valor.
.gap-example {
display: grid;
gap: 10px;
gap: 2ch;
gap: 5%;
gap: 1em;
gap: 3vmax;
}
Se puede pasar 1 longitud para el espacio, que se usará para la fila y la columna.
.grid { display: grid; gap: 10px; }
.grid { display: grid; row-gap: 10px; column-gap: 10px; }
Se pueden pasar 2 longitudes para el espacio, que se usarán para la fila y la columna.
.grid { display: grid; gap: 10px 5%; }
.grid { display: grid; row-gap: 10px; column-gap: 5%; }