Estado del CSS 2022

Funciones de diseño web actuales y futuras, como se ve en Google IO 2022, además de algunos extras.

El 2022 será uno de los mejores años para CSS, tanto en funciones como en lanzamientos de funciones cooperativas del navegador, con el objetivo colaborativo de implementar 14 funciones.

Descripción general

Esta publicación es el artículo de la charla brindada en Google IO 2022. No se trata de una guía detallada sobre cada función, sino una introducción y una breve descripción general para despertar tu interés, con amplitud en lugar de profundidad. Si te interesan, consulta los vínculos de recursos para obtener más información al final de la sección.

Índice

Usa la siguiente lista para ir directamente a los temas de interés:

Compatibilidad del navegador

Un motivo principal por el que se configuraron muchas funciones de CSS para lanzarse de manera cooperativa es gracias a los esfuerzos de Interoperabilidad 2022. Antes de estudiar los esfuerzos de la interoperabilidad, es importante consultar los esfuerzos de Compat 2021.

Compatibilidad 2021

Los objetivos para 2021, basados en los comentarios de los desarrolladores a través de encuestas, eran estabilizar las funciones actuales, mejorar el paquete de pruebas y aumentar las puntuaciones de aprobación de los navegadores para cinco funciones:

  1. Posicionamiento de sticky
  2. aspect-ratio tamaño
  3. Diseño flex
  4. Diseño grid
  5. Posicionamiento y animación de transform

Las puntuaciones de las pruebas se aumentaron de manera general, lo que demostró una estabilidad y confiabilidad mejoradas. Felicitaciones a los equipos.

Interoperabilidad 2022

Este año, los navegadores se reunieron para analizar las funciones y prioridades en las que pretendían trabajar, uniendo sus esfuerzos. Planificaron ofrecer las siguientes funciones web para los desarrolladores:

  1. @layer
  2. Funciones y espacios de color
  3. Contención
  4. <dialog>
  5. Compatibilidad con formularios
  6. Desplazamiento
  7. Subcuadrícula
  8. Tipografía
  9. Unidades del viewport
  10. Compatibilidad con la Web

Se trata de una lista emocionante y ambiciosa que no veo la hora de que se desarrolle.

Lo nuevo de 2022

Como era de esperar, el estado de CSS 2022 se ve afectado drásticamente por el trabajo de Interoperabilidad de 2022.

Capas de Cascade

Navegadores compatibles

  • 99
  • 99
  • 97
  • 15.4

Origen

Antes de @layer, el orden detectado de las hojas de estilo cargadas era muy importante, ya que los diseños cargados últimos pueden reemplazar los diseños cargados con anterioridad. Como resultado, se crearon hojas de estilo de entrada meticulosamente administradas, en las que los desarrolladores debían cargar primero los estilos menos importantes y los más importantes después. Existen metodologías completas, como ITCSS, para ayudar a los desarrolladores a administrar esta importancia.

Con @layer, el archivo de entrada puede predefinir las capas y su orden con anticipación. Luego, a medida que se cargan, se cargan o definen los diseños, se pueden colocar dentro de una capa, lo que permite conservar la importancia de la anulación del diseño, pero sin la organización de carga administrada de forma meticulosa.

En el video, se muestra cómo las capas de cascada definidas permiten un proceso de creación y carga más liberado y de estilo libre, a la vez que mantienen la cascada según sea necesario.

Las Herramientas para desarrolladores de Chrome son útiles para visualizar qué estilos provienen de qué capas:

Captura de pantalla de la barra lateral Estilos de Herramientas para desarrolladores de Chrome, en la que se destaca cómo aparecen los estilos dentro de los nuevos grupos de capas.

Recursos

Subcuadrícula

Navegadores compatibles

  • 117
  • 117
  • 71
  • 16

Origen

Antes de subgrid, una cuadrícula dentro de otra no podía alinearse con sus celdas superiores ni con las líneas de cuadrícula. Cada diseño de cuadrícula era único. Muchos diseñadores colocan una sola cuadrícula en todo el diseño y alinean constantemente los elementos dentro de ella, lo que no se podría hacer en CSS.

Después de subgrid, un elemento secundario de una cuadrícula puede adoptar las columnas o filas de sus elementos superiores como propias y alinearse a sí mismas o a las secundarias.

En la siguiente demostración, el elemento del cuerpo crea una cuadrícula clásica de tres columnas: la columna del medio se llama main, y las columnas izquierda y derecha nombran sus líneas fullbleed. Luego, cada elemento del cuerpo, <nav> y <main>, adopta las líneas nombradas del cuerpo mediante la configuración de grid-template-columns: subgrid.

​​body {
  display: grid;
  grid-template-columns:
    [fullbleed-start]
    auto [main-start] min(90%, 60ch) [main-end] auto
    [fullbleed-end]
  ;
}

body > * {
  display: grid;
  grid-template-columns: subgrid;
}

Por último, los elementos secundarios de <nav> o <main> pueden alinearse o ajustar su tamaño mediante las columnas y líneas fullbleed y main.

.main-content {
  grid-column: main;
}

.fullbleed {
  grid-column: fullbleed;
}

Herramientas para desarrolladores puede ayudarte a ver las líneas y subredes (solo Firefox por el momento). En la siguiente imagen, se superpusieron la cuadrícula superior y las subcuadrículas. Ahora se parece a la forma en que los diseñadores pensaban sobre el diseño.

Captura de pantalla de una demostración de la subcuadrícula, con las herramientas de superposición de la cuadrícula de Chrome DevTools para mostrar las líneas definidas por CSS.

En el panel de elementos de Herramientas para desarrolladores, puedes ver qué elementos son cuadrículas y subcuadrículas, lo que es muy útil para depurar o validar el diseño.

Captura de pantalla del panel Elementos de Herramientas para desarrolladores de Chrome donde se etiquetan los elementos que tienen diseños de cuadrícula o de subcuadrícula.
Captura de pantalla de las Herramientas para desarrolladores de Firefox

Recursos

Consultas de contenedores

Navegadores compatibles

  • 105
  • 105
  • 110
  • 16

Origen

Antes de @container, los elementos de una página web solo podían responder al tamaño de todo el viewport. Esto es ideal para los diseños macro, pero para los diseños micro, en los que su contenedor externo no es el viewport completo, es imposible que el diseño se ajuste en consecuencia.

Después de @container, los elementos pueden responder a un tamaño o estilo de contenedor superior. La única advertencia es que los contenedores deben declararse como posibles objetivos de consulta, lo cual es un pequeño requisito para un gran beneficio.

/* establish a container */
.day {
  container-type: inline-size;
  container-name: calendar-day;
}

Estos estilos son los que hacen que las columnas lun, martes, mié, jueves y viernes del siguiente video puedan consultarse mediante los elementos del evento.

Demostración de Una Kravets

Este es el CSS para consultar el contenedor calendar-day por su tamaño y, luego, ajustar un diseño y los tamaños de fuente:

@container calendar-day (max-width: 200px) {
  .date {
    display: block;
  }

  .date-num {
    font-size: 2.5rem;
    display: block;
  }
}

Este es otro ejemplo: un componente de libro se adapta al espacio disponible en la columna al que se arrastra:

Demostración de Max Böck

Una es correcta a la hora de evaluar la situación como el nuevo responsivo. Hay muchas decisiones de diseño interesantes y significativas que se deben tomar cuando se usa @container.

Recursos

accent-color

Navegadores compatibles

  • 93
  • 93
  • 92
  • 15.4

Origen

Antes del accent-color, cuando querías un formulario con colores que coincidan con las marcas, podías terminar con bibliotecas complejas o soluciones de CSS que se hicieron difíciles de administrar con el tiempo. Si bien te brindaron todas las opciones y, con suerte, incluyó accesibilidad, la opción de usar los componentes integrados o adoptar los tuyos se vuelve tedioso seguir eligiendo.

Después de accent-color, una línea de CSS le agrega un color de marca a los componentes integrados. Además de un tono, el navegador elige de forma inteligente colores de contraste adecuados para las partes auxiliares del componente y se adapta a los esquemas de colores del sistema (claro u oscuro).

/* tint everything */
:root {
  accent-color: hotpink;
}

/* tint one element */
progress {
  accent-color: indigo;
}

Elementos HTML claros y oscuros uno al lado del otro para compararlos.

Para obtener más información sobre accent-color, consulta mi entrada en web.dev, en la que exploro muchos más aspectos de esta útil propiedad de CSS.

Recursos

Nivel de color 4 y 5

Durante las últimas décadas, el sRGB ha dominado la Web, pero en un mundo digital en expansión de pantallas de alta definición y dispositivos móviles equipados con pantallas OLED o QLED, sRGB no es suficiente. Además, se espera que haya páginas dinámicas que se adapten a las preferencias de los usuarios, y la administración del color ha sido una preocupación creciente para los diseñadores, los sistemas de diseño y los encargados de mantener el código.

Sin embargo, no en 2022. CSS tiene una serie de funciones y espacios de color nuevos: - Colores que llegan a las capacidades de color HD de las pantallas. - Espacios de color que coinciden con un intent, como la uniformidad perceptual. - Espacios de color para los gradientes que cambian drásticamente los resultados de la interpolación. - Funciones de color que te ayudan a mezclar y contrastar, y elige en qué espacio trabajarás.

Antes de todas estas características de color, los sistemas de diseño debían calcular previamente los colores de contraste adecuados y garantizar las paletas vibrantes apropiadas, todo mientras los preprocesadores o JavaScript hacían el trabajo pesado.

Después de contar con todas estas funciones de color, el navegador y CSS pueden hacer todo el trabajo, de forma dinámica y justo a tiempo. En lugar de enviar muchos KB de CSS y JavaScript a los usuarios para habilitar los temas y los colores de visualización de datos, CSS puede realizar la organización y los cálculos. CSS también está mejor equipado para comprobar la compatibilidad antes del uso o administrar los resguardos con facilidad.

@media (dynamic-range: high) {
  .neon-pink {
    --neon-glow: color(display-p3 1 0 1);
  }
}

@supports (color: lab(0% 0 0)) {
  .neon-pink {
    --neon-glow: lab(150% 160 0);
  }
}

hwb()

Navegadores compatibles

  • 101
  • 101
  • 96
  • 15

Origen

HWB son las iniciales de matiz, blanura y negra. Se presenta como una forma amigable de articular el color, ya que es solo un tono y una cantidad de blanco o negro para oscurecer o aclarar. Los artistas que mezclan colores con blanco o negro pueden apreciar esta adición de sintaxis de colores.

El uso de esta función de color genera colores del espacio de color sRGB, al igual que HSL y RGB. En términos de novedades para 2022, esto no ofrece colores nuevos, pero puede facilitar algunas tareas para los fanáticos de la sintaxis y el modelo mental.

Recursos

Espacios de color

La forma en que se representan los colores se realiza con un espacio de color. Cada espacio de color ofrece varias características y compensaciones para trabajar con color. Algunos pueden empaquetar todos los colores brillantes; otros pueden alinearlos primero en función de su luminosidad.

En 2022, CSS ofrecerá 10 espacios de color nuevos, cada uno con funciones únicas para ayudar a los diseñadores y desarrolladores a mostrar, elegir y mezclar colores. Anteriormente, sRGB era la única opción para trabajar con color, pero ahora CSS desbloquea un nuevo potencial y un nuevo espacio de color predeterminado, LCH.

color-mix()

Navegadores compatibles

  • 111
  • 111
  • 113
  • 16.2

Origen

Antes de color-mix(), los desarrolladores y diseñadores necesitaban preprocesadores como Sass para combinar los colores antes de que el navegador los viera. La mayoría de las funciones de combinación de colores tampoco proporcionaban la opción de especificar en qué espacio de color se mezclaba, lo que a veces generaba resultados confusos.

Después de color-mix(), los desarrolladores y diseñadores pueden mezclar colores en el navegador, junto con todos sus otros estilos, sin ejecutar procesos de compilación ni incluir JavaScript. Además, pueden especificar el espacio de color para la mezcla o usar el espacio de color de mezcla predeterminado de LCH.

A menudo, se usa un color de marca como base y se crean variantes a partir de él, como los colores más claros o más oscuros para los estilos que se colocan cuando se coloca el cursor sobre un elemento. Así se ve con color-mix():

.color-mix-example {
  --brand: #0af;

  --darker: color-mix(var(--brand) 25%, black);
  --lighter: color-mix(var(--brand) 25%, white);
}

y, si deseas combinarlos en un espacio de color diferente, como srgb, cámbialo:

.color-mix-example {
  --brand: #0af;

  --darker: color-mix(in srgb, var(--brand) 25%, black);
  --lighter: color-mix(in srgb, var(--brand) 25%, white);
}

A continuación, se muestra una demostración de temas con color-mix(). Intenta cambiar el color de la marca y mira la actualización del tema:

Disfruta mezclar colores en distintos espacios de color en tus hojas de estilo en 2022.

Recursos

color-contrast()

Navegadores compatibles

  • x
  • x
  • x

Origen

Antes de color-contrast(), los autores de hojas de estilo necesitaban conocer los colores accesibles con anticipación. A menudo, una paleta mostraba texto en blanco o negro en una muestra de color para indicar a un usuario del sistema de colores qué color de texto se necesitaría para contrastar adecuadamente con esa muestra.

Captura de pantalla de 3 paletas de Material que muestran 14 colores y los colores de contraste apropiados blanco o negro para el texto.
Ejemplo de las paletas de colores de Material Design de 2014

Después de color-contrast(), los autores de hojas de estilo pueden descargar la tarea por completo al navegador. No solo puedes emplear el navegador para elegir automáticamente un color blanco o negro, sino también brindarle una lista de colores adecuados para el sistema de diseño y hacer que elija el primero que pase la relación de contraste deseada.

A continuación, se muestra una captura de pantalla de una demostración del conjunto de paleta de colores de HWB en la que el navegador elige automáticamente los colores del texto según el color de la muestra:

Captura de pantalla de la demostración de HWB en la que cada paleta tiene una vinculación diferente de texto claro u oscuro según lo determinado por el navegador.
Probar la demostración

Los conceptos básicos de la sintaxis se ven así: el gris se pasa a la función y el navegador determina si el blanco o el negro tienen el mayor contraste:

color: color-contrast(gray);

La función también se puede personalizar con una lista de colores, de la cual elegirá el color que contraste más alto de la selección:

color: color-contrast(gray vs indigo, rebeccapurple, hotpink);

Por último, en caso de que sea preferible no elegir el color que contraste más alto de la lista, se puede proporcionar una relación de contraste objetivo y se elige el primer color que pase:

color: color-contrast(
  var(--bg-blue-1)
  vs
  var(--text-lightest), var(--text-light), var(--text-subdued)
  to AA /* 4.5 could also be passed */
);

Esta función puede usarse para más que solo el color de texto, aunque califico que ese será su caso de uso principal. Piensa en lo mucho más fácil que será entregar interfaces accesibles y legibles una vez que la elección de colores contrastantes adecuados esté integrada en el lenguaje CSS.

Recursos

Sintaxis de colores relativos

Navegadores compatibles

  • 111
  • 111
  • 113
  • 15

Origen

Antes de la sintaxis de color relativa, para calcular el color y realizar ajustes, los canales de color debían colocarse de forma individual en las propiedades personalizadas. Esta limitación también convirtió a HSL en la función de color principal para manipular colores, ya que el tono, la saturación o la luminosidad se podrían ajustar de forma sencilla con calc().

Después de la sintaxis de colores relativas, cualquier color en cualquier espacio se puede deconstruir, modificar y mostrar como color, todo en una sola línea de CSS. No hay más limitaciones del HSL: las manipulaciones se pueden realizar en cualquier espacio de color deseado y se deben crear muchas propiedades menos personalizadas para facilitarlo.

En el siguiente ejemplo de sintaxis, se proporciona un hexadecimal base y se crean dos colores nuevos en relación con él. El primer color --absolute-change crea un nuevo color en LCH a partir del color base, luego reemplaza la luminosidad del color base por 75% y mantiene la croma (c) y el matiz (h). El segundo color --relative-change crea un color nuevo en LCH a partir del color base, pero esta vez reduce la croma (c) en un 20%.

.relative-color-syntax {
  --color: #0af;
  --absolute-change: lch(from var(--color) 75% c h);
  --relative-change: lch(from var(--color) l calc(c-20%) h);
}

Es similar a mezclar colores, pero se asemeja más a las alteraciones que a mezclar. Puedes transmitir un color desde otro color y obtener acceso a los tres valores de canal con el nombre de la función de color usada, con la oportunidad de ajustar esos canales. En general, esta es una sintaxis muy interesante y potente para el color.

En la siguiente demostración, usé la sintaxis de color relativo para crear variantes más claras y oscuras de un color base y usé color-contrast() para garantizar que las etiquetas tengan el contraste adecuado:

Captura de pantalla con 3 columnas, cada una más oscura o más clara que la columna central.
Probar la demostración

Esta función también se puede usar para generar una paleta de colores. Esta es una demostración en la que se generan paletas completas a partir de un color base proporcionado. Este conjunto único de CSS se utiliza en todas las paletas diferentes, y cada una proporciona una base diferente. Como beneficio adicional, dado que he usado LCH, mira cuán perceptualmente son las paletas: no hay puntos calientes ni muertos para ver gracias a este espacio de color.

:root {
  --_color-base: #339af0;

  --color-0:  lch(from var(--_color-base) 98% 10 h);
  --color-1:  lch(from var(--_color-base) 93% 20 h);
  --color-2:  lch(from var(--_color-base) 85% 40 h);
  --color-3:  lch(from var(--_color-base) 75% 46 h);
  --color-4:  lch(from var(--_color-base) 66% 51 h);
  --color-5:  lch(from var(--_color-base) 61% 52 h);
  --color-6:  lch(from var(--_color-base) 55% 57 h);
  --color-7:  lch(from var(--_color-base) 49% 58 h);
  --color-8:  lch(from var(--_color-base) 43% 55 h);
  --color-9:  lch(from var(--_color-base) 39% 52 h);
  --color-10: lch(from var(--_color-base) 32% 48 h);
  --color-11: lch(from var(--_color-base) 25% 45 h);
  --color-12: lch(from var(--_color-base) 17% 40 h);
  --color-13: lch(from var(--_color-base) 10% 30 h);
  --color-14: lch(from var(--_color-base) 5% 20 h);
  --color-15: lch(from var(--_color-base) 1% 5 h);
}
Captura de pantalla de 15 paletas generadas de forma dinámica por CSS.
Prueba la demostración

Con suerte, a estas alturas ya puedes ver cómo los espacios de color y las diferentes funciones de color se pueden usar para distintos propósitos, según sus fortalezas y debilidades.

Recursos

Espacios de color de gradientes

Antes de los espacios de color con gradiente, sRGB era el espacio de color predeterminado utilizado. En general, sRGB es confiable, pero tiene algunas debilidades, como la zona sin conexión gris.

4 gradientes en una cuadrícula, todo desde turquesa hasta rosa profundo. LCH y LAB tienen una intensidad más coherente, en la que sRGB se desatura un poco en el medio.

Después de los espacios de color del gradiente, indícale al navegador qué espacio de color se usará para la interpolación de colores. Esto les da a los desarrolladores y diseñadores la capacidad de elegir el gradiente que prefieran. El espacio de color predeterminado también cambia a LCH en lugar de sRGB.

La adición de sintaxis va después de la dirección del gradiente, usa la nueva sintaxis in y es opcional:

background-image: linear-gradient(
  to right in hsl,
  black, white
);

background-image: linear-gradient(
  to right in lch,
  black, white
);

Aquí hay un gradiente básico y esencial de negro a blanco. Observa el rango de resultados en cada espacio de color. Algunos alcanzan el negro oscuro antes que otros, y otros se atenúan a blanco demasiado tarde.

Se muestran 11 espacios de color en una comparación entre negro y blanco.

En el siguiente ejemplo, el negro pasa al azul porque es un espacio problemático conocido para los gradientes. La mayoría de los espacios de color se vuelven púrpura durante la interpolación del color o, como me gusta pensarlo, a medida que los colores viajan dentro de su espacio de color del punto A al punto B. Dado que el gradiente tomará una línea recta del punto A al punto B, la forma del espacio de color cambia drásticamente las paradas que toma la ruta en el camino.

Se muestran 11 espacios de color comparando el azul con el negro.

Para obtener información más detallada sobre exploraciones, ejemplos y comentarios, lee esta conversación de Twitter.

Recursos

inert

Navegadores compatibles

  • 102
  • 102
  • 112
  • 15.5

Origen

Antes del inert, era una práctica recomendada guiar el enfoque del usuario hacia las áreas de la página o la app que requerían atención inmediata. Esta estrategia de enfoque guiado se conoció como captura de enfoque porque los desarrolladores colocaban el enfoque en un espacio interactivo, escuchaban eventos de cambio de enfoque y, si el enfoque dejaba el espacio interactivo, se forzaba de nuevo. A los usuarios de teclados o lectores de pantalla se los guía de vuelta al espacio interactivo para asegurarse de que la tarea esté completa antes de continuar.

Después de inert, no se requiere captura, ya que puedes inmovilizar o proteger secciones completas de la página o la app. Los clics y los intentos de cambio de enfoque simplemente no están disponibles mientras esas partes de un documento estén inertes. También se podría pensar en esto como guardias en lugar de una trampa, en la que inert no está interesado en hacer que te quedes en algún lugar, sino en hacer que otros lugares no estén disponibles.

Un buen ejemplo de esto es la función alert() de JavaScript:

El sitio web se muestra como interactivo, se llama a alert() y la página ya no está activa.

Observa en el video anterior cómo se podía acceder a la página con el mouse y el teclado hasta que se llamó a alert(). Una vez que se mostró la ventana emergente del diálogo de alerta, el resto de la página se inmovilizó, o inert. El enfoque de los usuarios se ubica dentro del diálogo de alerta y no tiene otro lugar al que ir. Una vez que el usuario interactúa y completa la solicitud de la función de alerta, la página vuelve a ser interactiva. inert permite que los desarrolladores logren esta misma experiencia de enfoque guiado con facilidad.

A continuación, se incluye una pequeña muestra de código para ilustrar cómo funciona:

<body>
  <div class="modal">
    <h2>Modal Title</h2>
    <p>...<p>
    <button>Save</button>
    <button>Discard</button>
  </div>
  <main inert>
    <!-- cannot be keyboard focused or clicked -->
  </main>
</body>

Un diálogo es un excelente ejemplo, pero inert también es útil para cuestiones como la experiencia del usuario del menú lateral deslizante. Cuando un usuario desliza el menú lateral, no está bien dejar que el mouse o el teclado interactúen con la página detrás de él, lo que es un poco complicado para los usuarios. En cambio, cuando se muestra el menú lateral, inerte la página y, ahora, los usuarios deberán cerrar o navegar por ese menú lateral, y nunca se perderán en otro lugar de la página con un menú abierto.

Recursos

Fuentes COLRv1

Antes de las fuentes COLRv1, la Web tenía fuentes OT-SVG, también un formato abierto para fuentes con gradientes y colores y efectos integrados. Sin embargo, estas podían crecer mucho y, si bien permitían editar el texto, no había mucho alcance para la personalización.

Después de las fuentes COLRv1, la Web tiene fuentes más pequeñas, escalables con vectores, reposicionables, con funciones de gradiente y modo de combinación, que aceptan parámetros para personalizar la fuente por caso de uso o para hacer coincidir una marca.

Visualización comparativa y gráfico de barras que muestran cómo las fuentes COLRv1 son más nítidas y más pequeñas.
La imagen proviene de https://developer.chrome.com/blog/colrv1-fonts/

Este es un ejemplo de la entrada del Blog para desarrolladores de Chrome sobre emojis. Tal vez hayas notado que si aumentas el tamaño de la fuente en un emoji, este no se mantiene nítido. Es una imagen y no arte vectorial. A menudo, en las aplicaciones, cuando se usa un emoji, este se reemplaza por un recurso de mayor calidad. Con las fuentes COLRv1, los emojis son vectoriales y atractivos:

Las fuentes de íconos pueden lograr cosas increíbles con este formato, que ofrece paletas de colores personalizadas en dos tonos y mucho más. La carga de una fuente COLRv1 es como cualquier otro archivo de fuente:

@import url(https://fonts.googleapis.com/css2?family=Bungee+Spice);

La personalización de la fuente COLRv1 se realiza con @font-palette-values, una regla estándar de CSS especial para agrupar y nombrar un conjunto de opciones de personalización en un paquete para su referencia posterior. Observa cómo especificas un nombre personalizado como una propiedad personalizada, a partir de --:

@import url(https://fonts.googleapis.com/css2?family=Bungee+Spice);

@font-palette-values --colorized {
  font-family: "Bungee Spice";
  base-palette: 0;
  override-colors: 0 hotpink, 1 cyan, 2 white;
}

Con --colorized como alias para las personalizaciones, el último paso es aplicar la paleta a un elemento que use la familia de fuentes de colores:

@import url(https://fonts.googleapis.com/css2?family=Bungee+Spice);

@font-palette-values --colorized {
  font-family: "Bungee Spice";
  base-palette: 0;
  override-colors: 0 hotpink, 1 cyan, 2 white;
}

.spicy {
  font-family: "Bungee Spice";
  font-palette: --colorized;
}
Captura de pantalla de la fuente Bungee Spice con la palabra DUNE.
La fuente Bungee Spice se muestra con colores personalizados, fuente de https://developer.chrome.com/blog/colrv1-fonts/

Con cada vez más fuentes variables y de color disponibles, la tipografía web está en un camino magnífico hacia una personalización enriquecida y una expresión creativa.

Recursos

Unidades del viewport

Gráfico que muestra cómo la pantalla del dispositivo, la ventana del navegador y un iframe tienen diferentes viewports.

Antes de las nuevas variantes de viewport, la Web ofrecía unidades físicas para ayudar a ajustar las viewports. Había una para la altura, el ancho, el tamaño más pequeño (vmin) y el lado más grande (vmax). Si bien funcionaban bien para muchas cosas, los navegadores móviles introdujeron una complejidad.

En dispositivos móviles, cuando se carga una página, se muestra la barra de estado con la URL, y esta barra consume parte del espacio del viewport. Después de unos segundos y un poco de interactividad, es posible que la barra de estado se deslice hacia afuera para brindar al usuario una experiencia de viewport más grande. Sin embargo, cuando esa barra se desliza hacia afuera, cambia la altura del viewport, y cualquier unidad vh cambia y cambia de tamaño a medida que cambia el tamaño de destino. En años posteriores, la unidad vh tuvo que decidir específicamente cuál de los dos tamaños de viewport usaría, ya que causaba problemas de diseño visual molestos en los dispositivos móviles. Se determinó que vh siempre representaría el viewport más grande.

.original-viewport-units {
  height: 100vh;
  width: 100vw;
  --size: 100vmin;
  --size: 100vmax;
}

Una vez que se incorporan las nuevas variantes de viewport, se ponen a disposición las unidades de viewport pequeñas, grandes y dinámicas, con la adición de equivalentes lógicos a las físicas. La idea es darles a los desarrolladores y diseñadores la capacidad de elegir qué unidad desean usar para su situación específica. Tal vez esté bien tener un pequeño cambio de diseño discordante cuando la barra de estado desaparezca, por lo que se podría usar dvh (altura de viewport dinámica) sin preocupaciones.

Una imagen con tres teléfonos que ilustran los DVH, LVH y SVH. El teléfono de ejemplo del DVH tiene dos líneas verticales, una entre la parte inferior de la barra de búsqueda y la parte inferior del viewport, y otra entre la parte superior de la barra de búsqueda (debajo de la barra de estado del sistema) y la parte inferior del viewport, lo que muestra cómo el DVH puede ser cualquiera de estas dos longitudes. LVH se muestra en el medio con una línea entre la parte inferior de la barra de estado del dispositivo y el botón del viewport del teléfono. El último es el ejemplo de la unidad de SVH, que muestra una línea desde la parte inferior de la barra de búsqueda del navegador hasta la parte inferior del viewport

A continuación, se incluye una lista completa de todas las opciones nuevas de unidades de viewport disponibles con las nuevas variantes:

Unidades de altura de viewport
​​.new-height-viewport-units {
  height: 100vh;
  height: 100dvh;
  height: 100svh;
  height: 100lvh;
  block-size: 100vb;
  block-size: 100dvb;
  block-size: 100svb;
  block-size: 100lvb;
}
Unidades de ancho del viewport
.new-width-viewport-units {
  width: 100vw;
  width: 100dvw;
  width: 100svw;
  width: 100lvw;
  inline-size: 100vi;
  inline-size: 100dvi;
  inline-size: 100svi;
  inline-size: 100lvi;
}
Unidades laterales de la viewport más pequeñas
.new-min-viewport-units {
  --size: 100vmin;
  --size: 100dvmin;
  --size: 100svmin;
  --size: 100lvmin;
}
Unidades laterales del viewport más grandes
.new-max-viewport-units {
  --size: 100vmax;
  --size: 100dvmax;
  --size: 100svmax;
  --size: 100lvmax;
}

Se espera que estas funciones les brinden a los desarrolladores y diseñadores la flexibilidad necesaria para lograr que sus diseños responsivos de viewports se logren.

Recursos

:has()

Navegadores compatibles

  • 105
  • 105
  • 121
  • 15.4

Origen

Antes de :has(), el sujeto de un selector siempre estaba al final. Por ejemplo, el asunto de este selector es un elemento de lista: ul > li. Los seudoselectores pueden alterar el selector, pero no cambian el tema: ul > li:hover o ul > li:not(.selected).

Después de :has(), un sujeto que se encuentra más arriba en el árbol de elementos puede permanecer como tal mientras proporciona una consulta sobre los elementos secundarios: ul:has(> li). Es fácil comprender cómo :has() obtuvo un nombre común de "selector superior", ya que el sujeto del selector ahora es el superior en este caso.

Este es un ejemplo de sintaxis básica en el que la clase .parent sigue siendo el sujeto, pero solo se selecciona si un elemento secundario tiene la clase .child:

.parent:has(.child) {...}

Este es un ejemplo en el que un elemento <section> es el sujeto, pero el selector solo coincide si uno de los elementos secundarios tiene :focus-visible:

section:has(*:focus-visible) {...}

El selector :has() comienza a convertirse en una utilidad fantástica cuando aparecen más casos de uso prácticos. Por ejemplo, actualmente no es posible seleccionar etiquetas <a> cuando unen imágenes, lo que dificulta enseñarle a la etiqueta de anclaje cómo cambiar sus diseños en ese caso de uso. Sin embargo, es posible con :has():

a:has(> img) {...}

Todos estos son ejemplos en los que :has() solo parece un selector superior. Considera el caso de uso de imágenes dentro de elementos <figure> y el ajuste de estilos de las imágenes si la figura tiene un <figcaption>. En el siguiente ejemplo, se seleccionan figuras con TrueView y, luego, se muestran imágenes dentro de ese contexto. Se usa :has(), pero no cambia el tema, ya que nuestro objetivo son imágenes, no figuras:

figure:has(figcaption) img {...}

Las combinaciones aparentemente son infinitas. Combina :has() con consultas de cantidad y ajusta los diseños de cuadrícula de CSS según la cantidad de elementos secundarios. Combina :has() con pseudoclases interactivos y crea aplicaciones que respondan de nuevas maneras creativas.

La verificación de compatibilidad se simplifica con @supports y su función selector(), que prueba si el navegador comprende la sintaxis antes de usarla:

@supports (selector(:has(works))) {
  /* safe to use :has() */
}

Recursos

2022 y más allá

Todavía quedará una serie de cosas que serán difíciles de hacer después de que todas estas increíbles funciones lleguen en 2022. En la siguiente sección, se analizan algunos de los problemas restantes y las soluciones que se están desarrollando de forma activa para resolverlos. Estas soluciones son experimentales, aunque se puedan especificar o estar disponibles detrás de marcas en los navegadores.

El resultado de las siguientes secciones debería ser la tranquilidad de que muchas personas de muchas empresas buscan una solución a los problemas enumerados, no que estas soluciones se lanzarán en 2023.

Propiedades personalizadas poco escritas

Navegadores compatibles

  • 85
  • 85
  • 16.4

Origen

Las propiedades personalizadas de CSS son asombrosas. Permiten almacenar todo tipo de elementos dentro de una variable con nombre, que luego se puede extender, calcular, compartir y más. De hecho, son tan flexibles que sería bueno tener algunos que sean menos flexibles.

Considera una situación en la que un box-shadow usa propiedades personalizadas para sus valores:

box-shadow: var(--x) var(--y) var(--blur) var(--spread) var(--color);

Todo esto funciona bien hasta que una de las propiedades se cambia en un valor que CSS no acepta allí, como --x: red. Toda la sombra se interrumpe si falta alguna de las variables anidadas o si se establece un tipo de valor no válido.

Aquí es donde entra en juego @property: --x puede convertirse en una propiedad personalizada con tipografía, que ya no está suelta ni flexible, pero es segura con algunos límites definidos:

@property --x {
  syntax: '<length>';
  initial-value: 0px;
  inherits: false;
}

Ahora, cuando box-shadow use var(--x) y se intente realizar la --x: red posterior, se ignorará red, ya que no es <length>. Esto significa que la sombra sigue funcionando, aunque se asignó un valor no válido a una de sus propiedades personalizadas. En lugar de fallar, revierte a su initial-value de 0px.

Animación

Además de la seguridad de tipos, también abre muchas puertas a la animación. La flexibilidad de la sintaxis de CSS hace que sea imposible realizar animaciones, como los gradientes. @property es útil en este caso, ya que la propiedad de CSS escrita puede informar al navegador sobre el intent de un desarrollador dentro de una interpolación que, de otro modo, sería demasiado compleja. En esencia, limita el alcance de posibilidades en la medida en que un navegador puede animar aspectos de un diseño que antes no podía animar.

Considera este ejemplo de demostración, en el que se usa un gradiente radial para crear una parte de una superposición y crear un efecto de enfoque de foco. JavaScript establece las teclas "x" e "y" del mouse cuando se presiona la tecla Alt/opt y, luego, cambia el tamaño focal a un valor inferior (como un 25%) para crear el círculo de enfoque de enfoque en la posición del mouse:

Prueba la demostración
.focus-effect {
  --focal-size: 100%;
  --mouse-x: center;
  --mouse-y: center;

  mask-image: radial-gradient(
    circle at var(--mouse-x) var(--mouse-y),
    transparent 0%,
    transparent var(--focal-size),
    black 0%
  );
}

Sin embargo, no se pueden animar los gradientes. Son demasiado flexibles y complejos para que el navegador "simplemente derive" la forma en que quieres que se animen. Sin embargo, con @property, una propiedad se puede escribir y animar de forma aislada, para que el navegador pueda comprender fácilmente el intent.

Los videojuegos que usan este efecto de enfoque siempre animan el círculo, desde un círculo grande hasta un círculo pequeño. A continuación, se muestra cómo usar @property con nuestra demostración para que el navegador anime la máscara de gradiente:

@property --focal-size {
  syntax: '<length-percentage>';
  initial-value: 100%;
  inherits: false;
}

.focus-effect {
  --focal-size: 100%;
  --mouse-x: center;
  --mouse-y: center;

  mask-image: radial-gradient(
    circle at var(--mouse-x) var(--mouse-y),
    transparent 0%,
    transparent var(--focal-size),
    black 0%
  );

  transition: --focal-size .3s ease;
}
Prueba la demostración

El navegador ahora puede animar el tamaño del gradiente porque redujimos el área de la superficie de la modificación a una sola propiedad y escribimos el valor para que el navegador pueda interpolar las longitudes de manera inteligente.

@property puede hacer mucho más, pero estas pequeñas habilitaciones pueden ser muy útiles.

Recursos

Fue en min-width o max-width

Antes de los rangos de consultas de medios, una consulta de medios de CSS usa min-width y max-width para articular sobre ciertas condiciones. Es posible que se vea de este modo:

@media (min-width: 320px) {
  …
}

Después de los rangos de consultas de medios, la misma consulta de medios podría verse así:

@media (width >= 320px) {
  …
}

Una consulta de medios de CSS que use min-width y max-width puede verse de la siguiente manera:

@media (min-width: 320px) and (max-width: 1280px) {
  …
}

Después de los rangos de consultas de medios, la misma consulta de medios podría verse así:

@media (320px <= width <= 1280px) {
  …
}

Según tu fondo de programación, una de ellas se verá mucho más legible que la otra. Gracias a las incorporaciones en las especificaciones, los desarrolladores podrán elegir cuál prefieren o incluso usarlas de forma indistinta.

Recursos

No hay variables de consulta de medios

Antes de @custom-media, las consultas de medios tenían que repetirse una y otra vez o confiar en preprocesadores para generar el resultado adecuado basado en variables estáticas durante el tiempo de compilación.

Después de @custom-media, CSS permite asignar alias a consultas de medios y hacer referencia a ellas, al igual que con una propiedad personalizada.

Nombrar elementos es muy importante: puede alinear el propósito con la sintaxis, lo que facilita compartir los elementos y de usar en los equipos. Estas son algunas consultas de medios personalizadas que me siguen entre proyectos:

@custom-media --OSdark  (prefers-color-scheme: dark);
@custom-media --OSlight (prefers-color-scheme: light);

@custom-media --pointer (hover) and (pointer: coarse);
@custom-media --mouse   (hover) and (pointer: fine);

@custom-media --xxs-and-above (width >= 240px);
@custom-media --xxs-and-below (width <= 240px);

Ahora que están definidos, puedo usar uno de ellos de la siguiente manera:

@media (--OSdark) {
  :root {
    …
  }
}

Encontrar una lista completa de consultas de medios personalizados que uso en la biblioteca de propiedades personalizadas de CSS Open Props

Recursos

Anidar selectores es muy agradable

Antes del @nest, las hojas de estilo se repiten mucho. Se volvía especialmente difícil de manejar cuando los selectores eran largos y cada uno apuntaba a pequeñas diferencias. La comodidad de la anidación es una de las razones más comunes para adoptar un preprocesador.

Después de @nest, la repetición desaparece. Casi todas las funciones del anidamiento habilitado para el preprocesador estará disponible integrado en CSS.

article {
  color: darkgray;
}

article > a {
  color: var(--link-color);
}

/* with @nest becomes */

article {
  color: darkgray;

  & > a {
    color: var(--link-color);
  }
}

Para mí, lo más importante sobre la anidación, además de no repetir article en el selector anidado, es que el contexto de diseño permanezca dentro de un bloque de diseño. En lugar de saltar de un selector y sus estilos a otro selector con estilos (ejemplo 1), el lector puede permanecer dentro del contexto de un artículo y ver que el artículo posee vínculos dentro de él. La relación y el intent de estilo se empaquetan, por lo que article parece tener sus propios estilos.

La propiedad también podría considerarse centralización. En lugar de buscar diseños relevantes en una hoja de estilo, todas se pueden encontrar anidadas dentro de un contexto. Esto funciona con relaciones de superior a secundario, pero también con relaciones de elemento secundario a secundario.

Considera un componente secundario que desea ajustarse a sí mismo cuando está en un contexto superior diferente, a diferencia del elemento superior que posee el diseño y cambia un elemento secundario:

/* parent owns this, adjusting children */
section:focus-within > article {
  border: 1px solid hotpink;
}

/* with @nest becomes */

/* article owns this, adjusting itself when inside a section:focus-within */
article {
  @nest section:focus-within > & {
     border: 1px solid hotpink;
  }
}

En general, @nest ayuda a tener un estilo más saludable en la organización, la centralización y la propiedad. Los componentes pueden agrupar y poseer sus propios estilos, en lugar de dividirlos entre otros bloques de diseño. Puede parecer pequeño en estos ejemplos, pero puede tener impactos muy grandes, tanto para la conveniencia como para la legibilidad.

Recursos

Definir el alcance de los estilos es muy difícil

Navegadores compatibles

  • 118
  • 118
  • x
  • 17,4

Antes de @scope, existían muchas estrategias porque los diseños en CSS se transmiten en cascada, se heredan y tienen un alcance global de forma predeterminada. Estas funciones de CSS son muy convenientes para muchas funciones; sin embargo, en el caso de sitios y aplicaciones complejos, con posiblemente muchos estilos de componentes diferentes, el espacio global y la naturaleza de la cascada pueden hacer que los estilos parezcan fugas.

Después de @scope, no solo se puede establecer el alcance de los diseños solo dentro de un contexto, como una clase, sino que también pueden articular dónde terminan los diseños y no continúan en cascada ni se heredan.

En el siguiente ejemplo, el alcance de la convención de nombres BEM se puede revertir al intent real. El selector de BEM intenta definir el alcance del color de un elemento header en un contenedor .card con convenciones de nomenclatura. Esto requiere que el encabezado tenga este nombre de clase, lo que completa el objetivo. Con @scope, no se requieren convenciones de nombres para completar el mismo objetivo sin marcar el elemento del encabezado:

.card__header {
  color: var(--text);
}

/* with @scope becomes */

@scope (.card) {
  header {
    color: var(--text);
  }
}

A continuación, veremos otro ejemplo, menos específico de componentes y más sobre la naturaleza del alcance global de CSS. Los temas oscuros y claros deben coexistir dentro de una hoja de estilo, en la que el orden es importante para determinar el estilo ganador. Por lo general, esto significa que los diseños del tema oscuro vendrán después del tema claro, y establecerá el color claro como predeterminado y oscuro como el opcional. Evita las batallas de orden y alcance con @scope:

​​@scope (.light-theme) {
  a { color: purple; }
}

@scope (.dark-theme) {
  a { color: plum; }
}

Para completar la historia aquí, @scope también permite establecer el lugar donde finaliza el alcance de diseño. Esto no se puede hacer con ningún preprocesador o convención de nombres. Es especial y solo puede hacer algo CSS integrado en el navegador. En el siguiente ejemplo, los estilos img y .content se aplican exclusivamente cuando un elemento secundario de un .media-block es del mismo nivel o superior de .content:

@scope (.media-block) to (.content) {
  img {
    border-radius: 50%;
  }

  .content {
    padding: 1em;
  }
}

Recursos

No existe una manera de CSS para un diseño de mampostería

Antes de la mampostería de CSS con cuadrícula, JavaScript era la mejor manera de lograr un diseño de mampostería, ya que cualquiera de los métodos de CSS con columnas o flexbox representaba de forma imprecisa el orden del contenido.

Después de la mampostería de CSS con la cuadrícula, no se requerirán bibliotecas de JavaScript y el orden del contenido será correcto.

Captura de pantalla del diseño de albañilería que muestra los números que viajan por la parte superior y luego descienden.
Imagen y demostración de Smashing Magazine
https://www.smashingmagazine.com/native-css-masonry-layout-css-grid/

La demostración anterior se logra con el siguiente CSS:

.container {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: masonry;
}

Es reconfortante saber que es una estrategia de diseño faltante, además puedes probarla hoy en Firefox.

Recursos

El CSS no puede ayudar a los usuarios a reducir datos

Navegadores compatibles

  • x
  • x

Origen

Antes de la consulta de medios prefers-reduced-data, JavaScript y un servidor podían cambiar su comportamiento en función del sistema operativo o la opción de "ahorro de datos" del navegador del usuario, pero CSS no podía.

Después de la consulta de medios prefers-reduced-data, CSS puede unir la mejora de la experiencia del usuario y desempeñar su papel en el almacenamiento de datos.

@media (prefers-reduced-data: reduce) {
  picture, video {
    display: none;
  }
}

El CSS anterior se usa en este componente de desplazamiento de contenido multimedia, y el ahorro puede ser enorme. Según qué tan grande sea el viewport de la visita, más ahorro se obtendrá al cargar la página. El guardado continúa mientras los usuarios interactúan con los desplazadores de contenido multimedia. Todas las imágenes tienen atributos loading="lazy", lo que, combinado con CSS que oculta el elemento por completo, nunca realiza una solicitud de red para la imagen.

Captura de pantalla de una interfaz de carrusel de programas de TV en la que se muestran muchas miniaturas y títulos.

Para mi prueba, en un viewport de tamaño mediano, se cargaron inicialmente 40 solicitudes y 700 KB de recursos. A medida que un usuario se desplaza por la selección de contenido multimedia, se cargan más solicitudes y recursos. Con el CSS y la búsqueda de medios de datos reducida, se cargan 10 solicitudes y 172 KB de recursos. Esto equivale a medio megabyte de ahorro y el usuario ni siquiera se desplazó por ninguno de los medios, por lo que no se realizaron solicitudes adicionales.

Captura de pantalla de la interfaz de un carrusel de programas de TV sin miniaturas y se muestran muchos títulos.

Esta experiencia de datos reducida ofrece más ventajas que solo el ahorro de datos. Se pueden ver más títulos y no hay imágenes de portada que distraigan la atención de los usuarios. Muchos usuarios navegan en modo de ahorro de datos porque pagan por megabyte de datos. Es muy bueno ver cómo CSS puede ayudar en este caso.

Recursos

Las funciones para ajustar el desplazamiento son demasiado limitadas

Antes de estas propuestas de ajuste de desplazamiento, escribir tu propio JavaScript para administrar un carrusel, un control deslizante o una galería podría volverse complejo con todos los observadores y la administración de estados. Además, si no hay cuidado, las velocidades de desplazamiento naturales podrían normalizarse por secuencia de comandos, lo que hará que la interacción del usuario se sienta un poco poco natural y potencialmente engorrosa.

API nuevas

snapChanging()

Tan pronto como el navegador lance un elemento secundario de Snap, se activa este evento. Esto permite que la IU refleje la falta de un elemento secundario de Snap y el estado de ajuste indeterminado del desplazador, ya que ahora se está usando y llegará a un lugar nuevo.

document.querySelector('.snap-carousel').addEventListener('snapchanging', event => {
  console.log('Snap is changing', event.snappedTargetsList);
});
snapChanged()

Tan pronto como el navegador se ajuste a un nuevo elemento secundario y la barra de desplazamiento finalice, se activará este evento. Esto permite que cualquier IU que dependa del elemento secundario ajustado se actualice y refleje la conexión.

document.querySelector('.snap-carousel').addEventListener('snapchanged', event => {
  console.log('Snap changed', event.snappedTargetsList);
});
scroll-start

El desplazamiento no siempre comienza al principio. Considera usar componentes deslizables en los que el deslizamiento hacia la izquierda o la derecha activa diferentes eventos, o una barra de búsqueda que, cuando se carga la página, se oculta inicialmente hasta que te desplazas hacia la parte superior. Esta propiedad de CSS permite a los desarrolladores especificar que una barra de desplazamiento debe comenzar en un punto específico.

:root { --nav-height: 100px }

.snap-scroll-y {
  scroll-start-y: var(--nav-height);
}
:snap-target

Este selector CSS hará coincidir los elementos de un contenedor de ajuste de desplazamiento que el navegador ajusta actualmente.

.card {
  --shadow-distance: 5px;
  box-shadow: 0 var(--shadow-distance) 5px hsl(0 0% 0% / 25%);
  transition: box-shadow 350ms ease;
}

.card:snapped {
  --shadow-distance: 30px;
}

Después de estas propuestas de ajuste de desplazamiento, es mucho más fácil crear un control deslizante, un carrusel o una galería, ya que el navegador ahora ofrece ventajas para la tarea, lo que elimina a los observadores y el código de organización de desplazamientos para favorecer el uso de las APIs integradas.

Estas funciones de CSS y JS aún son muy tempranas, pero hay polyfills que pronto pueden ayudar a su adopción y prueba.

Recursos

Cómo alternar entre estados conocidos

Antes del toggle(), solo los estados integrados en el navegador ya se podían aprovechar para el estilo y la interacción. La entrada de la casilla de verificación, por ejemplo, tiene :checked, un estado de navegador administrado de forma interna para la entrada que CSS puede usar a fin de cambiar el elemento visualmente.

Después del toggle(), se pueden crear estados personalizados en cualquier elemento para que CSS los cambie y use para el diseño. Permite grupos, ciclismo, activación y desactivación directa y mucho más.

En el siguiente ejemplo, se logra el mismo efecto del tachado en un elemento de la lista cuando se completa, pero sin ningún elemento de la casilla de verificación:

<ul class='ingredients'>
   <li>1 banana
   <li>1 cup blueberries
  ...
</ul>

Y los estilos toggle() de CSS relevantes:

li {
  toggle-root: check self;
}

li:toggle(check) {
  text-decoration: line-through;
}

Si estás familiarizado con las máquinas de estado, es posible que notes cuánto cruce hay con toggle(). Esta función permitirá a los desarrolladores compilar más de su estado en CSS, lo que probablemente dará como resultado formas más claras y semánticas de organizar la interacción y el estado.

Recursos

Cómo personalizar determinados elementos

Antes del <selectmenu>, CSS no tenía la capacidad de personalizar elementos <option> con HTML enriquecido ni cambiar mucho sobre la visualización de una lista de opciones. Esto llevó a los desarrolladores a cargar bibliotecas externas que recreaban gran parte de la funcionalidad de un <select>, lo que dio como resultado mucho trabajo.

Después de <selectmenu>, los desarrolladores pueden proporcionar HTML enriquecido para los elementos de opciones y diseñarlos tanto como necesiten, sin dejar de cumplir con los requisitos de accesibilidad y proporcionar HTML semántico.

En el siguiente ejemplo, tomado de la página de explicación <selectmenu>, se crea un nuevo menú de selección con algunas opciones básicas:

<selectmenu>
  <option>Option 1</option>
  <option>Option 2</option>
  <option>Option 3</option>
</selectmenu>

CSS puede orientar las partes del elemento y aplicarles estilos:

.my-select-menu::part(button) {
  color: white;
  background-color: red;
  padding: 5px;
  border-radius: 5px;
}

.my-select-menu::part(listbox) {
  padding: 10px;
  margin-top: 5px;
  border: 1px solid red;
  border-radius: 5px;
}

Un menú selecto con colores de acento rojos.

Puedes probar el elemento <selectmenu> en Chromium en Canary con la marca de experimentos web habilitada. A partir de 2023, ten cuidado con la selección de elementos de menú personalizables.

Recursos

Fija un elemento a otro

Antes de anchor(), la posición absoluta y relativa eran estrategias de posición que se ofrecían a los desarrolladores para que los elementos secundarios se movieran dentro de un elemento superior.

Después de anchor(), los desarrolladores pueden posicionar elementos en relación con otros, más allá de que sean elementos secundarios o no. También permite que los desarrolladores especifiquen con qué borde deben posicionarse y otras cualidades para crear relaciones de posición entre elementos.

La explicación tiene algunos excelentes ejemplos y muestras de código que se proporcionan si te interesa obtener más información.

Recursos