Incidencia del tipo de selector Css en el rendimiento de la web 8.9.16
¿Hay diferencias en el rendimiento de una web por la forma de los selectores Css usados? ¿Le lleva más tiempo al navegador hallar la concordancia entre la regla Css y el elemento Html según qué tipo de selector se use?
Incidencia del tipo de selector Css en el rendimiento de la web
Este artículo es completamente ajeno a temas relacionados con la semántica o metodología al asignar nombres a los atributos (i.e.: class o id) o de estructurar las reglas en el archivo Css.
Sólo me centro en el aspecto del trabajo invertido por el navegador en buscar la concordancia y emparejar las reglas Css con el elemento html en función de los tipos de selectores usados en su conformación. Y si este aspecto es relevante y debe ser tenido en cuenta.
El debate sobre la incidencia que tiene el tipo de selector Css según su construcción sobre el rendimiento y composición de la página por el sobrecoste que puede suponer para el navegador asociar cada regla Css al elemento html indicado, pese a venir de largo, no está cerrado ni mucho menos.
Es la cuestión que muchos llaman de la eficiencia del tipo de selector Css
: el tiempo que emplea el navegador en buscar la concordancia entre un elemento del Html y las reglas Css que le pudieran ser de aplicación.
Desde este punto de vista cuanto más tiempo emplee menos eficiente sería el selector y tendría un impacto negativo en el rendimiento de la página.
Este parámetro hay quien lo tiene en cuenta a la hora de evaluar el rendimiento y lo incluye entre los optimizables.
Especialmente relevante a la hora de evaluar la posible incidencia del tipo de selector usado es la forma en que cada navegador, al construir el árbol de elementos (DOM), busca las concordancias en las hojas de estilo para aplicar el Css. Forma que está íntimamente relacionada con las capacidades del navegador (programación) y capacidades de la máquina en la que corre.
Como es lógico, los recursos del agente de usuario y la potencia de los aparatos implicados en la tarea de componer la página conforme a los elementos que contiene y los lenguajes que le afectan (como el CSS y el js) han ido cambiando, para bien, con el transcurso del tiempo y las sucesivas versiones.
Así, mucha de la literatura que se puede encontrar sobre este aspecto ha quedado obsoleta con el paso del tiempo. Hecho que no quita que aún permanezcan en el imaginario colectivo y se repitan a menudo como "mantras" que han devenido con el paso del tiempo en "leyendas urbanas".
Tradicionalmente [artículo del año 2000] se clasificaban las reglas Css por la composición de su selector y su incidencia en la carga de la página en cuatro grupos. Clasificación que traigo aquí sólo como curiosidad:
- Reglas ID: #mi_id {}
- Reclas de clase: .mi_clase {}
- Reglas de etiqueta: header, p, div {}
- Reglas universales
En las reglas universales se incluyen las que utilizan selectores por valor de atributo, pesudoclases y combinadores Css, siendo las que portan el sambenito de costosas
: ralentizan el emparejamiento regla Css con elemento Html. Y en el extremo opuesto, más eficientes, se colocan las de identificador único.
Super-velocidad, Cero practicidad
Sabemos que los ID´s son los selectores más eficientes. Si querías hacer la página más eficiente posible, literalmente da a cada elemento de la página de un identificador único, a continuación, aplica un estilo con selectores de ID.
Eso la haría muy rápida, y también súper ridícula.
Tiempos nuevos, tiempos modernos
Ya hace tiempo que los motores de Css de los principales navegadores se optimizaron en este aspecto. Y lo han seguido haciendo. Así, han implementado mejoras para abortar el seguir buscando coincidencias entre un elemento en concreto y las reglas Css que podrían afectarle.
Estas mejoras evitan la recursividad y los loops innecesarios, mejorando los tiempos de composición de la página mucho más que cualquier actuación referida a la composición del nombre del selector Css.
Allá en Diciembre de 2011 Nicole Sullivan [aka @stubbornella] publicó el que creo uno de los mejores artículos al respecto: CSS Selector Performance has changed! (For the better).
De este post traigo esta cita. Opinión de Antti Koivisto [aka @anttikoivisto] que se describe a sí mismo como Making WebKit suck less since 1999
:
Mi opinión es que los autores no deberían tener que preocuparse sobre la optimización de los selectores Css (y por lo que veo, por lo general no lo hacen), eso debe ser trabajo del agente de usuario.
No obstante lo anterior, es cierto que hay unos selectores Css que, por la composición de su nombre, son más costosos que otros. Entre estos últimos cabe destacar aquellos que en su construcción incluyen combinadores de hermanos, de pseudoclases o por valor de atributo. Especialmente cuando se combinan varios de ellos en el mismo selector.
Pero es algo que tampoco es muy relevante, de acuerdo nuevamente con Antti Koivisto:
Usados con moderación [esos selectores] el navegador realizará muy bien su trabajo desde la perspectiva de asignar los estilos.
Abundando en este punto, el de los selectores algo más costoso como los que utilizan pseudoclases concatenadas, y a raíz del artículo de Heydon Pickering en Alist Apart Quantity Queries for CSS
donde su autor construye selectores como los siguiente:
li:nth-last-child(6):first-child { } last-child(6):first-child ~ li {}
Un peso pesado en estos temas como Paul Irish se manifiesta:
Ok. Habrá que estar al loro
con este tipo de selectores Css que podrían penalizar la composición de la página... en algunas circunstancias muy concretas y no tan usuales.
Tiempos, tiempos, pero ¿cuánto tiempo?
En todo momento, al plantearse la relación entre del nombre del selector y su incidencia en la composición de la página por el navegador, todo se reduce a una cuestión de tiempos: tiempos a mayores que debe emplear usando un tipo u otro.
Y eso, el tiempo, es mensurable. Son muchos los artículos y pruebas realizadas al respecto. Una de tantas es la realizada por Ben Frain para su artículo publicado ahora hace un año [Febrero 2014] CSS performance revisited: selectors, bloat and expensive styles
. También disponible en github.
Selector lento, selector veloz
Para la evaluación construye una web con el siguiente bloque de elementos Html repetido 1000 (mil) veces:
<div class="tagDiv wrap1">
<div class="tagDiv layer1" data-div="layer1">
<div class="tagDiv layer2">
<ul class="tagUl">
<li class="tagLi">
<b class="tagB">
<a href="/" class="tagA link" data-select="link">Select</a>
</b>
</li>
</ul>
</div>
</div>
</div>
Tras la batería de pruebas y evaluaciones, este es el dato final en cuanto a diferencias de tiempo se refiere, en sus propias palabras:
Of the desktop browsers, IE9 stands out as having the biggest difference between fastest and slowest selectors at 31ms. The others are all around half of that figure. However, interestingly there was no consensus on what the slowest selector was.
31 milisegundos de diferencia en la composición de una página con 1000 (sí, mil) bloques de código. Sí, esa es la mayor diferencia entre usar un tipo u otro de selectores Css. Pero tanto o más clarificador que el dato en sí, las valoraciones sobre el particular que incluye en su artículo. Palabras de Benjamin Poulain, ingeniero en Webkit:
By choosing to measure performance through the loading, you are measuring plenty of much much bigger things than CSS, CSS Performance is only a small part of loading a page.
Volvemos a encontrarnos con que la misma conclusión: la posible penalización en la formación de la página por el uso de un tipo de selector Css u otro no es significativa. Infinitamente menos relevante que otros aspectos que sí deben ser considerados.
Para finalizar
Estamos en 2015. Los navegadores han hecho un gran trabajo en sus motores de interpretación de lenguajes. Dejando aparte construcciones de nombres de selectores #madredelamor .hermoso .pero #eso * .qué #es {}
por absurdas e ilógicas este punto debería ser secundario en la realización del Css.
Hay aspectos en las hojas de estilo que sí deben ser tenidos en cuenta para optimizar el Css. Y todos están no fuera de las llaves sino dentro, en el bloque de declaraciones.
Antaño eran unas declaraciones. El uso de b-position: fixed
con según qué tipo y tamaños de imágenes no siempre le sentaba bien al navegador, al hacer scroll protestaba. Hoy son otras las que merecen ser observadas y usadas con cuidado.
Las grandes sombras, recortes en las esquinas (border-radius
), opacidades y especialmente las transformaciones y animaciones Css (2D y 3D) junto a los "recién" llegados filtros y modos de fusión Css le suponen un gran trabajo al navegador y la máquina usados sin cuidado. Tanto en la composición como el manejo de la página.
Y junto a ello, el Css no usado. Ya sea porque se cargan todos los estilos en un gran archivo Css para todas las páginas (se use un módulo concreto o no) o porque haya declaraciones que no se usan en ninguna parte y no fueron limpiadas.
Especial atención también al uso de preprocesadores y el Css final generado. En ocasiones más del que realmente es necesario.
Post Data
Un aspecto que sí debería preocuparte al asignar el valor del atributo class
es cuál eliges, pero por razones ajenas a Css, su optimización y el pretendido carácter semántico del nombre de los selectores Css.
El motivo es mucho más prosaico. Tiene que ver con el uso de bloqueadores de publicidad y su lógica de nombre de elemento -> contenido
. Mira este pen con ABPlus o similares activado y desactivado.
Esto sí que es incidencia del nombre del selector (realmente el valor del atributo class) en la composición de la página.
Lecturas relacionadas
- CSS Selector Performance has changed! (For the better)
- CSS performance revisited: selectors, bloat and expensive styles
- El selector Css. Guía a fondo
- Selectores eficientes: la ley MsN o del "Mínimo Selector Necesario"
- Aclarando la cuestión de si "los ids y class pueden comenzar por un número"
- Nombres de Clases por su apariencia. ¡No son semánticas?
Kseso
the obCSServer ᛯ Ramajero Argonauta, Enredique Amanuense de CSS.#impoCSSible inside
Dicen que, en español, EsCss es el mejor blog de CSS. Posíblemente exageren.
@Kseso EsCss Kseso
Yo en un principio, utilizaba muchas reglas especificas en el momento que supe que existían, me funcionaba sí pero en determinados casos, cuando eran muchos y me refiero a cuando empezó apenas el boom del css3 lo hacia en casi todos los elementos casi así:
ResponderEliminar.page /*---body---*/ article:nth-child(3) p:nth-child(2) a:first-child
Casi que nunca usando clases.
Lo malo es que al no llevar una estándar de nominación y no documentar bien, cuando trabajaba con otros ingenieros el mantenimiento a largo plazo y con varios proyectos se volvía inmanejable estos selectores, sobre todo en la herencia, así que se acordó (en aquel momento) no usarlos sino en determinados casos y solo con ciertos elementos como lo Li, así como no más de 2 selectores de clase anidados: .padre .hijo con contadas excepciones. Agrupar clases generales y usar multiclases. class="bloque1 fondo-principal font3" y cosas así. Así como ordenarlas no alfabeticamente sino por categorías:
1) universales
2) generales > 2.1) Imágenes de fondo, 2.2) Colores de fondo 2.3) Color de letra, 2.4) Tipografías, ect
3) Estruturales > 3.1) Head, 3.2) Menu, 3.4) Cuerpo, 3.5) Sections, 3.6) p, etc
4) Elementos > 4.1) btn-submit-form 4.2) Checked-tipo1 4.3) Btn-Enlace 4.4) Enlace-Contextual, etc
5) Paginas > 5.1) home-enlace 5.2) asignacion-vista2-enlace 5.3) reporte-vista4-parrafo-tipo1 5.
6) Especificos > 6.2) Imagen-2col-full 6.3) Parrafo-Resaltar-Tipo1
O bueno algo, así, hoy día, trabajo más en otros proyectos con campañs mailing y una que otra landing, más relacionado al mercadeo que al desarrollo, y es muy diferente de cuando estaba en la IO, además este orden sí bien lo cuadrabamos en equipo, más que nada era con un lider de proyecto para nada sabia de diseño o css (bueno lo básico para ser lider de proyectos), yo era el único diseñador y el resto eran backends, por lo cual yo tuve (felizmente encantado) que aprender a maquetar y ser el único front-end designado, sin ninguna que otra experiencia en una que otra web personal de un conocido. Ah y nunca se maqueto websites (uno que otro home, o landings) sino más que nada aplicativos web, tipo CRM. Por lo que nunca se reparo sí este orden afectaba o no, la velocidad de render de la página como tal y casi siempre se culpaba a javascript y no a css cuando esto pasaba.
He desvariado un poco (quizas con casi relacion al articulo), pero es un tema que mas de una vez me ha llamado la atención y escuchando un webinar de wakko oi de algo sobre nominarlos usando un estándar que empieza por "O" (no recuerdo cual) e identarlos como sí usaras un preprocesador tipo SASS. Siempre pensé que era por el workflow en equipo pero desconocía totalmente que puede ser por primar la velocidad de carga.
En fin, excelente información como siempre. Éxitos.
Ese es un selector tipo "#madredelamor .hermoso pero eso * qué es {}" y sólo en muy contadas y excepcionales circunstancias tendría razón de ser tan específico.
ResponderEliminarEl artículo es completamente ajeno a temas relacionados con la metodología de asignar nombres a los atributos class o id o de estructurar las reglas en el archivo Css.
Sólo me centro en el aspecto del tiempo invertido por el navegador en buscar la concordancia y emparejar los estilos Css que le correspondan al elemento en función del tipo de selector que sea. Y si este aspecto es relevante y debe ser tenido en cuenta.
Dicho con un ejemplo: qué selector de los siguientes, aplicados al mismo elemento, es más o menos costoso:
[code]
a { }
#id { }
.clase { }
[href] { }
...
[/code]
Un saludo