Buenas prácticas en CSS

por Nahuel Sotelo

Hola, soy Nahuel Sotelo

Frontend developer en Schibsted Spain y Profesor de la asignatura Programación Frontend en el Master de Diseño Web de Bau.

Contenidos

  1. Introducción
  2. Guía de estilos de código
  3. Arquitectura de carpetas
  4. Componentes modulares
  5. Especificidad
  6. Selectores
  7. Sistemas de Nomenclatura
  8. Conclusiones

Introducción

¿Por qué?

  • Trabajar en un equipo de varios developers.
  • Generar un código mantenible y escalable.
  • Reutilizar código.

¿Cómo?

  • Generando un código organizado, estructurado y bien documentado
  • Fragmentando el código en pequeños trozos (componentes/módulos/objetos) independientes
  • Separando los componentes de su contexto
  • Refactorizando continuamente

Enlaces relacionados

Guía de estilos de código

Una guía de estilos:

  • Genera un código más legible y fácil de mantener.
  • Disminuye la cantidad de errores.
  • Refuerza las buenas prácticas.
  • Permite trabajar en un mismo proyecto a desarrolladores de diferente nivel.

Ejemplos:

Existen herramientas que nos ayudarán a que todos los miembros del equipo sigan las pautas definidas.

Arquitectura de carpetas

Es recomendable centralizar los estilos en un ùnico fichero (main.css, style.css) que no contenga reglas, únicamente @import a otros ficheros.

Wallpaper by Julien He

Podemos encontrar varias arquitecturas en internet pero es importante conseguir una que se adapte a las necesidades de nuestro proyecto.

La clave está en tener claro la función de cada selector que utilicemos y ubicarlo en el archivo correspondiente.

Un ejemplo:
El patrón 7-1

7 carpetas, 1 archivo:


  sass/
  |
  |– base/
  |   |– _reset.scss
  |   |– _typography.scss
  |   ...
  |
  |– components/
  |   |– _buttons.scss
  |   |– _carousel.scss
  |   |– _cover.scss
  |   |– _dropdown.scss
  |   ...
  |
  |– layout/
  |   |– _navigation.scss
  |   |– _grid.scss
  |   |– _header.scss
  |   |– _footer.scss
  |   |– _sidebar.scss
  |   |– _forms.scss
  |   ...
  |
  |– pages/
  |   |– _home.scss
  |   |– _contact.scss
  |   ...
  |
  |– themes/
  |   |– _theme.scss
  |   |– _admin.scss
  |   ...
  |
  |– utils/
  |   |– _variables.scss
  |   |– _functions.scss
  |   |– _mixins.scss
  |   |– _helpers.scss
  |
  |– vendors/
  |   |– _bootstrap.scss
  |   |– _jquery-ui.scss
  |   ...
  |
  |
  `– main.scss
    
  • base/

    Es el punto de partida del proyecto (reset, tipografía, etc). Los selectores de esta carpeta tendrán una especificidad muy baja, probablemente la mayoría serán selectores de tipo.

  • layout/

    Todo aquello referente al layout de nuestro sitio: grid, header, footer, sidebar, etc. Aquellos componentes que se repiten página a página.

  • components/

    El core de nuestra web. Todos aquellos componentes reutilizables que utilizaremos a lo largo de nuestra web.

  • pages/

    Estilos específicos para una página en concreto.

  • themes/

    Si nuestro sitio tiene algun tipo de sistema de theming, podemos hacer uso de esta carpeta. En caso contrario puede omitirse.

  • utils/

    Variables, funciones, mixins o cualquier otro tipo de helper. Lo normal es que los contenidos de esta carpeta no se compilen en el fichero .css.

  • vendors/

    Estilos que no hemos creado nosotros: librerías como Bootstrap o estilos que acompañen algún plugin que estemos utilizando.


  @import 'utils/variables';
  @import 'utils/functions';
  @import 'utils/mixins';
  @import 'utils/placeholders';

  @import 'vendors/bootstrap';
  @import 'vendors/jquery-ui';

  @import 'base/reset';
  @import 'base/typography';

  @import 'layout/navigation';
  @import 'layout/grid';
  @import 'layout/header';
  @import 'layout/footer';
  @import 'layout/sidebar';
  @import 'layout/forms';

  @import 'components/buttons';
  @import 'components/carousel';
  @import 'components/cover';
  @import 'components/dropdown';

  @import 'pages/home';
  @import 'pages/contact';

  @import 'themes/theme';
  @import 'themes/admin';
    

Enlaces relacionados:

Componentes modulares

“It's a repeating visual pattern, that can be abstracted into an independent snippet of HTML, CSS and possibly JavaScript.”

Características de un componente:

  • Son un fragmento de la interfaz que cumple una única función.
  • Son independientes, tanto de su contexto como del resto de componentes.
  • Son reutilizables.
  • Son autocontenidos, no filtran estilos a otros componentes.

Enlaces relacionados:

Especificidad

En CSS, la especificidad, es lo que determina que estilo será el que acabará aplicandose a un elemento determinado.

Cuando a un elemento se le aplica más de un selector con reglas que actúan sobre la misma propiedad, es la especificidad la encargada de resolver este conflicto.

A grandes rasgos podemos ordenar los diferentes tipos de selectores de menor a mayor peso específico de la siguiente manera:

  1. Selectores de elemento
  2. Selectores contextuales
  3. Clases
  4. IDs

Calcular especificidad

0,0,0,0

p {
  color: red;
}

0,0,0,1

.text {
  color: red;
}

0,0,1,0

#main strong {
  color: red;
}

0,1,0,1

header ul#main-nav .sub-menu li.child a:hover {
  color: red;
}

0,1,3,4

<p style="color: red">Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>

1,0,0,0

p {
  color: red !important;
}

0,0,0,1 0,0,0,0

Enlaces relacionados:

Selectores

Carcterísticas de un buen selector

  • Tiene baja especificidad
  • Es sólido (no depende del contexto)
  • Es autodocumentado (su función se entiende solo con leerlo)

El gráfico de especificidad es una representación de cómo se distribuye la misma a lo largo de una hoja de estilo.

Es recomendable que la especificidad vaya aumentando gradualmente, empezando con estilos más genéricos (selectores de elemento) y acabando con casos más específicos.

Gráfico de especificidad

The Specificity Graph - Harry Roberts

Especificidad plana

Intentar mantener los selectores lo más cortos posibles (evitar nesting) nos ayudará a que nuestros componentes no estén atados a un contexto determinado y sean independientes del HTML.


  /* Cuidado! */
  #main-header nav ul > li .nav-link:first-child { ... }  /* 0, 1, 2, 3 */

  /* Mejor */
  .MainNav-link--first { ... }  /* 0, 0, 1, 0 */
    

Nomenclaturas

"What we want is to be able to write code that is as transparent and self-documenting as possible. Transparency means that it is clear and obvious (to others) in its intent; self-documenting means that we don’t have to lose time to writing and reading lengthy, supplementary documentation."
- Harry Roberts

Enlaces relacionados:

Sistemas de Nomenclatura

BEM
(block / element / modifier)

BEM Methodology


  .nombre-del-bloque { ... }

  .nombre-del-bloque__elemento { ... }

  .nombre-del-bloque--modificador { ... }
    

BEM Nesting


    .nombre-del-bloque {
      ...

      &__elemento {
        ...
      }

      &--modificador {
        ...
      }
    }
    

    .nombre-del-bloque { ... }
    .nombre-del-bloque__elemento { ... }
    .nombre-del-bloque--modificador { ... }
    

Refactorizando:


  .tab-group { ... } /* 0, 0, 1, 0 */

  .tab-group > li { ... } /* 0, 0, 1, 1 */

  .tab-group a { ... } /* 0, 0, 1, 1 */

  .tab-group a.selected { ... } /* 0, 0, 2, 1 */
    

  .tab-group { ... } /* 0, 0, 1, 0 */

  .tab-group__tab { ... } /* 0, 0, 1, 0 */

  .tab-group__link { ... } /* 0, 0, 1, 0 */

  .tab-group__link--selected { ... } /* 0, 0, 1, 0 */
    

Otros sistemas nomenclaturas

Cómo continuar

Aprender y adaptar:

Es importante seguir leyendo y mirando los diferentes frameworks o soluciones que va creando la comunidad pero siempre adaptándolos a nuestras necesidades. No al copy-paste.

Practicar:

Aplicar las buenas prácticas siempre que se pueda, la mayoría son universales y no dependen del tamaño o naturaleza del proyecto.

Divide y vencerás:

Intentar repartir nuestro código en pequeños trozos manejables. Evitar los archivos de 2000 líneas.

Documentar:

Dejar nuestro código bien documentado nos ayudará a volver sobre nuestros proyectos pasado un tiempo sin perder la razón, además de ayudar a otros developers que trabajen con el mismo.

Documentar también nos ayuda a reflexionar sobre lo que hemos hecho y fijar conceptos.

Refactor constante:

No tener miedo al refactor siempre y cuando se haga con las precauciones adecuadas. Si hemos seguido buenas prácticas refactorizar no debería ser muy costoso.

¡Grácias!