Ayudando a los navegadores a optimizar con la propiedad CSS Contain

Publicado: 2022-03-10
Resumen rápido ↬ La propiedad de contain CSS le brinda una manera de explicar su diseño al navegador, para que se puedan realizar optimizaciones de rendimiento. Sin embargo, viene con algunos efectos secundarios en términos de su diseño.

En este artículo, voy a presentar una especificación CSS que acaba de convertirse en una recomendación W3C. La especificación de contención CSS define una propiedad única, contain , y puede ayudarlo a explicarle al navegador qué partes de su diseño son independientes y no necesitarán volver a calcularse si alguna otra parte del diseño cambia.

Si bien esta propiedad existe por razones de optimización del rendimiento, también puede afectar el diseño de su página. Por lo tanto, en este artículo, explicaré los diferentes tipos de contención de los que puede beneficiarse, pero también las cosas que debe tener en cuenta si aplica la contain a los elementos de su sitio.

El problema del recálculo del diseño

Si está creando páginas web sencillas que no agregan ni cambian elementos dinámicamente después de que se hayan cargado mediante JavaScript, no necesita preocuparse por el problema que resuelve CSS Containment. El navegador solo necesita calcular su diseño una vez, mientras se carga la página.

Donde la Contención se vuelve útil es cuando desea agregar elementos a su página sin que el usuario necesite volver a cargarla. En mi ejemplo, creé una gran lista de eventos. Si hace clic en el botón, se modifica el primer evento, se agrega un elemento flotante y se cambia el texto:

Una lista de elementos con un botón para cambiar parte del contenido del primer elemento
(Ver el ejemplo inicial en CodePen)

Cuando se cambia el contenido de nuestra casilla, el navegador tiene que considerar que alguno de los elementos puede haber cambiado. En general, los navegadores son bastante buenos para lidiar con esto, ya que es algo común que sucede. Dicho esto, como desarrollador, sabrá si cada uno de los componentes es independiente y que un cambio en uno no afecta a los demás, por lo que sería bueno que pudiera informar al navegador a través de su CSS. Esto es lo que le brinda la propiedad de contain y CSS.

¡Más después del salto! Continúe leyendo a continuación ↓

¿Cómo ayuda la contención?

Un documento HTML es una estructura de árbol que puede ver al inspeccionar cualquier elemento con DevTools. En mi ejemplo anterior, identifico un elemento que quiero cambiar usando JavaScript y luego realizo algunos cambios en las partes internas. (Esto significa que solo estoy cambiando cosas dentro del subárbol para ese elemento de la lista).

DevTools con el elemento de la lista del elemento destacado expandido para ver los elementos dentro
Inspeccionar un elemento de lista en DevTools

La aplicación de la propiedad de contain a un elemento le dice al navegador que los cambios se limitan al subárbol de ese elemento, de modo que el navegador puede realizar cualquier optimización posible, con la certeza de que nada más fuera de ese elemento cambiará. Exactamente lo que un navegador en particular podría hacer depende del motor. La propiedad CSS simplemente le brinda, como desarrollador y experto en este diseño, la oportunidad de informarlo.

En muchos casos, estará seguro de seguir adelante y comenzar a usar la propiedad de contain , sin embargo, los diferentes valores tienen algunos efectos secundarios potenciales que vale la pena comprender antes de agregar la propiedad a los elementos de su sitio.

Uso de contención

La propiedad contain puede establecer tres tipos diferentes de contención:

  • layout
  • paint
  • size

Nota : Hay un valor de style en la especificación de nivel 2. Se eliminó del Nivel 1, por lo que no aparece en la Recomendación y no está implementado en Firefox.

Disposición

La contención del diseño brinda los mayores beneficios. Para activar la contención de diseño, use el siguiente fragmento:

 .item { contain: layout; }

Con la contención de diseño habilitada, el navegador sabe que nada fuera del elemento puede afectar el diseño interno, y nada dentro del elemento puede cambiar nada sobre el diseño de las cosas fuera de él. Esto significa que puede realizar cualquier optimización posible para este escenario.

Algunas cosas adicionales suceden cuando la contención de diseño está habilitada. Todas estas son cosas que aseguran que esta caja y su contenido sean independientes del resto del árbol.

El cuadro establece un contexto de formato independiente . Esto asegura que el contenido de la caja permanezca en la caja; en particular, los flotantes estarán contenidos y los márgenes no colapsarán a través de la caja. Este es el mismo comportamiento que activamos cuando usamos display: flow-root como se explica en mi artículo "Comprender el diseño CSS y el contexto de formato de bloque". Si un flotador pudiera sobresalir de su caja, haciendo que el siguiente texto fluya alrededor del flotador, esa sería una situación en la que el elemento cambiaría el diseño de las cosas fuera de él, lo que lo convertiría en un mal candidato para la contención.

La caja contenedora actúa como el bloque contenedor para cualquier descendiente de posición absoluta o fija. Esto significa que actuará como si hubiera usado position: relative en el cuadro que aplicó contain: layout .

La caja también crea un contexto de apilamiento . Por lo tanto z-index funcionará en este elemento, sus elementos secundarios se apilarán en función de este nuevo contexto.

Si nos fijamos en el ejemplo, esta vez con contain: layout , puedes ver que cuando se introduce el elemento flotante ya no sobresale por la parte inferior de la caja. Este es nuestro nuevo contexto de formato de bloque en acción, que contiene el flotante.

Una lista de elementos, un elemento flotante está contenido dentro de los límites del cuadro principal
Usando contiene: diseño, el flotador está contenido (consulte el ejemplo de contención de diseño en CodePen)

Pintura

Para activar la contención de pintura, utilice lo siguiente:

 .item { contain: paint; }

Con la contención de pintura habilitada, se producen los mismos efectos secundarios que se observan con la contención de diseño: el cuadro contenedor se convierte en un contexto de formato independiente, un bloque contenedor para elementos posicionados y establece un contexto de apilamiento.

Lo que hace la contención de pintura es indicarle al navegador que los elementos dentro del bloque contenedor no serán visibles fuera de los límites de ese cuadro. El contenido será esencialmente recortado a la caja.

Podemos ver que esto sucede con un ejemplo simple. Incluso si le damos una altura a nuestra tarjeta, el elemento flotante todavía sobresale por la parte inferior de la caja, debido al hecho de que el flotador está fuera del flujo.

Una caja flotante que sobresale del fondo de una caja contenedora.
El flotante no está contenido en el elemento de la lista.

Con la contención de pintura activada, el elemento flotante ahora se recorta al tamaño de la caja. No se puede pintar nada fuera de los límites del elemento con la contain: paint aplicada.

Una caja con una caja flotante dentro de la cual se ha cortado por donde escapa de la caja.
El contenido de la caja se recorta a la altura de la caja (Vea el ejemplo de pintura en CodePen)

Tamaño

La contención de tamaño es el valor que es más probable que le cause un problema si no está completamente consciente de cómo funciona. Para aplicar la contención de tamaño, utilice:

 .item { contain: size; }

Si usa la contención de tamaño, le está diciendo al navegador que conoce el tamaño de la caja y que no va a cambiar. Esto significa que si tiene un cuadro cuyo tamaño se ajusta automáticamente en la dimensión del bloque, se tratará como si el contenido no tuviera tamaño, por lo tanto, el cuadro se colapsará como si no tuviera contenido.

En el siguiente ejemplo, no le he dado una altura a li ; también contain: size aplicado. Puede ver que todos los elementos se han colapsado como si no tuvieran ningún contenido, lo que lo convierte en una lista de aspecto muy peculiar.

Una lista de elementos con un botón para cambiar parte del contenido del primer elemento
(Vea el ejemplo de tamaño en CodePen)

Si le da a las cajas una altura, se respetará la altura cuando se use el contain: size Por sí sola, la contención de tamaño no creará un nuevo contexto de formato y, por lo tanto, no contiene flotadores ni márgenes como lo hará la contención de diseño y pintura. Es menos probable que lo use solo; en cambio, lo más probable es que lo aplique junto con otros valores de contain para poder obtener la mayor contención posible.

Valores abreviados

En la mayoría de los casos, puede utilizar uno de los dos valores abreviados para sacar el máximo partido de la contención. Para activar el diseño y la contención de pintura, utilice contain: content; , y para activar toda la contención posible (teniendo en cuenta que los elementos que no tienen un tamaño se colapsarán), use contain: strict .

La especificación dice:

contain: content es razonablemente "seguro" para aplicarse ampliamente; sus efectos son bastante menores en la práctica, y la mayoría del contenido no entrará en conflicto con sus restricciones. Sin embargo, debido a que no aplica la contención de tamaño, el elemento aún puede responder al tamaño de su contenido, lo que puede provocar que la invalidación del diseño se filtre más arriba de lo deseado en el árbol. Use contain: strict cuando sea posible, para obtener la mayor contención posible”.

Por lo tanto, si no conoce el tamaño de los elementos de antemano y comprende el hecho de que se contendrán los espacios flotantes y los márgenes, utilice la función de contain: content . Si conoce el tamaño de los elementos además de estar contento con los otros efectos secundarios de la contención, use contain: strict . El resto depende del navegador, has puesto tu granito de arena explicando cómo funciona tu diseño.

¿Puedo usar la contención ahora?

La especificación de contención CSS ahora es una recomendación W3C, que es a lo que a veces nos referimos como un estándar web . Para que la especificación llegara a esta etapa, era necesario que hubiera dos implementaciones de la característica que podemos ver tanto en Firefox como en Chrome:

Captura de pantalla de la información de soporte del navegador sobre Contención en ¿Puedo usar?
Soporte de navegador para contención (Fuente: Can I Use)

Como esta propiedad es transparente para el usuario, es completamente seguro agregarla a cualquier sitio, incluso si tiene muchos visitantes en navegadores que no la admiten. Si el navegador no es compatible con la contención, el visitante obtiene la experiencia que suele obtener, los navegadores compatibles obtienen un rendimiento mejorado.

Sugeriría que esto es una gran cosa para agregar a cualquier componente que cree en una biblioteca de componentes o patrones, si está trabajando de esta manera, es probable que cada componente esté diseñado para ser algo independiente que no afecta a otros elementos en el página, haciendo que el contain: content una adición útil.

Por lo tanto, si tiene una página que está agregando contenido al DOM después de la carga, le recomendaría que lo pruebe. Si obtiene algún resultado interesante, ¡hágamelo saber en los comentarios!

Recursos Relacionados

Los siguientes recursos le brindarán más detalles sobre la implementación de la contención y los posibles beneficios de rendimiento:

  • "La propiedad de contain CSS", documentos web de MDN
  • "Contención de CSS en Chrome 52", Google Developers
  • “Módulo de contención CSS nivel 1”, recomendación del W3C
  • “Introducción a la Contención CSS”, Manuel Rego Casasnovas