Categorías: Labs

Técnicas de desarrollo con CSS

Esta es una traducción del artículo original publicado en el blog de Mozilla Hacks. Traducción por Jose Enrique Bolaños.

Últimamente, hemos visto a muchas personas sufriendo con CSS, desde principiantes hasta desarrolladores experimentados. A algunos no les gusta la forma en que funciona, y se preguntan si sería mejor reemplazar CSS con un lenguaje distinto — los preprocesadores CSS emergieron de esta manera de pensar. Algunos usan frameworks de CSS con la esperanza de tener que escribir menos código (hemos visto en un artículo previo por qué usualmente éste no es el caso). Algunos han comenzado a descartar CSS del todo y a utilizar JavaScript para aplicar estilos.

Pero no siempre es necesario que incluyas un preprocesador CSS en tu línea de trabajo. No necesitas incluir un framework inflado como el punto de entrada por defecto de cualquier proyecto. Y usar JavaScript para hacer las cosas para las que CSS fue creado es una pésima idea.

En este artículo, veremos algunas recomendaciones para escribir código CSS que es mejor y más fácil de mantener, de modo que tus hojas de estilo sean más cortas y tengan menos reglas. CSS puede sentirse como una herramienta útil en vez de una tortura.

El “selector viable mínimo”

CSS es un lenguaje declarativo, en el cual tu especificas reglas que le darán estilo a elementos del DOM. En este lenguaje, algunas reglas tienen prioridad sobre otras en el orden en el que se aplican; estilos en-línea (inline) sobrescriben algunas reglas previas.

Por ejemplo, si tenemos este código HTML y CSS:

<button class="button-warning"></button>
.button-warning {
  background: red;
}
 
button, input[type=submit] {
  background: gray;
}

Aunque la regla de .button-warning está definida antes de la de button, input[type=submit], aquella va a sobrescribir la propiedad background de ésta. ¿Por qué? ¿Cuál es el criterio que decide cuál regla sobrescribe los estilos de otra?

Especificidad.

A algunos selectores se les considera como más específicos que otros. Por ejemplo, un selector #id sobrescribirá a un selector .class.

¿Qué ocurre cuando usamos un selector que es más específico de lo que necesita ser? Si después queremos sobrescribir esos estilos, necesitaremos un selector aún más específico. Y si a su vez después necesitamos sobrescribir este selector más específico, necesitaremos… sí, es una bola de nieve cada vez más grande, que eventualmente es más difícil de mantener.

Entonces, cuando estás escribiendo tus selectores, pregúntate: ¿es éste el selector menos específico que puedo usar?

Todas las reglas de especificidad están oficialmente definidas en la especificación de selectores CSS de W3C, la cual es la forma de averiguar cada detalle sobre selectores CSS. Para algo más fácil de comprender, lee este artículo sobre especificidad de CSS.

No le arrojes reglas nuevas a los errores

Imaginemos una situación típica: hay un error en tu CSS y logras encontrar el elemento DOM que tiene el estilo incorrecto. Te das cuenta de que por alguna razón está heredando una propiedad que no debería.

No le arrojes más CSS. Si lo haces, tu código crecerá un poco más, y encontrar futuros errores será más difícil.

En vez de eso, detente, da un paso hacia atrás, y utiliza las herramientas de desarrollo de tu navegador para inspeccionar el elemento y ver la cascada completa. Identifica exactamente cuál regla está aplicando el estilo que no quieres, y modifícala para que no tenga ese efecto no intencional.

En Firefox puedes depurar la cascada haciendo click derecho sobre un elemento de una página y seleccionando Inspeccionar Elemento.

Inspección de elemento

Mira esa cascada en toda su gloria. Aquí puedes ver todas las reglas que se aplican a un elemento, en el orden en que fueron aplicadas. Las primeras entradas son las que tienen mayor especificidad y pueden sobrescribir estilos anteriores. Puedes ver que algunas reglas tienen algunas propiedades tachadas: eso significa que una regla más específica está sobrescribiendo a esa propiedad.

Y no sólo puedes ver las reglas, sino que también puedes activar o desactivarlas, o cambiarlas sobre la marcha y observar los resultados. ¡Es muy útil para corregir errores!

La corrección requerida puede ser un cambio de la regla o puede ser un cambio de la regla en otro punto de la cascada. O la corrección podría requerir una nueva regla. Al menos sabrás que fue la decisión correcta y que era algo que tu base de código necesitaba.

Este también es un buen momento para buscar oportunidades de refactorización. Aunque CSS no es un lenguaje de programación, sí es código fuente y deberías darle la misma consideración que a tu código JavaScript o Python: debe ser limpio, legible, y debe ser refactorizado cuando sea necesario.

No le agregues !important a las cosas

Esto está implícito en las recomendaciones anteriores, pero ya que es crucial quisiera enfatizarlo: No uses !important en tu código.

!important es una funcionalidad en CSS que te permite romper la cascada. CSS significa “hojas de estilo en cascada”: ésta es una pista.

!important es utilizado frecuentemente cuando te apuras a corregir un error y no tienes el tiempo o las ganas de corregir tu cascada. También es muy utilizado cuando estás incluyendo un framework CSS con reglas muy específicas y simplemente es muy difícil sobrescribirlas.

Cuando agregas !important a una propiedad, el navegador ignorará otras reglas con mayor especificidad. Sabrás que estás realmente en aprietos cuando agregas !important a una regla para sobrescribir otra regla que a su vez ha sido marcada como !important.

Hay un uso legítimo de !important, y es cuando estás usando las herramientas de desarrollo para depurar algo. A veces necesitas encontrar cuáles valores de una propiedad arreglarán tu error. Utilizando !important en las herramientas de desarrollo y modificando tu regla CSS sobre la marcha te permite encontrar estos valores mientras ignoras la cascada.

Una vez que sabes cuáles partes de CSS funcionarán, puedes regresar a tu código y buscar en cuál punto de la cascada quieres incluir estas partes de CSS.

Existe vida más allá de de px y %

Trabajar con unidades de px (pixeles) y % (porcentajes) es bastante intuitivo, así que nos enfocaremos con unidades menos conocidas o menos intuitivas.

Em y rem

La unidad relativa mejor conocida es em. 1em es equivalente al tamaño de la fuente de ese elemento.

Imaginemos el siguiente bloque de HTML:

<article>
  <h1>Title</h1>
  <p>One Ring to bring them all and in the darkness bind the.</p>
</article>

Y una hoja de estilo con sólo esta regla:

article {
  font-size: 1.25em;
}

Por defecto la mayoría de los navegadores aplican un tamaño de fuente base de 16 píxeles al elemento raíz (lo cual, por cierto, puede ser sobrescrito por el usuario — una buena opción de accesibilidad). Así que el texto de párrafo de este elemento article probablemente tendrá un font-size de 20 pixeles (16 * 1.25).

¿Qué hay sobre el h1? Para entender mejor qué sucederá, agreguemos esta otra regla CSS a nuestra hoja de estilo:

h1 {
  font-size: 1.25em;
}

Aunque también es 1.25em, igual que article, tenemos que tener en cuenta que las unidades em son compuestas. Esto significa que un h1 que sea descendiente directo de un body tendría un tamaño de fuente de 20 pixeles (16 * 1.25). Sin embargo, nuestro h1 está dentro de un elemento que tiene un font-size distinto al de la raíz (nuestro article). En este caso, el 1.25 se refiere al font-size que dicta nuestra cascada, así que el h1 será dibujado con un font-size de 25 pixeles (16 * 1.25 * 1.25).

Por cierto, en vez de tener que hacer todas estas multiplicaciones en tu cabeza, puedes simplemente usar la pestaña Computado del Inspector, la cual despliega el valor final en píxeles:

Valor computado

Las unidades em son realmente versátiles y hacen que sea muy fácil cambiar — incluso dinámicamente — todos los tamaños de una página (no sólo font-size, sino también propiedades como line-height, o width).

Si te gusta la parte “relativa al tamaño base” de em pero no te gusta su aspecto compuesto, puedes usar unidades rem. Son iguales que las unidades em, pero ignoran ese efecto de composición y siempre utilizan el tamaño del elemento raíz como referencia.

Entonces, si tomamos nuestro CSS anterior y cambiamos las unidades em por rem en el h1:

article { font-size: 1.25em; }
h1 { font-size: 1.25rem; }

Todos los elementos h1 tendrían un font-size computado de 20 pixeles (asumiendo un tamaño base de 16px), sin importar si están dentro de un elemento article o no.

vw and vh

vw y vh son unidades de ventana (viewport). 1vw significa 1% del ancho de la ventana, mientras que 1vh es 1% del alto de la ventana.

Son increíblemente útiles cuando necesitas un elemento de interfaz que ocupe toda la pantalla (como el típico fondo semi-transparente de los diálogos modales), el cual no siempre está relacionado al tamaño del documento.

Otras unidades

Existen otras unidades que pueden no ser tan comunes o versátiles, pero que inevitablemente te vas a encontrar. Puedes aprender más sobre ellas en el MDN.

Usa flexbox

Hemos hablado al respecto en un artículo previo sobre frameworks CSS, pero el módulo flexbox simplifica la tarea de distribuir elementos y alinear cosas. Si eres nuevo a flexbox, revisa esta guía introductoria.

Y , puedes usar flexbox hoy; a menos que realmente quieras mantener compatibilidad con navegadores antiguos por razones de negocio. El soporte actual en los navegadores para flexbox es de más de 94%. Así que puedes dejar de escribir todos esos div flotantes que son difíciles de mantener y depurar.

También, mantente al tanto del módulo Grid que se avecina, el cuál hará que implementar diseños sea súper sencillo.

Cuando usas un procesador CSS…

Compiladores CSS como Sass o Less son muy populares en el mundo de desarrollo front-end. Son herramientas poderosas, y — cuando se usan bien — nos permiten trabajar más eficientemente con CSS.

No abuses de anidamiento de selectores

Una funcionalidad común en estos preprocesadores o “compiladores” es anidamiento de selectores. Por ejemplo, este código Less:

a {
  text-decoration: none;
  color: blue;
 
  &amp;.important {
    font-weight: bold;
  }
}

Sería traducido a las siguientes reglas CSS:

a {
  text-decoration: none;
  color: blue;
}
 
a.important {
  font-weight: bold;
}

Esta opción nos permite escribir menos código y agrupar reglas que afectan a elementos que usualmente están juntos en el árbol DOM. Es también útil para depurar errores.

Sin embargo, también es común abusar de esta funcionalidad y terminar duplicando el DOM completo en los selectores CSS. Por ejemplo, si tenemos el siguiente HTML:

<article class="post">
  <header>
    <!-- … -->
    <p>Tags: <a href="..." class="tag">irrelevant</a></p>
  </header>
  <!-- … -->
</article>

Puede que encontremos esto en la hoja de estilo CSS:

article.post {
  // ... otros estilos aquí
  header {
    // ...
    p {
      // ...
      a.tag {
        background: #ff0;
      }
    }
  }
}

La desventaja principal es que estas reglas CSS tienen selectores extremadamente específicos. Ya hemos visto que esto es algo que debemos evitar. Existen otras desventajas, las cuales hemos discutido en otro artículo.

En resumen: no permitas que el anidamiento genere reglas CSS que no escribirías tu mismo.

Include vs extend

Otra funcionalidad útil de los preprocesadores CSS son mixins, los cuales son pedazos reutilizables de CSS. Por ejemplo, digamos que queremos darle estilo a botones, y la mayoría tienen propiedades básicas de CSS. Podríamos crear un mixin en Less como éste:

.button-base() {
  padding: 1em;
  border: 0;
}

Y luego creamos una regla como ésta:

.button-primary {
  .button-base();
  background: blue;
}

Esto generaría el siguiente código CSS:

.button-primary {
  padding: 1em;
  border: 0;
  background: blue;
}

Como puedes ver, ¡es muy útil para refactorizar código común!

Además de “incluir” un mixin, también existe la opción de “extender” o “heredar” del mismo (la terminología exacta difiere de herramienta a herramienta). Lo que hace esto es combinar múltiples selectores bajo la misma regla.

Veamos un ejemplo usando el mixin .button-base que describimos anteriormente:

.button-primary {
  &amp;:extend(.button-base)
  background: blue;
}
 
.button-danger {
  &amp;:extend(.button-base)
  background: red;
}

Eso se traduciría a lo siguiente:

.button-primary, .button-danger {
  padding: 1em;
  border: 0;
}
 
.button-primary { background: blue; }
.button-danger { background: red; }

Algunos artículos en línea nos dicen que sólo usemos “include”, mientras que otros nos dicen que sólo usemos “extend”. El hecho es que producen CSS distinto, ninguno inherentemente incorrecto, y dependiendo de tu escenario real sería mejor utilizar uno u otro.

¿Cuál escoger? De nuevo, aquí aplica la regla de “¿escribiría yo esto a mano?”.

———–

Espero que este artículo te ayude a reflexionar sobre tu código CSS y te haga escribir mejores reglas. Recuerda lo que dijimos antes: CSS es código, y como tal merece el mismo nivel de atención y cuidado como el resto de tu código. Si le das cuidado, cosecharás las recompensas.

The following two tabs change content below.

jorgev

Add-ons Developer Relations Lead at Mozilla
Jorge trabaja para el equipo de complementos de Mozilla, y se dedica a Mozilla Hispano y Mozilla Costa Rica en su tiempo libre. Actualmente está encargado del blog de Mozilla Hispano Labs.