Al igual que las consultas de contenedores, pero para consultas atascadas, ajustadas y desbordadas.
Fecha de publicación: 15 de enero de 2025
Chrome 133 se basa en las consultas de contenedores, ya que presenta consultas de contenedores de estado de desplazamiento. El estado administrado por el navegador para el posicionamiento fijo, los puntos de ajuste del desplazamiento y los elementos desplazables ahora se puede consultar y adaptar desde CSS.
Descripción general
Antes de realizar consultas de estado de desplazamiento, debes usar JavaScript para comprender si un elemento está bloqueado, ajustado o desplazable. Ahora hay un método más eficaz en el segmento de estándares para conocer esta información y adaptarse según corresponda. También hay una nueva forma de activar animaciones, lo que desbloquea la animación activada por desplazamiento desde CSS.
A continuación, se incluye una descripción general de las consultas de estado disponibles a partir de Chrome 133:
- Estado bloqueado:
- Ejecuta cambios de diseño cuando un elemento está pegado a un borde.
- Estado ajustado:
- Activa los cambios de diseño cuando un elemento se ajusta a un eje.
- Estado desplazable:
- Activa los cambios de diseño cuando un elemento se desborda.
La buena noticia es que todo lo que aprendiste sobre las consultas de contenedor te ayudará a trabajar con las consultas de estado de desplazamiento.
También hay un territorio inexplorado entre las animaciones impulsadas por el desplazamiento y las consultas del contenedor de estado de desplazamiento. Debemos experimentar con el tiempo y el contexto para descubrir si es mejor una animación impulsada por el desplazamiento o una animación de estado de desplazamiento activada por el desplazamiento. En el siguiente video y demostración, se ilustra la situación: una animación activada fija en comparación con una animación impulsada por el desplazamiento.
Primera consulta de estado de desplazamiento
El primer paso es definir el contenedor con un valor nuevo para la propiedad container-type
. Al igual que con una consulta de contenedor, el elemento que deseas consultar es el que le asignas a container-type
y, de manera opcional, a container-name
. Con las consultas de estado de desplazamiento, le asignas el elemento que se ajusta, se bloquea o tiene desbordamiento container-type: scroll-state
.
.stuck-top {
container-type: scroll-state;
position: sticky;
top: 0px;
}
El segundo paso es seleccionar el elemento secundario de ese contenedor que responderá al estado, ya que, al igual que con las consultas de contenedores, no puede ser el mismo elemento que tiene el container-type
.
.stuck-top {
container-type: scroll-state;
position: sticky;
top: 0px;
> nav {
@container scroll-state(stuck: top) {
background: Highlight;
color: HighlightText;
}
}
}
El tercer paso es probarlo. En el siguiente ejemplo de CSS, se aplicará el estilo de fondo rojo cuando el elemento .stuck-top
se adhiera a la parte superior en 0
. Con algunas líneas adicionales al CSS que ya escribimos y un elemento contenedor adicional que actúa como proxy del estado del navegador, nuestros componentes son mucho más inteligentes en cuanto a su entorno.
Mejora progresiva
La regla de anidación y la regla @supports
pueden permitirte agregar la mejora progresiva o el uso de funciones condicionales en solo un par de líneas de código adicionales:
.stuck-top {
container-type: scroll-state;
position: sticky;
top: 0px;
@supports (container-type: scroll-state) {
> nav {
@container scroll-state(stuck: top) {
background: Highlight;
color: HighlightText;
}
}
}
}
Además, recuerda usar @media (prefers-reduced-motion: no-preference) {}
alrededor de tu movimiento si terminas animando elementos alrededor de la página con consultas de estado de desplazamiento.
Casos de uso
Atasco
¿Tal vez esta sección debería llamarse "situaciones difíciles"? Esta es una pequeña colección de casos de uso de estado fijo, además de una sección adicional de ideas que se deben crear.
@container scroll-state(stuck: top) {}
@container scroll-state(stuck: bottom) {}
Cómo agregar una sombra cuando se produce un bloqueo
Uno de los casos de uso más comunes de una consulta bloqueada es para las barras de navegación que desean agregar box-shadow
cuando están bloqueadas, de modo que puedan parecer que flotan sobre el contenido que superponen.
.stuck-top {
container-type: scroll-state;
position: sticky;
top: 0px;
> nav {
transition: box-shadow .3s ease;
@container scroll-state(stuck: top) {
box-shadow: var(--shadow-5);
}
}
}
Activa el encabezado bloqueado actual
Otro escenario común de comentarios de IU fija es destacar el elemento que está bloqueado. En una lista de bandas alfabéticamente ordenadas, esto puede ser muy útil y ayudar a la experiencia.
.sticky-slide {
dt {
container-type: scroll-state;
position: sticky;
inset-block-start: 0;
inset-inline: 0;
> header {
transition:
background .3s ease,
box-shadow .5s ease;
@container scroll-state(stuck: top) {
background: hsl(265 100% 27%);
box-shadow: 0 5px 5px #0003;
}
}
}
}
Esta es otra variante, en la que los encabezados están al costado de los elementos de la lista. ¡Hay muchas posibilidades!
Idea desbordada
Esta es una lista de demostraciones fijas que podrían inspirarte a agregarle un poco de sabor o quitar su código JavaScript con consultas de estado de desplazamiento. Te sugiero que intentes crear uno que te guste. Esto ayudará a que la sintaxis y las ideas se fijen 😏.
- https://codepen.io/BlogFire/pen/PoGMjaX: Variante de notas adhesivas
- https://codepen.io/mikegolus/pen/jOZzRzw: Agrega sombras a una tabla cuando se pegan.
- https://codepen.io/MarcRay/pen/PomBeP: La barra de navegación del encabezado aparece en el activador.
- https://codepen.io/kevinpowell/pen/OqKJjK: Revelación de la barra de navegación del pie de página
- https://codepen.io/abhisekz-the-decoder/pen/eKaLRd: Encabezados de tarjetas fijos
- https://codepen.io/tutsplus/pen/abojPjP: Sombra del encabezado de precios en el activador
- https://codepen.io/kevinpowell/pen/KEjMEv: Títulos de la barra lateral de la sección fija
Ajustado
Con las consultas de estado ajustado, podemos quitar parte de la responsabilidad de JavaScript y los eventos de ajuste, y trasladar el control a CSS.
@container scroll-state(snapped: x) {}
@container scroll-state(snapped: y) {}
@container scroll-state(snapped: inline) {}
@container scroll-state(snapped: block) {}
Te recordamos que, en caso de que hayas omitido la sección Primera consulta de estado de desplazamiento, el contenedor de una consulta de ajuste es el elemento con scroll-snap-align
, y el elemento que puede adaptarse debe ser secundario de ese elemento. Esto significa que hay tres elementos necesarios para configurarlo:
a scroll container with `scroll-snap-type`
⤷ a snap target with both `scroll-snap-align` and `container-type: scroll-state`
⤷ a child of the snap target that can query the container for snap state
Cómo mejorar visualmente el elemento ajustado
Es muy común que un control deslizante centrado destaque o muestre el elemento centrado. En este ejemplo de testimonios, se usa la palabra clave not
para que todos los testimonios no ajustados tengan una opacidad baja, mientras que el ajustado se encuentra en su estado de presentación natural.
.demo {
overflow: auto hidden;
scroll-snap-type: x mandatory;
> article {
container-type: scroll-state;
scroll-snap-align: center;
@supports (container-type: scroll-state) {
> * {
transition: opacity .5s ease;
@container not scroll-state(snapped: x) {
opacity: .25;
}
}
}
}
}
Mostrar la leyenda del elemento ajustado
Este es un buen ejemplo de cómo las consultas de estado de desplazamiento habilitan la animación activada por desplazamiento. También es un buen ejemplo de cuándo es valioso respetar el movimiento reducido en el CSS.
.demo {
overflow-x: auto;
scroll-behavior-x: contain;
scroll-snap-type: x mandatory;
> .card {
container-type: scroll-state;
scroll-snap-align: center;
@supports (container-type: scroll-state) {
@media (prefers-reduced-motion: no-preference) {
figcaption {
transform: translateY(100%);
@container scroll-state(snapped: x) {
transform: translateY(0);
}
}
}
}
}
}
Cómo animar elementos de diapositivas
Es muy común animar elementos de una presentación de diapositivas o una presentación cuando se da una charla. Antes, era bastante molesto escribir un observador de intersección para esto, que solo configuraba una clase en la diapositiva. Ahora no necesitamos ningún JavaScript.
html {
scroll-snap-type: y mandatory;
}
section {
container-type: scroll-state;
scroll-snap-align: start;
scroll-snap-stop: always;
@supports (container-type: scroll-state) {
@media (prefers-reduced-motion: no-preference) {
> h1 {
transition: opacity .5s ease, transform .5s var(--ease-spring-3);
transition-delay: .5s;
opacity: 0;
transform: scale(1.25);
@container scroll-state(snapped: block) {
opacity: 1;
transform: scale(1);
}
}
}
}
}
Es posible que notes que todas las consultas de estado de CSS ajustadas se comportan como scrollsnapchanging
, en lugar de scrollsnapchange
. Esto te brinda el hook más temprano posible para proporcionar comentarios visuales del elemento ajustado. Si es demasiado pronto, considera el evento de JavaScript.
Desplazable
La consulta de estado desplazable será muy útil para mostrar indicaciones visuales cuando se pueda desplazar una zona de desplazamiento. Hasta las consultas de estado de desplazamiento, esta era información difícil de conocer.
@container scroll-state(scrollable: top) {}
@container scroll-state(scrollable: right) {}
@container scroll-state(scrollable: bottom) {}
@container scroll-state(scrollable: left) {}
Indica el desplazamiento con sombras
Hay un famoso truco de CSS de Lea Verou que usa background-attachment: local
para lograr un efecto similar a este, así como una forma de hacerlo con una animación basada en el desplazamiento. Cada técnica tiene compensaciones, y depende de nosotros explorar cuándo y dónde es más adecuada cada una de ellas.
En el siguiente ejemplo, se usa un solo elemento fijo que abarca el desplazamiento. Un gradiente en la parte superior y otro en la parte inferior tienen su opacidad animada con @property
cuando se aplica su consulta de estado de desplazamiento contextual: @container scroll-state(scrollable: top)
.
También ten en cuenta que es el primer contenedor que es size
y scroll-state
.
.scroll-container {
container-type: scroll-state size;
overflow: auto;
&::after {
content: " ";
background: var(--_shadow-top), var(--_shadow-bottom);
transition:
--_scroll-shadow-color-1-opacity .5s ease,
--_scroll-shadow-color-2-opacity .5s ease;
@container scroll-state(scrollable: top) {
--_scroll-shadow-color-1-opacity: var(--_shadow-color-opacity, 25%);
}
@container scroll-state(scrollable: bottom) {
--_scroll-shadow-color-2-opacity: var(--_shadow-color-opacity, 25%);
}
}
}
Instrucción de flecha
A veces, mostrar una flecha puede ayudar a los usuarios a descubrir que un área se puede desplazar. Suelen apuntar en la dirección en la que se puede desplazar el contenido y desaparecen una vez que ya no son necesarios. Puedes hacerlo con el siguiente código.
@container scroll-state((scrollable: top) or (not (scrollable: bottom))) {
translate: 0 calc(100% + 10px);
}
@container scroll-state((scrollable: top) and (not (scrollable: bottom))) {
translate: 0 calc(100% + 10px);
rotate: .5turn;
}
Volver al principio
Otra interacción popular del estado de desplazamiento es el botón de conveniencia "desplazarse hasta la parte superior". El siguiente código hace que el botón de desplazamiento hacia arriba desaparezca cuando no hay ningún lugar para desplazarse hacia arriba.
Esta solución está un poco invertida, pero te permite reducir la cantidad de CSS. El lugar de descanso natural del botón está a la vista, por lo que debes indicarle que se oculte cuando no haya más lugar para desplazarse hacia arriba.
@container not scroll-state(scrollable: top) {
translate: 0 calc(100% + 10px);
}
Estudio continuo
Si quieres obtener más información, consulta los siguientes recursos, que incluyen desde detalles de las especificaciones hasta otros artículos interesantes sobre este tema:
- ¿Qué más deberíamos poder consultar en los contenedores? https://github.com/w3c/csswg-drafts/issues/5989
- Explicación de scroll-state(): https://drafts.csswg.org/css-conditional-5/scroll_state_explainer.md
- Especificación de CSS scroll-state(): https://www.w3.org/TR/css-conditional-5/#scroll-state-container
- Captura de instantáneas del diseño en el bucle de eventos de HTML
- Un episodio de podcast sobre consultas de estado: https://nerdy.dev/the-css-podcast-on-state-queries
- Más artículos
- https://utilitybend.com/blog/is-the-sticky-thing-stuck-is-the-snappy-item-snapped-a-look-at-state-queries-in-css/
- https://ishadeed.com/article/css-state-queries/
- https://csscade.com/can-you-detect-overflow-with-css/
- https://css-tip.com/overflow-detection/: Detecta con animación impulsada por desplazamiento de una manera que más de solo los elementos secundarios pueden saber (con la desventaja de la trampa)