style - Diferencia de rendimiento entre los estilos en línea creados con JavaScript y las hojas de estilo creadas con JavaScript
modificar estilo css con js (3)
Pros y contras de los estilos en línea
Ha habido mucho debate sobre este tema en los últimos dos años desde que React y JSX han ganado una enorme popularidad.
He probado algunas soluciones, así que las enumeraré aquí. Primero una discusión general ..
CSS es básicamente el único lenguaje que aboga por el uso de un espacio de nombres global, y esta es la razón número 1 por la que las personas se están alejando de los CSS directos y los marcos generales pesados. Con flexbox, los diseños de respuesta se pueden hacer en varias líneas de códigos en lugar de un sistema de cuadrícula completo como el que obtendría con algo como bootstrap.
CSS resolvió el problema de proporcionar estilos a los documentos de una manera reutilizable, pero a medida que las aplicaciones se hacían más grandes y más complejas, y se incluían más bibliotecas de terceros con su propio CSS, la posibilidad de colisiones globales de espacio de nombres era casi inevitable. Tanto es así que se crearon y defendieron algunos patrones diferentes, como BEM y SMACSS.
La reacción surgió, lo que hizo que la administración y la creación de estilos en línea reutilizables fueran relativamente sencillos. Podrías usar todo javascript, lo que significaba que podrías anular los estilos usando cosas como _.extend
o Object.assign
. Esto hizo que fuera fácil compartir módulos y paquetes que incluían componentes y sus estilos, y tenía la ventaja de no requerir ningún tipo de cargador de estilo, como lo que se requiere al usar el webpack
. Aunque no todo eran rosas. Cosas como :hover
, otros psuedo-selectores y consultas de medios no son compatibles con los estilos en línea.
Para sortear estas limitaciones, los desarrolladores implementaron eventos para desencadenar cambios de estilo, como onmouseover
for hover, y enganchando en la ventana los eventos de cambio de tamaño para consultas de medios. Poco después, se creó una biblioteca para estandarizar estos eventos js, y definir una API similar a CSS, que ganó popularidad, llamada Radium
. En la naturaleza, Radium tampoco era justo (créeme, lo intenté). En aplicaciones grandes, ninguna de las consultas de medios se pudo ejecutar hasta que todos los JS se descargaron, ¡lo cual no recomiendo!
Eso llevó a la creación de algunas herramientas nuevas que adoptan un enfoque diferente. Estas nuevas generaciones de herramientas usan estilos definidos en JS, pero generan CSS. Esto le da el poder completo de los estilos en línea y el poder completo de CSS. Lo mejor de ambos mundos. La mejor biblioteca probablemente depende de su caso de uso, pero esos consisten en Fela.js, Afrodita y JSS.
Mi solución favorita es Fela.js. Compruébelo en fela.js.org. Fela es probablemente el mejor rendimiento que obtendrás, y no es específico de ningún marco en particular. Dicho esto, funciona bien con React y React Native. Tiene un par de características interesantes, como permitirte acceder a accesorios de tus estilos. Se configura un renderer
en el encabezado de la página. Fela funciona mejor con SSR, pero también funciona puramente del lado del cliente según sus necesidades. Cuando se utiliza con SSR, puede obtener cargas de páginas increíblemente rápidas porque Fela optimiza los estilos que ha escrito en las clases de css atómicas, y se envían de vuelta al cliente en la solicitud inicial.
Estas herramientas son increíbles si le preocupa obtener la página más rápida posible. Puede realizar fácilmente patrones difíciles, como la optimización de la ruta css crítica, donde los estilos necesarios se devuelven como parte de la solicitud HTTP inicial, en lugar de un enlace a una hoja externa que también debe descargarse.
Por último, tengo que mencionar los módulos CSS. Estos crean una hoja de estilo externa, pero le permiten tener un CSS con espacio de nombre por módulo. Esto le permite escribir CSS real o SASS o etc, pero viene con una sobrecarga de configuración adicional. En el paquete web, por ejemplo, necesitarías usar una combinación de cargadores de estilo falso y herramientas de extracción de texto para crear el archivo .css.
Quiero diseñar dinámicamente todos los elementos de un selector determinado en mi DOM. Veo más o menos dos maneras al respecto. Para el ejemplo a continuación, usaré un elemento p
y su atributo de text-align
de text-align
pero estoy más interesado en los pros y los contras de las dos formas posibles de hacerlo que en los párrafos específicamente de alineación de texto.
1. Estilos en línea (por elemento)
var nodes = document.getElementsByTagName(''p'');
Array.prototype.forEach.call (nodes, function (node) {
node.style.textAlign = "center";
});
2. Hoja de estilo
var sheet = (function() {
// Create the <style> tag
var style = document.createElement("style");
// WebKit hack :(
style.appendChild(document.createTextNode(""));
// Add the <style> element to the page
document.head.appendChild(style);
return style.sheet;
})();
sheet.insertRule("p { text-align: center; }");
Por lo general, seguiría la ruta de los estilos en línea, ya que parece más simple y asegura que el cambio de estilo anularía las hojas de estilo existentes. Pero se me ocurre que para uno: a veces no es preferible anular las hojas de estilo, y para dos: podría ser más eficaz modificar un elemento de style
que una cantidad desconocida de elementos p
. Pero eso es solo mi suposición.
En cuanto al rendimiento, ¿habría alguna vez una situación en la que aplicar estilos en línea a cada elemento individual fuera mejor que crear una hoja de estilo? Suponiendo que la respuesta podría depender de la cantidad de elementos a los que estoy diseñando, ¿en algún momento la creación de una hoja de estilo se vuelve más eficiente?
EDITAR: Para aclarar por qué estoy haciendo la pregunta, explicaré un poco sobre por qué lo hago: recientemente he convertido un puñado de hacks JS que a menudo copié y pegué entre proyectos en un conjunto de Módulos reutilizables de CommonJS. Hacen cosas como configurar todos los elementos de un selector dado con el mismo alto o ancho que el más alto o el más ancho del conjunto en situaciones donde la medida del más alto o más ancho podría estar sujeta a cambios en el cambio de tamaño de una ventana u otros disparadores.
Aquí hay una publicación del blog al respecto: http://davejtoews.com/blog/post/javascript-layout-hacks
Aquí están los repositorios de GitHub para los módulos:
En este punto, todos estos módulos utilizan estilos en línea, pero estoy pensando en cambiarlos a hojas de estilo. No pude encontrar una buena respuesta sobre los pros y los contras de cualquiera de los enfoques, así que publiqué la pregunta aquí.
No tengo una buena respuesta general a tu pregunta (y no estoy seguro de que haya una), pero he realizado algunos experimentos con el ejemplo que publicaste en Chrome 57.0.2987.98 beta, utilizando la línea de tiempo de las herramientas dev.
Aquí hay un desglose del trabajo realizado en el marco único que actualiza 10,000 elementos <p>
con estilos en línea (izquierda) y una hoja de estilo dinámica (derecha):
Para comparar, aquí están los resultados para la misma prueba con 100 elementos <p>
:
En resumen, para una pequeña cantidad de elementos, la diferencia es despreciable. Para un gran número de elementos, cuando se usan estilos en línea, el navegador dedica más tiempo a las secuencias de comandos (lo que es de esperar, ya que hay un gran bucle) y a volver a calcular los estilos (creo que esto se puede explicar porque el navegador tiene que analizar un estilo regla por elemento en lugar de una sola regla de estilo común).
Todos los demás pasos toman aproximadamente la misma cantidad de tiempo. En particular, el tiempo de pintura no aumenta cuando se usan estilos en línea.
Para referencia, había utilizado la siguiente página de prueba.
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<button id="add-stylesheet">Stylesheet</button>
<button id="add-inline-styles">Inline</button>
<script type="text/javascript">
let stylesheet = document.getElementById(''add-stylesheet'');
let inline = document.getElementById(''add-inline-styles'');
stylesheet.addEventListener(''click'', addStylesheet);
inline.addEventListener(''click'', addInlineStyles);
function addStylesheet() {
let style = document.createElement("style");
style.appendChild(document.createTextNode(""));
document.head.appendChild(style);
style.sheet.insertRule(''p { text-align: center }'', 0);
}
function addInlineStyles() {
let nodes = document.getElementsByTagName(''p'');
for (let node of nodes) {
node.style.textAlign = ''center'';
}
}
// initialize <p> elements
init(10000);
function init(numElements) {
for (let i = 0; i < numElements; ++i) {
let p = document.createElement(''p'');
p.innerText = ''testing''
document.body.appendChild(p);
}
}
</script>
</html>
Todo depende del contexto de lo que está tratando de lograr. En mi empleador actual, terminé creando una pequeña biblioteca llamada stylo que se encarga de actualizar una hoja de estilos dinámica.
Cuando la cantidad de elementos que intenta actualizar es de miles, la actualización a través de estilos en línea será prohibitivamente costosa. La demostración en el enlace anterior actualiza 6.400 elementos en una fracción de segundo.
Sin embargo, si está actualizando solo un puñado de elementos, la actualización de la hoja de estilo podría desencadenar una nueva representación de la página, lo que no sería el caso si se actualizara un estilo en línea.