Crear una lista de selectores con MENOS

Problema general

Tengo consultas de medios, donde cambio ciertos elementos de texto de esta manera:

body.single .entry-content p, body.single .entry-content ul, body.single .entry-content ol, body.single .entry-content table { line-height: 1.8; } 

¿Cómo puedo usar LESS para construir solo la lista de selectores, no los valores CSS correspondientes?

Mi bash

No estoy buscando esta respuesta o esta , que incluye el CSS en la función. En cambio, me imagino que se usa así:

 /* .selector-list() { ... } */ @text-elements: p, ul, ol, table; .selector-list("body.single .entry-content", @text-elements); @selector-list { line-height: 1.8; } 

Básicamente, construiría una lista de cadenas añadiendo el elemento principal (“body.category”) y anexando una coma a cada elemento de un conjunto. Esto es lo que he intentado solo para probar el resultado:

 @text-elements: p, ul, ol, table; .selector-list(@parent, @children, @i:1, @list:"") when (@i <= length(@children)) { @child: extract(@children, @i); @selector-list: "@{list} @{parent} @{child},"; .selector-list(@parent, @children, (@i + 1), @selector-list); } .selector-list("body.single .entry-content", @text-elements); section { content: @selector-list; // yields only " body.single .entry-content p," } 

¿Por qué @ selector-list no pasa el primer elemento? No entiendo completamente cuando algo se imprime / devuelve, ¿entonces quizás estoy haciendo esto de la manera incorrecta?

Como ya se mencionó, su bash casi está allí, no funciona debido a las reglas de visibilidad variable. Observe que cada iteración .selector-list define una nueva variable @selector-list que tiene mayor precedencia en el ámbito actual, pero no anula las variables @selector-list para el ámbito externo (es decir, ámbitos de las .selector-list anteriores de .selector-list y superiores ) . Entonces, cuando usas @selector-list después de la .selector-list inicial .selector-list obtienes el valor establecido en la iteración “más alta” .selector-list (es decir, la primera con @i = 1 ).

Para “devolver” un valor de la última iteración de un bucle recursivo, necesita definir una variable con este valor solo dentro de esa última iteración. Por lo general, la forma más sencilla de hacerlo es proporcionar una mixin “terminal” (es decir, una especialización para la última llamada de la mezcla recursiva). De hecho, necesitaría tal terminal de todos modos para manejar la coma final de la lista. P.ej:

# 1

 .selector-list(@parent, @children, @i: 1, @list: "") when (@i < length(@children)) { @child: extract(@children, @i); .selector-list(@parent, @children, (@i + 1), "@{list} @{parent} @{child},"); } .selector-list(@parent, @children, @i, @list) when (@i = length(@children)) { @child: extract(@children, @i); @selector-list: e("@{list} @{parent} @{child}"); } // usage: @text-elements: p, ul, ol, table; .selector-list("body.single .entry-content", @text-elements); @{selector-list} { line-height: 1.8; } 

-

# 2 Igual que el anterior ligeramente "optimizado":

 .selector-list(@parent, @children, @i: length(@children), @list...) when (@i > 1) { .selector-list(@parent, @children, (@i - 1), e(", @{parent}") extract(@children, @i) @list); } .selector-list(@parent, @children, 1, @list) { @selector-list: e(@parent) extract(@children, 1) @list; } // usage: @text-elements: p, ul, ol, table; .selector-list("body.single .entry-content", @text-elements); @{selector-list} { line-height: 1.9; } 

-

# 3 Hablando del caso de uso en general, una "manipulación de selector basada en cadenas" no siempre es una buena idea en el contexto de Less. El principal problema es que Less no trata tales cadenas como selectores "nativos" y la mayoría de las características avanzadas de Less no funcionarán con ellos (por ejemplo, Less no reconocerá & y elementos similares allí, por lo que dichas reglas no pueden anidarse , extend también no puede ver tales selectores etc. etc.). Un enfoque alternativo, más "menos favorable" es definir dicha lista como mixin en lugar de variable, por ejemplo:

 .text-elements(@-) {p, ul, ol, table {@-();}} body.single .entry-content { .text-elements({ line-height: 1.8; }); } 

y (cuando también necesita reutilizar body.single .entry-content /.text-elements/ ):

 .text-elements(@-) { p, ul, ol, table {@-();}} .selector-list(@-) { body.single .entry-content { .text-elements(@-); } } .selector-list({ line-height: 1.9; }); 

etc.

-

PD. Además, hablando aún más general, no te pierdas eso en Menos una consulta de medios se puede poner en el conjunto de reglas de selector, por lo que dependiendo de un caso de uso también es a menudo más fácil escribir una lista de selectores una vez y establecer estilos dependientes de los medios dentro de él (es decir, haciéndolo en oposición al método CSS estándar en el que tiene que repetir los mismos selectores para cada consulta de medios).

Esto es bastante cercano. Necesita un pequeño ajuste para hacerlo exactamente, pero sin duda es un buen comienzo.

El problema con su bash es que a LESS no le gusta sobrescribir las mismas variables y producirá un error. Esto se debe a que las variables son constantes en LESS.

MENOS

 @text-elements: p, ul, table; .selector-list(@el,@t1) { @selector-list: ~"@{t1}, body.single .entry-content @{el}"; } .selector-list(@index, @elements, @t1) when (@index > 1) { @el: extract(@elements, @index); @t2: "@{t1}, body.single .entry-content @{el}"; .selector-list(@elements,@t2); } .selector-list(@elements) { @num: length(@elements); @el: extract(@elements, @num); @t2: "body.single .entry-content @{el}"; .selector-list((@num - 1), @elements, @t2); } .selector-list(@text-elements); @{selector-list} { content: 'Bacon'; } 

Salida

 body.single .entry-content table, body.single .entry-content ul, body.single .entry-content p, ul, table { content: 'Bacon'; } 

Obtuve la mayor parte de esto de esta respuesta SO; Concatenar cadena en menos en bucle