MENOS CSS: abusando de & Operator cuando anida?

Less usa el operador & para mejorar las posibilidades de anidación .

 .header { color: black; .navigation { font-size: 12px; &.class { text-decoration: none } } } 

que causa una sustitución de & con el selector principal y da como resultado una concatenación del selector real al selector principal: .header .navigation.class lugar de .header .navigation.class normal, lo que daría como resultado que .class sea ​​un descendiente: .header .navigation .class .

Ahora lo que también es posible es lo siguiente ( ver también aquí ):

 .header { color: black; .navigation { font-size: 12px; #some-id & .foo { text-decoration: none } } } 

que daría como resultado lo siguiente: #some-id .header .navigation .foo try aquí . La substición se lleva a cabo y he antepuesto un selector ( #some-id ) a mi selector principal.

Además del hecho de que nunca codificaría de esta manera, ya que esto probablemente arruina tu hoja de estilo en un instante, mi pregunta:

Como esta funcionalidad no está documentada, ¿es una característica o más probablemente un error?
¿Cuáles son los posibles efectos secundarios?

También he estado reflexionando sobre este uso más desde que lo encontramos en esa pregunta que mencionaste . Si bien no puedo responder definitivamente que este es un uso de “error” para & (BoltClock parece hacer un buen argumento de que no es un error), quiero argumentar a favor del valor (que argumenta que no es un error de un punto de vista lógico).

Sin embargo, antes del argumento lógico, encontré otra cita corta y simple (en la sección “reglas anidadas”) que parece indicar que al menos no es involuntaria: ” & representa el padre selector actual”. Eso es. Como BoltClock argumenta, ya sea anteponer o agregar parece irrelevante. Todo lo que se pretendía era que fuera un marcador de posición para ese “padre selector” que es actual hasta ese momento. El hecho de que siempre se menciona junto con el uso de “anidación” del lenguaje implica que está diseñado para designar la secuencia de selección completa del nido hasta el punto del nido en el que reside. La forma en que se utiliza esa secuencia (para pre o anexar) le correspondería al codificador.

Ahora, menciona (y mencionó anteriormente) que “nunca codificaría de esta manera” y, sin embargo, me encuentro viendo lo que parece ser un uso muy valioso para esto. Considera el siguiente argumento.

La configuración de HTML para la ilustración

Supongamos, por el bien de la ilustración, que hay una configuración dinámica de tres clases posibles (temas “claro”, “medio”, “oscuro”) en el elemento del body que cambian el “aspecto” del sitio. Tenemos dos columnas y varios tipos de enlaces que queremos textLink ( textLink , picLink , textWithIconLink ) de manera diferente en cada columna para cada tema.

  

Ahora las preguntas son solo mirar los enlaces de los dos métodos siguientes, que …

  1. Es menos código en LESS
  2. Las mejores organizas el código en LESS
  3. Emite menos código en CSS
  4. Best organiza el CSS entregado

“Mejor” puede ser algo subjetivo. Te dejaré sopesar esa evidencia desde abajo.

Opción # 1 Nesting típico

MENOS (aproximadamente 99 líneas de código)

 /*Light Color Theme */ .light { .leftCol { .textLink { color: fooL1; &:hover { color: barL1;} } .picLink { background-image: url(/fooL1.jpg); &:hover { background-image: url(/barL1.jpg);} } .textWithIconLink { color: fooL2; background-image: url(/fooL2.jpg); &:hover { color: barL2; background-image: url(/barL2.jpg);} } } .rightCol { .textLink { color: fooL3; &:hover { color: barL3;} } .picLink { background-image: url(/fooL3.jpg); &:hover { background-image: url(/barL3.jpg);} } .textWithIconLink { color: fooL4; background-image: url(/fooL4.jpg); &:hover { color: barL4; background-image: url(/barL4.jpg);} } } } /*Medium Color Theme */ .medium { .leftCol { .textLink { color: fooM1; &:hover { color: barM1;} } .picLink { background-image: url(/fooM1.jpg); &:hover { background-image: url(/barM1.jpg);} } .textWithIconLink { color: fooM2; background-image: url(/fooM2.jpg); &:hover { color: barM2; background-image: url(/barM2.jpg);} } } .rightCol { .textLink { color: fooM3; &:hover { color: barM3;} } .picLink { background-image: url(/fooM3.jpg); &:hover { background-image: url(/barM3.jpg);} } .textWithIconLink { color: fooM4; background-image: url(/fooM4.jpg); &:hover { color: barM4; background-image: url(/barM4.jpg);} } } } /*Dark Color Theme */ .dark { .leftCol { .textLink { color: fooD1; &:hover { color: barD1;} } .picLink { background-image: url(/fooD1.jpg); &:hover { background-image: url(/barD1.jpg);} } .textWithIconLink { color: fooD2; background-image: url(/fooD2.jpg); &:hover { color: barD2; background-image: url(/barD2.jpg);} } } .rightCol { .textLink { color: fooD3; &:hover { color: barD3;} } .picLink { background-image: url(/fooD3.jpg); &:hover { background-image: url(/barD3.jpg);} } .textWithIconLink { color: fooD4; background-image: url(/fooD4.jpg); &:hover { color: barD4; background-image: url(/barD4.jpg);} } } } 

Salida CSS (aproximadamente 87 líneas de salida, organizadas por tema, por supuesto)

  /*Light Color Theme */ .light .leftCol .textLink { color:fooL1; } .light .leftCol .textLink:hover { color:barL1; } .light .leftCol .picLink { background-image:url(/fooL1.jpg); } .light .leftCol .picLink:hover { background-image:url(/barL1.jpg); } .light .leftCol .textWithIconLink { color:fooL2; background-image:url(/fooL2.jpg); } .light .leftCol .textWithIconLink:hover { color:barL2; background-image:url(/barL2.jpg); } .light .rightCol .textLink { color:fooL3; } .light .rightCol .textLink:hover { color:barL3; } .light .rightCol .picLink { background-image:url(/fooL3.jpg); } .light .rightCol .picLink:hover { background-image:url(/barL3.jpg); } .light .rightCol .textWithIconLink { color:fooL4; background-image:url(/fooL4.jpg); } .light .rightCol .textWithIconLink:hover { color:barL4; background-image:url(/barL4.jpg); } /*Medium Color Theme */ .medium .leftCol .textLink { color:fooM1; } .medium .leftCol .textLink:hover { color:barM1; } .medium .leftCol .picLink { background-image:url(/fooM1.jpg); } .medium .leftCol .picLink:hover { background-image:url(/barM1.jpg); } .medium .leftCol .textWithIconLink { color:fooM2; background-image:url(/fooM2.jpg); } .medium .leftCol .textWithIconLink:hover { color:barM2; background-image:url(/barM2.jpg); } .medium .rightCol .textLink { color:fooM3; } .medium .rightCol .textLink:hover { color:barM3; } .medium .rightCol .picLink { background-image:url(/fooM3.jpg); } .medium .rightCol .picLink:hover { background-image:url(/barM3.jpg); } .medium .rightCol .textWithIconLink { color:fooM4; background-image:url(/fooM4.jpg); } .medium .rightCol .textWithIconLink:hover { color:barM4; background-image:url(/barM4.jpg); } /*Dark Color Theme */ .dark .leftCol .textLink { color:fooD1; } .dark .leftCol .textLink:hover { color:barD1; } .dark .leftCol .picLink { background-image:url(/fooD1.jpg); } .dark .leftCol .picLink:hover { background-image:url(/barD1.jpg); } .dark .leftCol .textWithIconLink { color:fooD2; background-image:url(/fooD2.jpg); } .dark .leftCol .textWithIconLink:hover { color:barD2; background-image:url(/barD2.jpg); } .dark .rightCol .textLink { color:fooD3; } .dark .rightCol .textLink:hover { color:barD3; } .dark .rightCol .picLink { background-image:url(/fooD3.jpg); } .dark .rightCol .picLink:hover { background-image:url(/barD3.jpg); } .dark .rightCol .textWithIconLink { color:fooD4; background-image:url(/fooD4.jpg); } .dark .rightCol .textWithIconLink:hover { color:barD4; background-image:url(/barD4.jpg); } 

Opción n. ° 2 Fin del grupo objective

Lo llamé “Finalizar agrupación de objectives”, porque así es como realmente veo usar el & de esta otra manera de agregar selectores principales. Uno ahora está codificando basado en el elemento objective final que en realidad está siendo diseñado.

MENOS (aproximadamente 88 líneas de código)

 /*Links */ /*Text Links*/ .textLink { .light .leftCol & { color: fooL1; &:hover { color: barL1;} } .light .rightCol & { color: fooL3; &:hover { color: barL3;} } .medium .leftCol & { color: fooM1; &:hover { color: barM1;} } .medium .rightCol & { color: fooM3; &:hover { color: barM3;} } .dark .leftCol & { color: fooD1; &:hover { color: barD1;} } .dark .rightCol & { color: fooD3; &:hover { color: barD3;} } } /*Picture Links */ .picLink { .light .leftCol & { background-image: url(/fooL1.jpg); &:hover { background-image: url(/barL1.jpg);} } .light .rightCol & { background-image: url(/fooL3.jpg); &:hover { background-image: url(/barL3.jpg);} } .medium .leftCol & { background-image: url(/fooM1.jpg); &:hover { background-image: url(/barM1.jpg);} } .medium .rightCol & { background-image: url(/fooM3.jpg); &:hover { background-image: url(/barM3.jpg);} } .dark .leftCol & { background-image: url(/fooD1.jpg); &:hover { background-image: url(/barD1.jpg);} } .dark .rightCol & { background-image: url(/fooD3.jpg); &:hover { background-image: url(/barD3.jpg);} } } /*Text with Icon Links */ .textWithIconLink { .light .leftCol & { color: fooL2; background-image: url(/fooL1.jpg); &:hover { color: barL2; background-image: url(/barL1.jpg);} } .light .rightCol & { color: fooL4; background-image: url(/fooL3.jpg); &:hover { color: barL4; background-image: url(/barL3.jpg);} } .medium .leftCol & { color: fooM2; background-image: url(/fooM1.jpg); &:hover { color: barM2; background-image: url(/barM1.jpg);} } .medium .rightCol & { color: fooM4; background-image: url(/fooM3.jpg); &:hover { color: barM4; background-image: url(/barM3.jpg);} } .dark .leftCol & { color: fooD2; background-image: url(/fooD1.jpg); &:hover { color: barD2; background-image: url(/barD1.jpg);} } .dark .rightCol & { color: fooD4; background-image: url(/fooD3.jpg); &:hover { color: barD4; background-image: url(/barD3.jpg);} } } 

CSS (aproximadamente 88 líneas de salida [debido a un comentario adicional], organizado por elemento objective final, pero tenga en cuenta que todavía hay una suborganización por tema debido a la estructura de clase)

 /*Links*/ /*Text Links*/ .light .leftCol .textLink { color:fooL1; } .light .leftCol .textLink:hover { color:barL1; } .light .rightCol .textLink { color:fooL3; } .light .rightCol .textLink:hover { color:barL3; } .medium .leftCol .textLink { color:fooM1; } .medium .leftCol .textLink:hover { color:barM1; } .medium .rightCol .textLink { color:fooM3; } .medium .rightCol .textLink:hover { color:barM3; } .dark .leftCol .textLink { color:fooD1; } .dark .leftCol .textLink:hover { color:barD1; } .dark .rightCol .textLink { color:fooD3; } .dark .rightCol .textLink:hover { color:barD3; } /*Picture Links */ .light .leftCol .picLink { background-image:url(/fooL1.jpg); } .light .leftCol .picLink:hover { background-image:url(/barL1.jpg); } .light .rightCol .picLink { background-image:url(/fooL3.jpg); } .light .rightCol .picLink:hover { background-image:url(/barL3.jpg); } .medium .leftCol .picLink { background-image:url(/fooM1.jpg); } .medium .leftCol .picLink:hover { background-image:url(/barM1.jpg); } .medium .rightCol .picLink { background-image:url(/fooM3.jpg); } .medium .rightCol .picLink:hover { background-image:url(/barM3.jpg); } .dark .leftCol .picLink { background-image:url(/fooD1.jpg); } .dark .leftCol .picLink:hover { background-image:url(/barD1.jpg); } .dark .rightCol .picLink { background-image:url(/fooD3.jpg); } .dark .rightCol .picLink:hover { background-image:url(/barD3.jpg); } /*Text with Icon Links */ .light .leftCol .textWithIconLink { color:fooL2; background-image:url(/fooL1.jpg); } .light .leftCol .textWithIconLink:hover { color:barL2; background-image:url(/barL1.jpg); } .light .rightCol .textWithIconLink { color:fooL4; background-image:url(/fooL3.jpg); } .light .rightCol .textWithIconLink:hover { color:barL4; background-image:url(/barL3.jpg); } .medium .leftCol .textWithIconLink { color:fooM2; background-image:url(/fooM1.jpg); } .medium .leftCol .textWithIconLink:hover { color:barM2; background-image:url(/barM1.jpg); } .medium .rightCol .textWithIconLink { color:fooM4; background-image:url(/fooM3.jpg); } .medium .rightCol .textWithIconLink:hover { color:barM4; background-image:url(/barM3.jpg); } .dark .leftCol .textWithIconLink { color:fooD2; background-image:url(/fooD1.jpg); } .dark .leftCol .textWithIconLink:hover { color:barD2; background-image:url(/barD1.jpg); } .dark .rightCol .textWithIconLink { color:fooD4; background-image:url(/fooD3.jpg); } .dark .rightCol .textWithIconLink:hover { color:barD4; background-image:url(/barD3.jpg); } 

pensamientos conclusivos

Algunas otras consideraciones:

Primero, la mayoría de los colores de los temas (y posiblemente otros aspectos de los temas) se configurarán con variables, que se pueden agrupar en la parte superior del código LESS por tema, incluso utilizando la Opción n.º 2 anterior, teniendo así la estructura del tema para la salida CSS en sí mismo esparcido en el código no es necesariamente malo.

En segundo lugar, cualquier código “estándar” para un tipo de elemento se define encima de cualquier código de tema. Mis ejemplos no mostraron esto, pero dicen que todos los elementos .textLink tenían text-decoration: none; conjunto. Eso ocurriría una vez en la Opción # 2 sin ningún otro código de selector, y aparecería sobre todos los cambios de tema a continuación. Para la Opción # 1, necesito configurar un selector .textLink nuevo, sin .textLink (al menos otra línea de código) para aplicarlo a todos los enlaces temáticos, y ese código “base” para la clase estará, de nuevo, en algún lugar sin relación a donde está el rest del código para la información del enlace del tema.

Tercero, como desarrollador, si tengo problemas con mis picLinks (un tipo específico de elemento en mi página), la Opción # 2 hace que sea mucho más fácil examinar mi código para el elemento con el que estoy teniendo problemas, ya que todo mi código para todos los temas están justo en un lugar.

Obviamente, cómo uno quiere que el LESS final y el CSS estén organizados va a ser un factor importante en cómo uno ve el valor de esto. Mi punto aquí es simplemente demostrar que hay una razón lógica muy útil para usar & de esta manera de agregar selectores de nivel padre a la & referencia.

No es un abuso del & combinador en absoluto; puede ubicarlo en cualquier lugar de un selector nested y se lo sustituirá por lo que esté sobre él (su llamado selector principal):

[El & combinador es] utilizado cuando desea que un selector nested se concatene con su selector principal, en lugar de actuar como un descendiente.

Observe que dice “concatenado”; no dice que solo puede anteponer o anexar el selector principal al selector nested. La concatenación no funciona solo en una dirección específica.

Además, la palabra “descendiente” tiene que ver con la naturaleza de los selectores nesteds que se tratan como si estuvieran vinculados por el combinador descendiente de forma predeterminada. De ninguna manera esto limita intrínsecamente el uso de & a los descendientes solamente, ni implica que el selector padre tenga que representar un elemento padre o ancestro de tal forma que el selector nested solo pueda ser anexado a él, y no anexado o incluso insertado en el medio de ella.