Bucles en los preprocesadores CSS | Programar Plus

Si alguna vez has visto viejas películas de ciencia ficción, sabes lo poderosos que pueden ser los bucles. Alimenta a tu robot némesis con un bucle infinito y kaboom. Robo polvo.

Los bucles de preprocesador no causarán explosiones dramáticas en el espacio (espero), pero son útiles para escribir DRY CSS. Si bien todo el mundo habla de bibliotecas de patrones y diseño modular, la mayor parte de la atención se ha centrado en los selectores de CSS. Independientemente del acrónimo que impulse sus selectores (BEM, OOCSS, SMACSS, ETC), los bucles pueden ayudar a que sus patrones sean más legibles y mantenibles, integrándolos directamente en su código.

Echaremos un vistazo a lo que pueden hacer los bucles y cómo usarlos en los principales preprocesadores de CSS: Sass, Less y Stylus. Cada idioma proporciona una sintaxis única, pero todos hacen el trabajo. Hay más de una manera de hacer un lazo con un gato.

ver la pluma
Walkcycle con bucle de música por Programar Plus(@css-tricks)
en CodePen.

(animación de Rachel Nabors)

PostCSS también es popular, pero no proporciona ninguna sintaxis propia. Si bien a veces se le llama posprocesador, yo lo llamaría metapreprocesador. PostCSS le permite escribir y compartir su propia sintaxis de preprocesador. Si quisiera, podría volver a escribir Sass o Less dentro de PostCSS, pero alguien más se le adelantó.

Condiciones de bucle

Star Trek no estaba del todo equivocado. Si no tiene cuidado, los bucles infinitos pueden ralentizar o bloquear su compilador. Si bien esa no es una buena manera de vaporizar robots malvados, molestará a cualquiera que use su código. Es por eso que los bucles siempre deben tener un propósito limitado, generalmente definido por una cantidad de repeticiones incrementales o una colección de objetos.

En términos de programación:

  1. Mientras los bucles son genéricos y seguirán repitiéndose mientras se cumple alguna condición. ¡Ten cuidado! Aquí es donde los bucles infinitos son más probables.
  2. Para los bucles son incrementales, en ejecución por un determinado número de repeticiones.
  3. Para cada los bucles iteran a través de una colección o lista, considerando cada artículo uno a la vez.

Cada tipo de bucle tiene un enfoque más limitado que el anterior. A for-each loop es solo un tipo de for bucle, que es un tipo de while círculo. Pero la mayoría de sus casos de uso caerán en categorías más específicas. Tuve problemas para encontrar la verdad while bucles en la naturaleza: la mayoría de los ejemplos podrían haberse manejado mejor con for o for-each. Probablemente sea por eso que Stylus solo proporciona sintaxis para este último. Sass proporciona una sintaxis única para los tres, y Less técnicamente no tiene ninguna sintaxis de bucle, ¡pero eso no nos detendrá! Sumerjámonos.

Colección for-each Bucles

Los bucles de preprocesador son más útiles cuando tiene una colección (lista o matriz) de elementos para recorrer, como una matriz de iconos y colores de redes sociales, o una lista de modificadores de estado (success, warning, error, etc.). Porque for-each los bucles están vinculados a una colección conocida de elementos, tienden a ser los bucles más concretos y comprensibles.

Comencemos recorriendo una lista simple de colores para ver cómo funciona.

En Hablar con descaro a, usaremos el @each directiva (@each $item in $list) para llegar a los colores:

Consulte la lista Pen Sass ForEach de Miriam Suzanne (@mirisuzanne) en CodePen.

En Aguja, el for sintaxis (for item in list) maneja colecciones:

Consulte la lista Pen Stylus ForEach de Miriam Suzanne (@mirisuzanne) en CodePen.

Menos no proporciona una sintaxis de bucle, pero podemos falsificarla con recursividad. La recursividad es lo que sucede cuando llamas a una función o mezclas desde dentro de sí misma. En Less, podemos usar mixins para la recursividad:

.recursion() {
  /* an infinite recursive loop! */
  .recursion();
}

Ahora agregaremos un when “proteger” a la mezcla, para evitar que se reproduzca infinitamente.

.recursion() when (@conditions) { 
  /* a conditional recursive "while" loop! */
  .recursion();
}

Podemos hacer que sea un por bucle agregando un contador (@i), que comienza en 1, y aumenta con cada repetición (@i + 1) mientras nuestra condición (@i <= length(@list)) se cumple — donde length(@list) restringe nuestras iteraciones de bucle a la misma longitud que nuestra colección. Si extraemos el siguiente elemento de la lista en cada pasada, tendremos una para cada círculo:

Consulte la lista Pen Less ForEach de Miriam Suzanne (@mirisuzanne) en CodePen.

En Less, puedes hacer todo de la manera difícil. Construye carácter.

Botones de redes sociales

Recorrer listas puede ser útil, pero lo más frecuente es que desee recorrer objetos. Un ejemplo común es asignar diferentes colores e íconos a los botones de las redes sociales. Para cada elemento de la lista, necesitaremos el nombre del sitio y el color de la marca para esa red social:

$social: (
  'facebook': #3b5999,
  'twitter': #55acee,
  'linkedin': #0077B5,
  'google': #dd4b39,
);

Utilizando Hablar con descaro a, podemos acceder a la clave (nombre de la red) y el valor (color de la marca) de cada par usando la sintaxis @each $key, $value in $array. Aquí está el bucle completo:

Vea el bucle de redes sociales Pen Sass de Miriam Suzanne (@mirisuzanne) en CodePen.

Aguja tiene una sintaxis similar: for key, value in array

Vea el Pen Stylus Social Media Loop de Miriam Suzanne (@mirisuzanne) en CodePen.

En Menos, tenemos que extraer cada lado del par manualmente:

Vea Pen LESS Social Media Loop de Miriam Suzanne (@mirisuzanne) en CodePen.

Incremental for Bucles

Para los bucles pueden ejecutarse para cualquier número de repeticiones, no solo para la longitud de un objeto. Puede usar esto para crear un diseño de cuadrícula (for columns from 1 through 12), recorrer la rueda de colores (for hue from 1 through 360), o numere sus divs con nth-child y contenido generado.

Comencemos con un bucle a través de 36 div elementos, proporcionando un número y color de fondo en cada uno, usando :nth-child.

Hablar con descaro a proporciona una sintaxis for-loop especial: @for $count from $start through $finish, donde $start y $finish ambos son enteros. Si el valor inicial es mayor, Sass contará hacia atrás en lugar de hacia arriba.

Vea el bucle “for” de Pen Sass de Miriam Suzanne (@mirisuzanne) en CodePen.

El through palabra clave significa que nuestro bucle incluirá el número 36. También puede utilizar el to palabra clave, que no incluye el contador final: @for $i from 1 to 36 solo haría un bucle 35 veces.

Aguja tiene una sintaxis similar para incrementar, pero to y through se reemplazan con ... y .. respectivamente:

Vea el bucle “for” de Pen Stylus de Miriam Suzanne (@mirisuzanne) en CodePen.

Stylus también proporciona una range() función, que le permite cambiar el tamaño de un incremento. Utilizando for hue in range(0, 360, 10) aumentaría la cuenta en 10 en cada repetición.

Menos tendrá que usar mixins recursivos nuevamente. Podemos crear un argumento para el número de iteraciones (@i), guardarlo con la condición when (@i > 0), y reste uno en cada iteración, para que actúe como un bucle for decreciente:

Vea el ciclo Pen Less “for” de Miriam Suzanne (@mirisuzanne) en CodePen.

Vale la pena señalar que CSS también puede darnos la nth-child-numeración sin preprocesadores. Si bien CSS no tiene estructuras de bucle, proporciona una counter() que puede incrementar en función de cualquier cantidad de condiciones relacionadas con DOM y usar en el contenido generado. Lamentablemente no se puede utilizar fuera del content propiedad (todavía), por lo que nuestros colores de fondo no se aplican:

Vea el contador Pen CSS de Miriam Suzanne (@mirisuzanne) en CodePen.

Sistemas de red

Ocasionalmente uso bucles incrementales en mis kits de herramientas abstractos de Sass, pero casi nunca en hojas de estilo reales. La única excepción común es generar selectores numerados, ya sea con nth-child (como hicimos anteriormente) o en clases generadas automáticamente (a menudo utilizadas para sistemas de cuadrícula). Construyamos un sistema de cuadrícula fluida simple sin canales para dificultar las matemáticas:

Vea las cuadrículas For-Loop de Pen Sass de Miriam Suzanne (@mirisuzanne) en CodePen.

Cada intervalo de cuadrícula es un porcentaje, usando las matemáticas span / context * 100% — el cálculo básico que deben realizar todos los sistemas de red. Aquí está de nuevo en Stylus and Less:

Vea las cuadrículas For-Loop de Pen Stylus de Miriam Suzanne (@mirisuzanne) en CodePen.

Vea las cuadrículas For-Loop de Pen LESS de Miriam Suzanne (@mirisuzanne) en CodePen.

Avatares únicos

En OddBird, recientemente diseñamos una aplicación con avatares de usuario predeterminados, pero queríamos que los valores predeterminados fueran lo más únicos posible. Al final, diseñamos solo nueve íconos únicos y usamos bucles para transformarlos en 1296 avatares diferentes, por lo que la mayoría de los usuarios nunca verían un duplicado.

Cada avatar tiene cinco atributos:

<svg class="avatar" data-dark="1" data-light="2" data-reverse="true" data-rotation="3">
  <use xlink:href="https://css-tricks.com/loops-css-preprocessors/#icon-avatar-1" xmlns:xlink="http://www.w3.org/1999/xlink"></use>
</svg>
  1. La forma del icono inicial (9 opciones)
  2. Rotación de 0, 90, 180, o 270 grados (4 opciones)
  3. Un color oscuro para el relleno (6 opciones)
  4. Un color claro para el fondo (6 opciones)
  5. A true/false atributo que invierte los colores (2 opciones)

El código tiene seis colores y tres bucles:

  1. @for $i from 0 through 3 nos da cuatro rotaciones
  2. @for $i from 1 through length($colors) nos permite recorrer la lista de colores ($colors), y asigne a cada color un número ($i). Normalmente usaría el @each bucle para recorrer la colección de colores, pero @for es más simple cuando también necesito un número para cada elemento.
  3. el anidado @each $reverse in (true, false) nos da la opción de voltear el primer plano y el fondo para cada combinación de colores.

Aquí está el resultado final en Hablar con descaro a:

Vea los avatares de Pen 1296 usando múltiples bucles de Miriam Suzanne (@mirisuzanne) en CodePen.

Convirtiendo eso en Menos y Aguja puede ser tu tarea. Ya estoy cansado de mirarlo.

Genérico while Bucles

Cierto while los bucles son raros, pero los uso en ocasiones. Los encuentro más útiles cuando estoy siguiendo un camino para ver a dónde conduce. No quiero recorrer una colección completa o un número específico de iteraciones; quiero seguir recorriendo hasta encontrar lo que estoy buscando. Esto es algo que uso en mis kits de herramientas abstractos, pero no es algo que necesitará muy a menudo en el estilo del día a día.

Creé un conjunto de herramientas para ayudarme a almacenar y manipular colores en Sass. El almacenamiento de colores en variables podría ser el caso de uso más común para cualquier preprocesador. La mayoría de la gente hace algo como esto:

$pink: #E2127A;
$brand-primary: $pink;
$site-background: $brand-primary;

Yo sé eso pink Probablemente no sea el único color en su sitio, pero es el único que necesitamos por ahora. Le di varios nombres porque es útil para establecer capas de abstracción, desde colores simples (pink), a patrones más amplios (brand-primary) y casos de uso concretos (site-background). También quiero convertir esa lista de colores individuales en una paleta que mi preprocesador pueda entender. Necesito una forma de decir que estos valores están todos relacionados y son parte de un patrón. De esa manera, almaceno todos los colores de mi tema en un solo mapa Sass, con pares clave-valor:

$colors: (
  'pink': #E2127A,
  'brand-primary': 'pink',
  'site-background': 'brand-primary',
);

¿Por qué molestarse? Lo hago porque puedo apuntar mi generador de guía de estilo a una sola variable y crear automáticamente una paleta de colores que se mantiene actualizada. Pero hay ventajas y desventajas, y no es la solución adecuada para todos. El mapa no me permite realizar asignaciones directas entre pares, como podría hacerlo con las variables. necesito un while bucle para seguir el rastro de migas de pan de nombres clave, para encontrar el valor de cada color:

Vea el bucle “while” de Pen Sass de Miriam Suzanne (@mirisuzanne) en CodePen.

Hago eso todo el tiempo, pero si buscas en mi código el de Sass @while, no lo encontrarás. Eso es porque puedes lograr lo mismo con una función recursiva, haciéndola reutilizable:

Vea la función recursiva “while” de Pen Sass de Miriam Suzanne (@mirisuzanne) en CodePen.

Ahora podemos llamar al color() funcionar en cualquier parte de nuestro código.

Aguja no tiene sintaxis para while bucles, pero también permite variables de matriz y funciones recursivas:

Vea el bucle “while” de Pen Stylus de Miriam Suzanne (@mirisuzanne) en CodePen.

Menos no tiene variables de matriz incorporadas, pero podemos imitar el mismo efecto creando una lista de pares, de la misma manera que hicimos con los colores de las redes sociales:

@colors:
  'pink' #E2127A,
  'brand-primary' 'pink',
  'site-background' 'brand-primary'
;

Tendremos que crear el nuestro @array-get mixin para recuperar valores de la matriz usando nombres clave, y luego crea nuestro ciclo while recursivo para seguir la ruta:

Vea el bucle de la lista Pen Less “while” de Miriam Suzanne (@mirisuzanne) en CodePen.

Eso funciona con fines de demostración, pero probablemente haya una mejor manera de hacerlo en Less, ya que puede alias y variables de espacio de nombres sin usar una matriz (a diferencia de Sass o Stylus):

Consulte las variables con espacio de nombres Pen Less de Miriam Suzanne (@mirisuzanne) en CodePen.

Ahora que mis colores están correctamente en una variable, puedo usar otro bucle para generar mi paleta de colores. He aquí un ejemplo rápido en Hablar con descaro a:

Vea la paleta de colores Pen Sass de Miriam Suzanne (@mirisuzanne) en CodePen.

Estoy seguro de que podrías hacerlo más bonito que yo.

¡Consiguiendo Loopy!

Si no está seguro de cuándo usar bucles en su código, esté atento a la repetición. ¿Tiene varios selectores que siguen un patrón similar o un cálculo que está haciendo una y otra vez? He aquí cómo saber qué bucle es el mejor:

  1. Si puede enumerar y nombrar los elementos en su ciclo, use for-each para circular por ellos.
  2. Si el número de repeticiones es más importante que cualquier conjunto de elementos de origen, o si necesita numerar sus elementos, utilice un for círculo.
  3. Si necesita acceder al mismo ciclo con diferentes entradas, pruebe una función recursiva en su lugar.
  4. Para cualquier otra cosa (casi nunca), utilice un while círculo.
  5. Si está usando Less… ¡Buena suerte!

¡Diviértete haciendo bucles!

(Visited 4 times, 1 visits today)