Less.js: : extender mixins

Creado en 12 feb. 2013  ·  112Comentarios  ·  Fuente: less/less.js

Esta solicitud de función se propuso como una solución a este problema https://github.com/cloudhead/less.js/issues/1155

Esta es la sinopsis

Lo asombroso de los mixins es que aceleran el desarrollo, mantienen limpia mi superficie de trabajo, solo tengo que escribirlos una vez y sé cuál será el resultado compilado. Sin embargo, una desventaja de los mixins es que no están SECOS. Especialmente cuando usa mucho mixins de "utilidad", como clearfix. Aquí es donde la extensión _podría_ ser una opción mucho mejor. De hecho, este es un gran caso de uso concreto para extender mixins . Básicamente, funcionaría como extender selectores anidados, aceptar con mixins. Entonces los mixins no cambiarían en absoluto, seguirían funcionando de la misma manera. Si tiene un mixin y no lo usa, no se mostrará en el CSS compilado. Si lo usa, sus propiedades seguirán apareciendo en el código compilado en cada selector donde se usó. Y si _ extiende _ un mixin, el selector (o selectores) que extiende el mixin aparecerá en lugar del mixin. Entonces, si haces esto:

.clearfix() {
    // stuff
}
.navbar {
    &:extend(.clearfix());
}
.banner {
    &:extend(.clearfix());
}

y el resultado compilado será:

.navbar,
.banner {
   // clearfix stuff
}

Entonces, las propiedades de los mixins aún son heredadas por los selectores que las extendieron, pero el mixin (selector) en sí mismo no aparece en el resultado compilado.

Esto haría que tanto las extensiones como las mezclas sean mucho más poderosas de lo que son por sí mismas.

feature request medium priority up-for-grabs

Comentario más útil

Anuncio de servicio publico

En cualquier momento, puede enviar una solicitud de extracción o trabajar con un desarrollador para obtener una, y es muy probable que esta función se fusione. La biblioteca Less.js necesita contribuciones más regulares de personas como las personas en este hilo. . No es responsabilidad de nadie. Depende completamente de que una persona vea este hilo, o necesite esta función, y se tome el tiempo para hacerlo realidad.

Si su respuesta es que no es un desarrollador, entonces hay muchas OTRAS formas en las que puede apoyar este proyecto en roles que no sean de desarrollo, ya sea proporcionando la documentación necesaria para nuevas funciones o el diseño de soporte en el sitio web, ejecutando pruebas, proporcionando comentarios. sobre problemas, gestión de proyectos, responder preguntas sobre Stack Overflow, escribir publicaciones en blogs, tuitear sobre Less, contribuir a CSS y comunidades web, y escribir bibliotecas Less.

Muchas de estas tareas las realizan personas que son desarrolladores, por lo que el tiempo que podrían estar contribuyendo al desarrollo se dedica a estas otras tareas.

Si usted es un desarrollador y su respuesta es "No tengo tiempo", entonces esa es la razón exacta por la que este problema ha quedado abierto. Depende 100% de usted si se completa una función, por lo que preguntar por qué "alguien" no la ha completado no es útil. _Tú eres ese alguien. Sucederá, te garantizo que sucederá, siempre y cuando te involucres en este proyecto. Puede involucrarse en una de las herramientas de código abierto más populares en la web. ¿Puedes marcar la diferencia en la vida de ... miles? ¿Cientos de miles? Millones Y como beneficio adicional, puede asegurarse de que sus funciones favoritas aparezcan más temprano que tarde.

Si desea que suceda esto o cualquier otra característica, hágalo realidad . Nos encantaría tenerte. ¡Nos encantaría trabajar con usted! ¡Menos puede seguir mejorando y mejorando cuanto más grande crece esta comunidad!

Y, escuche, aprecio que a veces la gente realmente no tiene tiempo para contribuir y, sin embargo, realmente le gustaría que ocurriera una característica en particular. Esta bien. Solo diría que si estás en ese escenario, tu objetivo es la empatía y la gratitud por las personas que donan su tiempo (y a veces dinero) para ayudarte, y estoy seguro de que otras personas en la comunidad Less harán todo lo posible para continúen haciéndolo, en la medida de sus posibilidades.

Atentamente,
Matthew Dean, miembro del equipo central de Less.js

Todos 112 comentarios

Me gusta, pero para ser claro ... esto no te permite hacer algo que no podías hacer antes, solo significa que obtienes ...

.navbar,
.banner {
    // clearfix stuff
}

en vez de

.navbar {
    // clearfix stuff
}
.banner {
    // clearfix stuff
}

o he entendido mal?

Me encantaría tener ambos mixins, paramétricos y habituales, para tener

.navbar,
.banner {
    // clearfix stuff
}
.....

o

.clearfix,
.navbar,
.banner {
    // clearfix stuff
}
....

siempre que lo necesite, sé que esta es la forma similar en la que ya funcionan los mixins, por lo que la pregunta tiene principalmente flexibilidad y forma de manejar mejor la salida CSS final en términos de optimización.

seguramente

.clearfix,
.navbar,
.banner {
    // clearfix stuff
}

es más corto que

 .clearfix {
    // clearfix stuff
  }
 .navbar{
    // clearfix stuff
 }
.banner {
    // clearfix stuff
}

y para ejemplos más complicados que podrían ser críticos, y sé que algunas personas cambiaron a SASS solo por esta escasez

Los mixins regulares no podían cambiar. Son prácticamente un elemento fijo de Less. @agatronic , sí, yo también lo veo así. Sin embargo, existen desafíos para esto, como ¿seríamos capaces de extender mixins paramétricos? Y si es así, ¿cómo funcionaría? Suponiendo que esto fuera compatible, digamos que extiende una mezcla paramétrica dos veces pero usa diferentes variables cada vez, así:

.transition(@transition) {
  -webkit-transition: @transition;
     -moz-transition: @transition;
       -o-transition: @transition;
          transition: @transition;
}
.navbar {
    &:extend(.transition(opacity .2s linear));
}
.banner {
    &:extend(.transition(opacity .3s linear));
}

Me imagino que podría crear dos copias del mixin, que no es menos código y no tiene ninguna ventaja sobre los mixins normales:

.navbar {
  -webkit-transition: opacity .2s linear;
     -moz-transition: opacity .2s linear;
       -o-transition: opacity .2s linear;
          transition: opacity .2s linear;
}
.banner {
  -webkit-transition: opacity .3s linear;
     -moz-transition: opacity .3s linear;
       -o-transition: opacity .3s linear;
          transition: opacity .3s linear;
}

Sin embargo, puede usar mucho este mixin en particular, por lo que cuando use el mixin nuevamente en .dropdown con las mismas variables que .banner , podría resultar en esto:

.navbar {
  -webkit-transition: opacity .2s linear;
     -moz-transition: opacity .2s linear;
       -o-transition: opacity .2s linear;
          transition: opacity .2s linear;
}
.banner,
.dropdown {
  -webkit-transition: opacity .3s linear;
     -moz-transition: opacity .3s linear;
       -o-transition: opacity .3s linear;
          transition: opacity .3s linear;
}

Y esto es lo que me hace interesante. También sería bueno escuchar los comentarios de los demás.

@jonschlinkert sí, esa es una ilustración aún mejor, gracias. como dije con ambas manos en eso! pero entienda que está agregando otro nivel de complicidad, y debe hacerse / no hacerlo cuidadosamente

La extensión en el método al que hace referencia se puede lograr con bastante facilidad con este patrón:

.transition(@transition) {
    -webkit-transition: @transition;
     -moz-transition: @transition;
       -o-transition: @transition;
          transition: @transition;
}

.quickOpacity1(){
    .transition(opacity .2s linear);
}

.quickOpacity2(){
    .transition(opacity .3s linear);
}

.navbar{
    .quickOpacity1();
}

.banner,
.dropdown{
    .quickOpacity2();
}

Lo anterior está inyectando mixins semi-extendidos en las 2 nuevas declaraciones.

Para el clearfix también es fácil usar un patrón similar a continuación, que no solo creará el clearfix como una clase, sino que inyectará esos estilos clearfix en una nueva declaración.

.clearfix{
  //clearfix stuff
}
.navbar,
.banner {
    .clearfix;
}

@krismeister Creo que podría haber confusión sobre esto. El patrón que describe es en realidad solo mixins anidados o un patrón de herencia mixin. Extiende el trabajo a la inversa de eso.

@jonschlinkert Herencia de Mixin - un gran nombre. Parecía que los dos ejemplos anteriores trataban de heredar la salida del padre, que es una característica central de la extensión. Probablemente esté de acuerdo en que el resultado de mi ejemplo fue el resultado esperado.

Sin embargo, entiendo que al volver a leer su comentario original, le gustaría que la salida se uniera en una regla CSS. Aunque fue escrito originalmente como 2.

En realidad, :extend es bastante impresionante. Me voy a volver completamente nerd, pero todo se reduce a "qué se mueve a dónde". Piense en un mixin como "transmitir las propiedades del mixin al selector que lo utilizó". Y piense en :extend como el inverso, "enviando el selector que lo usó hasta la mezcla en sí". No las propiedades del _selector, solo el selector en sí. Entonces, si hiciste esto:

.some-mixin() {
    padding-top: 100px;
    background: #f7f7f7;
}


// a selector that is extending the mixin
.alert:extend( .some-mixin() ) {
    border: 1px solid #e5e5e5;
}
// another selector extending the mixin
section:extend(.some-mixin()) {
    margin: 20px 0;
}

Resultaría en esto:

// The selectors that extended the mixin are now where the mixin used to be.
.alert,
section {
    padding-top: 100px;
    background: #f7f7f7;
}

// And the properties of the mixin did not get copied down below
// so we saved a line or two of code.
.alert {
    border: 1px solid #e5e5e5;
}
section {
    margin: 20px 0;
}

Ojalá tenga más sentido. Estoy feliz de poder ayudar en cualquier momento.

@agatronic , @matthewdl , @DesignByOnyx , solo un pensamiento, sé que este es un enfoque inusual, pero asumiendo que no hay desafíos técnicos para esto, y asumiendo que permitimos una lista de selectores separados por comas, tal vez extender _ debería_ sentirse más como una matriz . ¿Qué opinas sobre cambiar la sintaxis a: :extend[N] .

Creo que también es más agradable para los ojos cuando se extienden los mixins:

section:extend[.some-mixin(), .another-mixin()] {
    margin: 20px 0;
}

Estoy bien de cualquier manera, pero algo se siente bien acerca de los corchetes.

@jonschlinkert - [] significa atributo en css, no matriz, donde se eligió :extend() debido a su enlace a pseudo selectores, por lo que creo firmemente que los corchetes normales deberían permanecer.

buen punto, estoy de acuerdo.

Estoy de acuerdo en que los corchetes se ven y se leen bien, pero sí, tenemos que ceñirnos a la sintaxis que ya hemos elegido.

Pulgar hacia arriba para extender la sintaxis (N), se siente más como CSS natural, la misma razón que @agatronic

Extender mixins no es una mala idea. No estoy seguro de la sintaxis de ejemplo, @jonschlinkert. No es que no me guste; En realidad, no entiendo lo que ha escrito.

Creo que lo que quieres decir es que quieres definir clases que "incorporen" el mismo contenido de mezcla, pero que en realidad no se repitan en el CSS resultante. No llamaría a eso extender mixins. Es decir, no está alterando la definición de mezcla (de la misma manera que la definición extendida lo haría con los selectores), en realidad está alterando (extendiendo) las clases resultantes.

Entonces, corríjame si me equivoco, pero su ejemplo de barra de navegación / banner / menú desplegable no sería compatible con:

.navbar {
  .transition(opacity .2s linear);
}
.banner {
  .transition(opacity .3s linear);
}
.dropdown:extend(.banner) { }

Es decir, ¿extender las clases como lo haría normalmente? Solo estoy tratando de entender su patrón de uso, y el uso de extender para mixins parece estar en desacuerdo con su uso y nomenclatura para extender selectores. ¿Puede proporcionar más detalles sobre por qué necesitaría / querría hacer referencia al mixin en una llamada extendida y no extender un selector que hiciera referencia al mixin?

Asi es como lo consigo

SALIDA CSS FINAL DESEADA

.sometingShared,
.anotherClass,
.anotherYetClass,
.yetClass {
    // amount of shared code here
}

.anotherClass,
.anotherYetClass {
    // did something dynamic with a
}

.yetClass {
    // did something dynamic with b
}

.anotherClass {
    // native another class code
}

.anotherYetClass {
    // native another yet class code
}

.yetClass {
    // native yet class code
}

EL CAMINO QUE TIENE QUE IR CON LA VERSIÓN ACTUAL DE MENOS PARA OBTENER EL PRODUCTO DESEADO

.somethingShared,
.anotherClass,
.anotherYetClass,
.yetClass {
    // amount of shared code here
}

.someMixin(@val) {
    // do something dynamic with val
}

.anotherClass,
.anotherYetClass {
    .someMixin(a);
}

.yetClass {
    .someMixin(b);
}

.anotherClass {
    // native another class code
}

.anotherYetClass {
    // native another yet class code
}

.yetClass {
    // native yet class code
}

MENOS SINTAXIS SUGERIDA

.somethingShared {
    // amount of shared code here
}

.someMixin(@val) {
    // do something dynamic with val
}

.anotherClass:extend(.sometingShared, .someMixin(a)) {
    // native another class code
}

.anotherYetClass:extend(.sometingShared, .someMixin(a)) {
    // native another yet class code
}

.yetClass:extend(.sometingShared, .someMixin(b)) {
    // native yet class code
}

Si bien las extensiones pueden ser útiles solo cuando tiene una gran cantidad de código compartido, en otros casos, el uso ordinario de mixins tiene el favor.

Y solo un poco, muestra ficticia en vivo, destinada solo a jugar alrededor

http://jsbin.com/opekon/1/edit
http://jsbin.com/opekon/2/edit
http://jsbin.com/opekon/3/edit
http://jsbin.com/opekon/4/edit

como se dijo, podría haber un aumento de rendimiento en ciertas circunstancias para las personas que son perezosas como yo :) para optimizar el código MENOS solo porque se ve afectado una mayor flexibilidad

Aquí hay una buena publicación de blog sobre extensiones que cubre varias cosas con respecto a cómo SASS maneja las extensiones, y probablemente sea prudente que aprendamos de cómo otros han hecho esto. http://designshack.net/articles/css/semantic-grid-class-naming-with-placeholder-selectors-in-sass-3-2/

En particular, creo que mi propuesta para extender mixins esencialmente lograría el mismo resultado final que los "marcadores de posición" de SASS, pero sin tener que crear clases de solo marcadores de posición superfluas e inútiles.

EDITAR: sí, aquí hay otra publicación que resume muy bien los marcadores de posición. Es exactamente lo que propongo con la ampliación de mixins http://maximilianhoffmann.com/article/placeholder-selectors

Personalmente, preferiría esto por encima de todas las demás funciones relacionadas con las extensiones. Sin duda. Esta es una declaración contundente, pero creo que no estoy haciendo un buen trabajo explicándola si los demás no están de acuerdo. Esto es algo bastante poderoso.

Siento que SASS

 %tile {
  width: 200px;
  height: 200px;
  margin-right: 20px;
}

es igual al mixin paramétrico, diseñado para se extiende exclusivamente, lo que probablemente no sea tan malo en cuanto a separación de preocupaciones. pero sí, eso es CSS, ¿y no se supone que sea lo más simple posible?

@agatronic mientras hablamos, ¿qué se supone que es esta extensión https://github.com/agatronic/less.js/blob/master/lib/less/tree/extend.js ? señaló que ya está en la rama principal menos. Lo siento por la pregunta de novato.

@ dmi3y es la primera versión de extender que se extrajo de una solicitud de extracción lista para 1.4.0; representa el nodo de extensión

gracias @agatronic , ahora veo cuanto me perdí;)

@ dmi3y, por favor, no dude en continuar agregando a la conversación, intentemos mantener este problema en un nivel más alto para que podamos llegar a una conclusión. También siéntase libre de enviarme un correo electrónico personalmente, estoy feliz de discutir cómo mixins y extiende el trabajo con usted (mi información de contacto está en mi perfil). También un comentario rápido para evitar más confusión en este hilo. Tu ejemplo:

%tile {
    width: 200px;
    height: 200px;
    margin-right: 20px;
}

Esta es la sintaxis de un "marcador de posición" SCSS, que se implementó en la especificación SCSS para lograr algo similar a lo que propongo con la extensión de mixins. Pero esto no tiene nada que ver con ser paramétrico. Los mixins paramétricos son simplemente _mixins que aceptan parámetros_, lo que significa que sus valores pueden cambiar cada vez que se utilizan.

@matthewdl

Creo que lo que quieres decir es que quieres definir clases que "incorporen" el mismo contenido de mezcla, pero que en realidad no se repitan en el CSS resultante.

y

¿No sería compatible su ejemplo de barra de navegación / banner / menú desplegable con ...

No, se está perdiendo el punto operativo, es al revés. Tal vez la confusión se debió a que cometí el error de centrarme en mixins paramétricos en mi ejemplo.

Entonces, primero, creo que es importante delinear que no todos los mixins son paramétricos, muchos se crean para _no_ aceptar parámetros. Algunos mixins, como clearfix, se utilizan una y otra vez sin cambiar ninguna variable cuando se utilizan. Este es un caso de uso perfecto de por qué sería ventajoso extender mixins.

Paramétrico o no, en todo su esplendor, los mixins tienen la desventaja de que cada vez que se usa uno, sus propiedades se duplican . Así que déjame intentar explicar cómo funcionaría la extensión de mixins usando solo "mixins regulares", y continuando con el ejemplo que usaste anteriormente.

Dado su ejemplo, hay dos puntos completamente independientes y no relacionados que deben hacerse:

  1. la clase de banner seguiría apareciendo en el CSS compilado si se extendió o no, pero si la clase de banner fuera una combinación, solo se mostraría en el CSS resultante si se usaba (extendido o mezclado). Esto solo es valioso. Y
  2. Cuando _extenderá un mixin_, en lugar de duplicar las mismas propiedades exactas una y otra vez, copiaríamos los selectores reales en el lugar del mixin.

Pero este es solo un ejemplo. Considere que en un momento en Twitter Bootstrap, el mixin .clearfix() solo se usó más de 20 veces dentro de otros selectores, Y también se anidó dentro de otros 4 o 5 mixins estructurales, como .container-fixed() , .make-row() y #grid > .core() . Lo que significa que esos mixins _también_ duplicaban las propiedades del clearfix mixin cada vez que se usaban. Y esto no es exclusivo de ese marco.

¿Tiene esto más sentido? Entonces, en lugar de tener las propiedades de clearfix mixin duplicadas más de 20 veces, agruparíamos los selectores que usan clearfix mixin en el lugar del mixin en sí, y las propiedades solo se declararían una vez . Y nuevamente, esta es solo una combinación, imagine el beneficio neto de extender la pérdida de mezclas regulares, en comparación con la duplicación de sus propiedades. Como mencioné en alguna parte anteriormente, los mixins regulares aún deberán usarse sin extenderse a veces, por especificidad y anulaciones, pero eso no disminuye el valor de extender los que no lo hacen. De hecho, personalmente crearía mixins adicionales para usar específicamente con extender, que no usaría de otra manera.

Y mi segundo ejemplo anterior se centró en cómo extender funcionaría con mixins paramétricos, así que espero que esto complete la imagen y tenga más sentido ahora. De lo contrario, los artículos a los que he vinculado anteriormente deberían aclarar cualquier confusión. Extender mixins es extremadamente poderoso y útil y le permitiría lograr el mismo resultado neto que extender selectores anidados, pero con mixins específicamente en lugar de cualquier selector anidado. Esto le permite organizar sus selectores de la manera que es más probable que proporcione los resultados que desea y evitar consecuencias no deseadas. @DesignByOnyx , @agatronic , @matthewdl , ¿hay algo que me esté perdiendo u olvidado aquí? ¿Hay algo que podamos hacer para aclarar la confusión?

Gracias. Creo que entiendo el caso de uso y creo que esta línea lo dice mejor:

la clase de banner era una combinación, solo se mostraría en el CSS resultante si se usaba (ya sea extendida o combinada)

Eso tiene sentido para mi. Probablemente lo que me está colgando es que la sintaxis general :extend aún no es definitiva. Pero haces casos persuasivos.

Yo diría que una vez que finalizamos para los bloques selectores, si el comportamiento de extender mixins termina coincidiendo con el comportamiento de extender selectores (con la diferencia clave siendo esa línea que acaba de decir, no se genera ningún selector en el CSS para un extendido A MENOS QUE haya un uso inicial), entonces eso es intuitivo para mí.

Es decir, si también pudiera hacer algo como esto (o una sintaxis equivalente):

.facebook-button:extend( .button() all ) {
    border: 1px solid #e5e5e5;
}

... luego me levanto el pulgar. Pero, para mí, todo eso depende de qué / cómo / si resolvemos :extend para los selectores. Pero, dejando de lado la sintaxis, como idea característica, tienes razón, es buena.

@jonschlinkert gracias, agradezco mucho su apoyo y seguramente haré todo lo posible para expresar mis pensamientos con la mayor claridad posible. Creo que es muy emocionante escuchar lo que está sucediendo con el desarrollo futuro y sí, ser escuchado. Todos ustedes, hagan un trabajo increíble con eso.

Sí, este ejemplo, tuve que ser explícito con mi publicación anterior.

%tile {
   width: 200px;
   height: 200px;
   margin-right: 20px;
 }

se toma de los tutoriales de SASS proporcionados por Jon, y su objetivo principal es evitar la destrucción de la salida en CSS de las clases que no estarían en uso. Entonces, en este ángulo en particular, podría verse como una mezcla paramétrica vacía en MENOS. Cuando desee utilizarlo pero no desee que se imprima en la hoja de estilo final.

Me meto en esta discusión y me gustaría aclarar el siguiente comentario:

si la clase de banner fuera una mezcla, solo se mostraría en el CSS resultante si se usaba (ya sea extendida o mezclada)

Entonces, yendo con un ejemplo de clearfix más genérico, ¿es este el MENOS y el CSS resultante ?:

.clearfix() {
    &:before,
    &:after { content: " "; display: table; }

    &:after { clear: both; }
}
.something:extend( .clearfix() ) { }

/*
.clearfix:before,
.clearfix:after,
.something:before,
.something:after {
    content: " ";
    display: table;
}
.clearfix:after,
.something:after {
    clear: both;
}
*/

Originalmente esperaba que la clase .clearfix permaneciera omitida del CSS compilado. Personalmente, no _necesitaría_ la clase en el CSS compilado, ya que no la usaría en el marcado y son bytes adicionales en mi CSS. Realmente no tengo una opinión sólida de ninguna manera, pero una aclaración sobre este punto me ayudaría a hacer mejores comentarios en el futuro. Gracias.

¿Es este el ... CSS resultante ?:

Me alegro de que lo preguntes, pero no , solo la clase .something aparecerá en el CSS resultante. Así que tenías razón en tu expectativa original.

solo lea el enlace de marcadores de posición y sí, creo que extender mixins es una forma mejor y más fácil de hacer las cosas y obtener la misma funcionalidad.

Para calibrar su punto anterior

.clearfix() {
    &:before,
    &:after { content: " "; display: table; }
    &:after { clear: both; }
}
.something:extend( .clearfix() ) { }

/*
.something:before,
.something:after {
    content: " ";
    display: table;
}
.something:after {
    clear: both;
}
*/

y presumiblemente si la definición de .clearfix() { es .clearfix { entonces llamarlo con o sin corchetes dentro de la definición extendida no hará ninguna diferencia en la salida.

El uso de sintaxis de pseudoclase para extender la función es totalmente INCORRECTO,
debido a que "extender sth" NO es igual a "coincidir con algo", no significa nada sobre la estructura DOM que un selector debería.

Ustedes MENOS chicos han "inventado" muchas malas ideas. El más famoso es "reutilizar" .xxx (selector de clases) como notación mixin. Al menos facilita la migración de CSS simple al preprocesador. Pero: extender la sintaxis es la peor idea que he escuchado.

No quiero dignificar este tipo de perorata sobre nuestros problemas, pero esta no es la primera vez que escucho estas cosas, así que hablemos de CSS y aclaremos las cosas.

Ustedes MENOS chicos han "inventado" muchas malas ideas. El más famoso es "reutilizar" .xxx (selector de clases) como notación mixin ...: extender la sintaxis es la peor idea que he escuchado.

.xxx se denomina mixin implícito. Funciona y es fácil de entender. De hecho, esta sintaxis no es tan "invasiva" en la especificación CSS como, por ejemplo, el uso de reglas at para aplicar estilos a real. @keyframes acercan más a lo que se describiría como estilo y _quizá_ podría considerarse una excepción a lo que estoy diciendo, ya que se utilizan identificadores que coinciden con la producción de identificadores en la sintaxis CSS. Más allá de los fotogramas clave, en general, las reglas at de CSS se reservan principalmente para la configuración de nivel superior y la manipulación de estilos o hojas de estilo en función de información "externa", es decir, fuera de los estilos mismos, como la codificación de caracteres ( @charset ), o respondiendo a condiciones específicas del dispositivo ( @media ).

Además, puedo pensar en peores ideas. Al igual que usar reglas at para el estilo es una de ellas, usar dos reglas at para la misma característica es otra. Por supuesto, todo depende de sus objetivos, si desea manipular estilos mediante programación sin tocarlos personalmente, entonces probablemente haya ventajas en el uso de construcciones gramaticales más obtusas y obvias que podrían ser más fáciles de captar para un analizador sintáctico. Parece que usa Stylus, así que me interesa escuchar su punto de vista sobre por qué otras sintaxis son ventajosas.

"extender sth" NO es igual a "coincidir con sth", no significa nada sobre la estructura DOM que un selector debería.

Correcto. Las pseudoclases con nth _algo_ se describen como pseudoclases " estructurales " por la especificación CSS. Sin embargo, hay otros 6 tipos de pseudoclases: "dinámica", "negación", "destino", "en blanco", "estados de elementos de la interfaz de usuario" e "idioma". Si la especificación CSS de hecho describiera una característica de "extensión", podría ubicarse con bastante elegancia como una categoría entre las pseudoclases de "negación" y "objetivo".

Las pseudoclases permiten la selección basada en la información del árbol del documento, pero probablemente este no sea un uso óptimo de la función de extensión.

Completamente equivocado

Una comunidad que es más grande que todos los demás preprocesadores combinados no puede estar equivocada. ¿Qué más hay que decir?

@hax : el trolling sin sentido podría convertirse en una discusión educada si :extend . Después de semanas de diferentes sugerencias y deliberaciones entre desarrolladores front-end muy experimentados y usuarios habituales de LESS, llegamos a una solución satisfactoria con la sintaxis :extend . Si tiene una sugerencia mejor, créame, todos somos oídos.

Para agregar a @jonschlinkert , .this:not(.that) { } y .this:matches(.that) { } y .this:extend(.that) { } son categóricamente similares. Es decir: "Dado el selector 'esto', relacionarlo con el selector 'eso' de una manera particular". Dado que LESS a menudo amplía los conceptos y la sintaxis introducidos en CSS, es una extensión bastante lógica del lenguaje. Prestamos mucha atención a la especificación CSS y, como resultado, reflejamos sus idiosincrasias. Si hay algo extraño en el concepto, es de esperar que comience primero en CSS. Es por eso que en nuestros guardias mixin, "Y" está representado por la palabra "y", y "O" está representado por una coma: porque así es en las consultas de medios. Nuestro objetivo no es arreglar o cambiar CSS, sino hacer que CSS sea mucho más fácil de trabajar y hacer que LESS sea completamente familiar para los autores de CSS. :extend es un ejemplo de eso. Si sabe cómo usar :not , sabe cómo usar :extend .

¿Qué pasaría si usáramos una sintaxis más "implícita" para esto para evitar anidar parens y facilitar la extensión de mixins paramétricos?

Hoy, usamos una mezcla paramétrica como esta:

.square {
  .border-radius(9px);
}

En lugar de extender el mixin de esta manera (como podría extender una clase normal):

.square {
  &:extend(.border-radius);
}

Podríamos extendernos así:

.box {
  .border-radius:extend(9px);
}
.square {
  .border-radius:extend(9px);
}
.rectangle {
  .border-radius:extend(4px);
}

La distinción es que la "mezcla extendida" termina en un punto y coma y declara un valor o valores dentro de los paréntesis, .border-radius:extend(9px); , en lugar de enumerar las clases para extender dentro de los paréntesis y comenzar un nuevo bloque selector con llaves, .border-radius:extend(.some-class) {} . En mi humilde opinión, esto no es menos sutil que las mezclas implícitas ( .border-radius; ), que es una de las características más interesantes de LESS, de nuevo en mi humilde opinión.

En la salida renderizada, cualquier "mezcla paramétrica extendida" se renderizaría en el lugar de la mezcla original, así:

.box, 
.square {
    -webkit-border-radius: 9px;
    -moz-border-radius: 9px;
    border-radius: 9px;
}
.rectangle {
    -webkit-border-radius: 4px;
    -moz-border-radius: 4px;
    border-radius: 4px;
}
.some-other-class, 
.another-class, 
.and-another {
    -webkit-border-radius: 2px;
    -moz-border-radius: 2px;
    border-radius: 2px;
}

Así que personalmente me gusta esto porque es una desviación suficiente de la sintaxis de extensión "normal" dentro de los bloques selectores para que sea lo suficientemente obvio lo que está sucediendo, y va de la mano con la sutileza de las menos convenciones existentes donde no hay necesidad de explicar demasiado qué que está tratando de lograr en el código. Esta característica está definitivamente en la parte superior de mi lista de deseos personal.

Usando el ejemplo de clearfix que di en mi solicitud original, así es como se vería con mi sintaxis revisada:

.clearfix() {
    // ...
}
.navbar {
    .clearfix:extend(); // instead of &:extend(.clearfix());
}
.banner {
    .clearfix:extend();
    &:extend(.some-class); // "implicit mixin" being extended
}

Me gusta a dónde vas con esto. Creo que un enfoque más amigable es usar un :extend al final de la sintaxis mixin _existing_ como tal:

.box {
  .border-radius(9px):extend;
}
.square {
  .border-radius(9px):extend;
}
.rectangle {
  .border-radius(4px):extend;
}

Algo acerca de omitir los parens después de :extend hace que parezca que tiene un propósito diferente al de la sintaxis de extensión existente.

Podría ir de cualquier manera con esto, pero prefiero .border-radius:extend(9px); porque es consistente con la sintaxis de extensión, IMO todavía es obvio que es una mezcla, pero también implica que los parámetros / valores se están extendiendo, lo que ayudará a explicar por qué la salida está "agrupada".

@jonschlinkert : en este punto, tengo en muy alta estima sus opiniones y apoyaré cualquier decisión que crea que es la mejor. Diré que su método se siente como si los 9px se pasaran a "extender" en lugar de pasar a la mezcla en sí ... pero estoy de acuerdo con cualquiera de los dos.

@DesignByOnyx gracias por las amables palabras. Lo que estás diciendo tiene mucho sentido, mi "lente" de extensiones (en Menos) ha sido algo como:

.this:extend(.that) {}

entonces tu punto es consistente con mi propio punto de vista. @matthewdl o @lukeapage, ¿alguno de ustedes tiene alguna opinión sobre esto? Creo que ambas sintaxis podrían funcionar (y probablemente otras), pero es cierto que no me he centrado en la "prueba de futuro" con ninguna de las sintaxis, por lo que podría haber algunos errores en cualquiera de ellas. Me encantaría ver que esto suceda, creo que extender mixins es una característica emocionante para Less, hará más para generar código DRY que cualquier otra característica que se me ocurra en este momento.

¿Por qué el compilador Less no puede "hacer lo correcto" automáticamente? En otras palabras, si tengo este mixin declarado en mi código:

.someMixin {
    color: red;
}

Y luego lo uso así:

#someElement {
    .someMixin;
}

¿Por qué el compilador no puede ser lo suficientemente inteligente como para optimizar este código Less en este CSS?

.someMixin,
#someElement
{
    color:red;
}

¿Por qué debería yo, como usuario, tener que agregar manualmente una palabra clave: extiende para obtener este comportamiento? El compilador debe ser lo suficientemente inteligente como para darse cuenta de que esta optimización se puede realizar y luego hacerlo.

Personalmente, creo que esto: la idea extendida es confusa. Toda la noción de una palabra clave "extiende" significa: "Toma esta cosa X y agrégale A, B y C". Pero en este contexto, propone redefinir la extensión a: "Esta cosa X es en realidad lo mismo que Y, por lo que puede declarar que Y y X son iguales y escribirlo una vez". Esto va en contra de la noción estándar de "extender" algo.

Sí, estaba pensando exactamente lo mismo antes y lo iba a publicar, pero después de pensarlo, decidí que aplicar automáticamente "comportamiento extendido" a los mixins es demasiado obstinado para Less.js. Específicamente, aunque la herencia del selector (extender) es un concepto asombroso que es muy beneficioso para la reducción de código, la gran mayoría de las quejas que he leído sobre la función es que agrega una capa de abstracción que hace que sea difícil revisar el código. y depurar cuando haya problemas.

Así que las grandes mentes piensan igual, pero yo personalmente rechazo la idea porque a) no deberíamos jugar con los mixins "normales" hasta que la función extend sea ​​completamente estable y la especificación sea más completa, b) Creo que muchos desarrolladores quieren hacer esta llamada por sí mismos, yc) muchas veces las cosas parecen tan obvias y sencillas, cuando el hecho es que nos estamos olvidando de muchas de las excentricidades de los mixins que harían que tu sugerencia difícil de implementar como mínimo, y probablemente imposible de implementar al tiempo que permite a los desarrolladores usar todos los "trucos de mezcla" que hemos ... ejem, que han llegado a conocer y amar.

La sintaxis: extended () sigue siendo un truco bastante torpe que no es intuitivo y difícil de explicar a los nuevos usuarios.

La mejor solución es simplemente hacer que el compilador optimice automáticamente el CSS como se describe arriba cuando el usuario ha seleccionado un estilo de salida apropiado (comprimido, optimizado, etc.). Si el usuario selecciona el estilo de salida sin comprimir, el compilador debería evitar estas optimizaciones y generar menos código DRY.

Además, puede resolver las dificultades de depuración con mapas de origen. Pueden señalar fácilmente la ubicación del CSS compilado que proviene de un mixin Less.

@bdkjones , cree una nueva solicitud de función para "optimizar automáticamente el CSS" con sus sugerencias sobre cómo lograr esto en el código. Este tipo de aportación siempre es bienvenida.

¡Punto a favor! No quise ser tan duro en mi último comentario; A veces me dejo llevar.

En cuanto al código, me temo que estoy totalmente ocupado con CodeKit. ¡Les dejé discutir los idiomas!

¡Para nada! De verdad, vi que está involucrado con CodeKit, me encantaría contar con sus aportes continuos. No todas las funciones van a complacer a todos, pero los comentarios y las opiniones sólidas son las únicas cosas que hacen que las ruedas sigan girando.

@bdkjones El problema es la cascada. En su caso de uso, funciona, pero la agrupación de selectores no tendría el resultado deseado en todos los casos, ya que posiblemente movería los selectores "antes" en el documento evitando declaraciones que sobrescribieran esos selectores.

Pero estoy de acuerdo con sus afirmaciones en contra de la sintaxis de extensión mixin tal como ha evolucionado aquí. Selector X debería extender Selector o mezclar Y, por lo que esto parece extraño:

.border-radius(9px):extend;

Creo que estamos haciendo un mal uso de la sintaxis de extensión. Si la sintaxis de extensión tal como existe no encaja con los mixins (lo cual es perfectamente plausible), sugiero que encontremos la sintaxis correcta para los mixins, en lugar de expandir la sintaxis de extensión de una manera que altere la metáfora, como señala @bdkjones fuera.

Creo que estamos haciendo un mal uso de la sintaxis de extensión.

Estoy en desacuerdo. Si funciona, úselo. ¿Por qué crear nuevas sintaxis sin ningún motivo? Creo que tenemos un gran precedente para la sintaxis propuesta, doy abundantes ejemplos y razones de apoyo detrás de mis sugerencias, pero su opinión sobre las sintaxis propuestas parece muy subjetiva. Y dado que ha hecho esa afirmación un par de veces recientemente, ¿puede explicar por qué cree que se está abusando de la sintaxis? ¿O explicar en qué punto se abusa de una sintaxis? ¿O comparte tus pensamientos sobre cómo deberían extenderse los mixins, pero sin la sintaxis "extender"?


En su caso de uso, funciona, pero la agrupación de selectores no tendría el resultado deseado en todos los casos, ya que posiblemente movería los selectores "antes" en el documento evitando declaraciones que sobrescribieran esos selectores.
...
Creo que estamos haciendo un mal uso de la sintaxis de extensión. Si la sintaxis de extensión tal como existe no encaja con los mixins (lo cual es perfectamente plausible), sugiero que encontremos la sintaxis correcta para los mixins, en lugar de expandir la sintaxis de extensión de una manera que altere la metáfora, como señala bdkjones. .

No. No señaló nada, nos instó a hacer que Less sea más fácil de usar, ese era su resultado final. La forma que sugirió de hacerlo estaba equivocada, pero la intención era buena. En lo que no estaba pensando es en la cascada que acabas de señalar. Al usar extender en general debes tener en cuenta la cascada. Creo que cualquiera que use extender en lugar de un mixin lo sabe. Por lo tanto, es por eso que Less.js le ofrece la opción de usarlo cuando tiene sentido o _no_ cuando no lo tiene. El hecho de que la primera "C" en CSS sea sinónimo de cascada no niega la ventaja de consolidar estilos duplicados cuando la cascada no es material. ¿Que me estoy perdiendo aqui?

Entonces, ¿puedes aclarar tu sentimiento? ¿Está en contra de esta característica o de la sintaxis? Si está en contra de la sintaxis, proponga algo más para mantener las cosas en movimiento; de lo contrario, no obstaculicemos el progreso de una característica que es tan prometedora para el lenguaje.

¿Está en contra de esta característica o de la sintaxis?

Estoy a favor de la función, absolutamente. Esta es una dirección obvia. Revisé la sintaxis nuevamente en este hilo. Algunos pensamientos:

Primero, esto me resulta incómodo:

.something:extend( .clearfix() ) { }

Los dobles paréntesis son raros. Pero, es una adopción fiel de la sintaxis de extensión existente, por lo que es bastante justa. Entonces, es por eso que abogaba por algo más, tal vez algo más que extender.

Luego está esto que propusiste, creo que por razones similares:

.border-radius(9px):extend;

... al que tuve una reacción alérgica, porque parece contrario a las especificaciones extendidas existentes. Así que ahí es donde me pareció un mal uso.

PERO

Me di cuenta de que en realidad hay dos opciones allí. Una es que hacemos algo diferente para los mixins. Pero la otra opción es que revisemos la especificación de extensión existente, para todas las cosas, incluidos los mixins, como:

#namespace {
  .box-template {
    .subelement {
      // we'll add the all flag to extend everything here
    }
  }
}
.clearfix() {
  // a clearfix mixin
}
.text-shadow(@shadow) {
  -moz-text-shadow: @shadow;
  text-shadow: @shadow;
}
.some .random .selector {
  // with properties
}
.mybox {
  .clearfix:extend;
  #namespace > .box-template:extend !all;
  .text-shadow:extend(2px 2px #ff0000);
  .some .random .selector:extend;
}

Pero .... con un selector completo ( .some .random .selector ), comienza a leer mal. Parece que solo .selector tiene la extensión. Y la palabra "extender" comienza a perderse, cuando es la palabra importante en esta declaración. Este no fue el caso cuando se escribió como &:extend() (porque apareció al principio), pero esa sintaxis parece romperse con los mixins.

Entonces, propondría una de estas opciones:

// Migrating existing syntax, but ommitting a parens requirement when used with &:

.mybox {
  &:extend .clearfix;
  &:extend #namespace > .box-template !all;
  &:extend .text-shadow(2px 2px #ff0000);
  &:extend .some .random .selector;
}

// Adopting something similar to the SASS approach

.mybox {
  <strong i="24">@extend</strong> .clearfix;
  <strong i="25">@extend</strong> #namespace > .box-template !all;
  <strong i="26">@extend</strong> .text-shadow(2px 2px #ff0000);
  <strong i="27">@extend</strong> .some .random .selector;
}

Creo que la discusión sobre la extensión de mixins y media queries ha resaltado que nuestro enfoque de sintaxis original para :extend no es tan flexible, especialmente cuando queremos extender múltiples selectores y mixins.

Creo que es importante conseguir: extender bien. Si queremos usar "extender" para mixins, entonces creo que tenemos que revisar la sintaxis de extender.

No propuse .border-radius(9px):extend; , lo hizo .border-radius:extend(9px);

Pero cualquier sintaxis está bien para mí. O podríamos hacer .border-radius(9px) !extend; o .border-radius:shamallamadingdongscoobiedoo(9px):extendmyass (jk), no me importa porque nada cambia con el comportamiento de los mixins o extendidos en absoluto.

Así que no estoy seguro de cómo se te ocurrió la necesidad de hacer todo eso, probablemente te estés complicando demasiado las cosas.

Esta solicitud de función se trata expresamente de tener la capacidad de copiar las propiedades heredadas de un mixin _en el lugar del mixin_, y seguirá reglas que ya han sido bien establecidas con el comportamiento actual de mixin, y ahora también tienen precedencia y comportamiento idéntico a la función <strong i="14">@import</strong> (reference) (que, por cierto, he estado usando bastante en la práctica y me encanta). En una palabra:

  • Cuando usa un mixin, sus propiedades se copian en el lugar del selector que llama al mixin.
  • Cuando usa extender, el selector _extending_ se copia en el lugar de la clase _extended_.
  • Por lo tanto, cuando extiendes un mixin, el selector de llamadas se copia al lugar del mixin.

No estoy seguro de por qué incluso quiere repetir el debate sobre la sintaxis para extenderlo después de dos años de debate,> 100 publicaciones, mucha investigación y ya se ha argumentado que es _mucho más_ flexible que @extend .

Por cierto, no estoy seguro de a qué te refieres aquí:

con un selector completo (.algunos .selector aleatorio), comienza a leer mal. Parece que solo .selector tiene la extensión. Y la palabra "extender" comienza a perderse, cuando es la palabra importante en esta declaración.

No estoy de acuerdo en que sea confuso, ya que así es como funciona ahora. ¿No es como decir "los desarrolladores de CSS no saben cómo funcionan los selectores agrupados"? ¿Qué pasa con :hover o :after ? Creo que los desarrolladores de CSS pueden resolver esto bien, porque funciona de la misma manera que otros pseduos.

.some .random .selector:extend(.something) {}

Me gusta la flexibilidad que esto brinda, ya que puedo aplicar una extensión (o ambas) al selector, que es .some .random .selector , no .selector , o puedo colocarlo dentro del bloque selector.

Creo que la discusión sobre la extensión de mixins y media queries

Cerré el problema de las consultas de medios porque me di cuenta de que podría resolverse extendiendo mixins. "Todos los caminos conducen a _____" extendiendo mixins. ;-)

Me gustaría agregar mis dos centavos y decir que los parens dentro de un parens - :extend( .some-mixin() ) - realmente no me molestan tanto, especialmente porque :extend( .some-selector ) ya está establecido y se ha discutido hasta la saciedad. Estoy de acuerdo en que el doble parens no es ideal de ninguna manera y se siente un poco extraño. Pero creo que es importante que los mixins y los selectores se traten de la misma manera en términos de "extensión", de la misma manera que se tratan de la misma manera en el clásico Less:

header {
    .some-selector;
    .some-mixin;
    .some-mixin();
}

Como tal, realmente no me siento tan mal (o limitado) al hacer esto:

header {
    &:extend( .some-selector );
    &:extend( .some-mixin );
    &:extend( .some-mixin() );
}

Pero creo que es importante que los mixins y los selectores se traten de la misma manera en términos de "extensión", de la misma manera que se tratan de la misma manera en el clásico Less

Estoy en la misma página en ese punto.

No estoy seguro de por qué incluso quiere repetir el debate sobre la sintaxis para extenderlo después de dos años de debate,> 100 publicaciones

No es cuestión de querer. No, no quiero. Sin embargo, en ese momento, de alguna manera cambiamos los mixins para tratarlos más tarde. Solo quiero hacer la pregunta si estamos seguros de que esta sintaxis funciona de la manera que queremos que funcione para todo. No hay nada de malo en volver a examinar la pregunta si creemos que no funciona o que no es elegante para algunos usos. LESS existe desde hace mucho tiempo sin extenderse. Es más importante hacerlo bien que hacerlo rápidamente.

Entonces, ¿estamos bien con esto?

.mybox {
  &:extend(.clearfix());
  &:extend(#namespace > .box-template all);
  &:extend(.text-shadow(2px 2px #ff0000));
  &:extend(.some .random .selector);
}

parens dentro de un parens -: extend (.some-mixin ()) - realmente no me molesta mucho, especialmente porque: extend (.some-selector) ya está establecido

Sí, es cierto, y de hecho, ya tenemos un precedente para los pares dobles en Less.js, Y con la sintaxis extendida existente. Y el precedente que ya se ha sentado no es tan agradable a la vista como lo que estamos sugiriendo con los mixins. Actualmente, podemos hacer esto:

.one:nth-child(5) {
  color: red;
}
// We can extend psuedos
.two:extend(.one:nth-child(5)) {
  background: blue;
}
// And attributes
.two:extend(.one, [hidden]) {
  width: 2px;
}

Incluso encontrará paréntesis anidados en la sintaxis CSS existente .

Así que aquí tenemos sintaxis _pares anidados_ y _pseudoclase anidada_. Y no tengo ningún problema con eso, está claro en mi opinión.

Así que estoy de acuerdo con @DesignByOnyx , esa era mi propuesta original y parecía desagradable para otros por alguna razón, así que estaba tratando de encontrar otra sintaxis. Pero estoy a favor de usar la sintaxis mixin antigua normal dentro de los paréntesis de la extensión.

De hecho, la sintaxis original permitiría extender múltiples clases o mixins separados por comas.

.banner {
    &:extend(.clearfix(), .border-radius(4px), .alert, .navbar-fixed-top, [hidden]); 
}

Hace el trabajo y es ajustado. No tengo quejas aquí.

Entonces, ¿estamos bien con esto?

sí. completamente. Eso ya es así en CSS. Así que estoy bien con eso.

sí. completamente. Eso ya es así en CSS. Así que estoy bien con eso.

ASÍ DEBERÁ PASAR.

Pregunta, no creo que actualmente tengamos soporte para múltiples selectores en: extender, así que me pregunto dónde encajaría la palabra clave "todos" en ese formato, pero eso probablemente debería ser parte de un problema separado.

Ha presentado su caso, Sr. Schlinkert. Deberías haberte convertido en abogado. ;)

No creo que actualmente tengamos soporte para múltiples selectores en: extender

Pero lo hacemos ;-) Lo he hecho mucho. Acabo de hacer esto antes:

.global-nav {
  // Extend and override bootstrap styles
  &:extend(.navbar, .navbar-fixed-top all, .navbar-inverse); // this works, and it's pretty handy
  &.hidden:extend(.navbar.hidden) {}
  &.visible:extend(.navbar.visible) {}
  &:hover {
    background: lighten(@brand-primary, 5%);
  }
  .navbar-brand {
    padding-left: 20px; 
  }
  .navbar-nav > .active > a {
    &, &:hover, &:focus {
      background-color: darken(@brand-primary, 5%);      
    }
  }
}

Ha presentado su caso, Sr. Schlinkert. Deberías haberte convertido en abogado. ;)

Pfft, jajaja, ¡detente!

Solo quiero agregar que creo que esta sintaxis:

.foo {
  &:extend( .bar() );
}

es genial. No encuentro los paréntesis incómodos en absoluto.

Pero principalmente solo quiero que se den prisa para poder hacer todas las cosas interesantes en las que estoy trabajando en SASS en mi preprocesador favorito: D

¡Gracias por tus comentarios, @mgerring !

+1 Esperando esta función. Sigan con el buen trabajo :)

A la publicación original:

.clearfixed {
   // stuff
}
.clearfix() {
    &:extend(.clearfixed);
}
.navbar {
  .clearfix();
}
.banner {
  .clearfix();
}

¿Quizás esto no funcionó en el momento de la publicación? Pero resulta en algo muy parecido a lo que querías:

.clearfixed,
.navbar,
.banner {
  // stuff
}

@aaronmw , sí, seguro que su ejemplo hace lo mismo, pero el punto clave de esta propuesta es la capacidad de extender un mixin definido en otro lugar (es decir, cuando no puede o no quiere modificar el mixin en sí, por ejemplo, otro archivo, compartido biblioteca, etc.)

Sí, según el punto de @ seven-phase-max, esto se puede hacer de la manera que usted describe, pero no es idiomático.

Bien, lo siento, he leído mucho más de este hilo ahora y veo a qué apuntamos. La clase "esqueleto" que he usado es simplemente basura en la salida compilada porque la clase .clearfixed nunca sería referenciada explícitamente fuera del mixin. &: extend (.clearfix ()) tiene sentido para mí ahora, y es bastante emocionante. Por ahora, me ocuparé de las clases de esqueleto que ensucian mi CSS.

¡Gran discusión aquí!

: +1:

Entonces, ¿cuándo podemos esperar esta característica? Es muy útil para conceptos como OOCSS para crear construcciones como una "clase abstracta".

  • decidir cómo lidiamos con la anidación / alcance y la mezcla frente a la clase normal, por ejemplo
.a {
  color: green;
}
#thing {
  .a() {
    color: black;
   }
}

.b:extend(#thing .a) {}  //
.b:extend(.a) {}  // and if so is the output wrapped by #thing?
.b:extend(.a()) {}  // do I need special format to say extend only that mixin?
  • manejamos argumentos? ¿Combinamos mixins con los mismos argumentos?
  • cambie a-css-visitor para no eliminar las definiciones de mixin
  • Consiga que el visitante extendido visite las definiciones mixtas y cree un nuevo conjunto de reglas con la nueva clase.

Creo que lo más difícil es decidir _exactamente_ cómo debería funcionar.

decidir cómo lidiamos con la anidación / alcance y la mezcla frente a la clase normal, por ejemplo

Intentaría interpretar la extensión mixin de esta manera:
.b:extend(.a(1, 2, 3)) {} debería comportarse igual que crear un mixin anónimo no paramétrico (es decir, un selector simple) en el alcance de 'b' que llama a .a(1, 2, 3) dentro y luego se extiende de la manera habitual, es decir, esto:

.a(<strong i="11">@a</strong>, <strong i="12">@b</strong>, @c) {
    // ...
}

.b:extend(.a(1, 2, 3)) {}

debería ser igual a esto:

.a(<strong i="16">@a</strong>, <strong i="17">@b</strong>, @c) {
    // ...
}

#__anon_a_1_2_3 {.a(1, 2, 3);}

.b:extend(#__anon_a_1_2_3) {}

excepto que no aparece #__ anon_a_1_2_3 en la salida. Creo que tal enfoque debería hacerlo menos o más sencillo sin inventar reglas especiales.

Entonces, al aplicar el concepto anterior al ejemplo #thing .a obtenemos lo siguiente:

.a {
  color: green;
}
#thing {
  .a() {
    color: black;
   }
}

.b:extend(#thing .a) {} // since we do ignore parens on mixin call and have ...
// no plans changing this (?), it should probably create .b {color: black} 

.b:extend(.a) {}  // there's only one .a in this scope so it's -> .b {color: green}

.b:extend(.a()) {}  // same as above -> .b {color: green}

Por otro lado, los "parens opcionales" son algo menor desde un punto de vista práctico, por lo que también podría estar bien hacerlo más estricto y requerir parens para mixins paramétricos dentro de extend (no hay presión sobre extend para heredar la sintaxis simple de la llamada mixin, ya que de todos modos no será totalmente compatible).

¿Combinamos mixins con los mismos argumentos?

Idealmente sí, de lo contrario hará que todo sea inútil, por ejemplo:

.b:extend(.a()) {}
.c:extend(.a()) {}

debería crear:

.b, .c {color: green}

Mmm, parece que la fusión será lo más difícil de implementar.


Otro problema es el alcance, como surgió recientemente en el n. ° 1730, los mixins usan la ruta de alcance 'relativa' y los usos extendidos 'absolutos', por lo que obtenemos una especie de conflicto al combinar ambos:

.div {color: green}

body {
   .div {color: red}

   p-a       {.div()}    // -> body p-a {color: red}
   p-b:extend(.div)   {} // -> body p-b {color: green}
   p-c:extend(.div()) {} // -> ???
}

Y es aún más confuso si reescribimos este ejemplo con mixins paramétricos.

Me gustaría ofrecer mis dos centavos para decir que este podría ser un buen momento para dar un paso atrás y decir "cómo se deben usar los mixins extendidos", y creo que @donaldpipowitch tiene razón al decir que aporta un poco de capacidad OOCSS . Como tal, no creo que debamos empantanarnos demasiado en cómo las subclases ("propiedades", por así decirlo) se extenderán desde dentro de la propia clase. Entonces, por ejemplo, los usuarios tendrán ciertas "clases" (componentes) con "propiedades" (selectores anidados):

.dog() {
    .leg { ... }
    .ears { ... }
    .fur { ... }
}

No creo que debamos centrarnos en situaciones en las que un usuario querría hacer lo siguiente:

.dog() {
    .leg { ... }
    .ears { ... }
    .fur { ... }
    .tail:extend( .leg() ) { 
        .toes { display:none; } 
    }
}

En mi opinión, no solo es un escenario de caso marginal, sino que el usuario debe escribir sus estilos de esta manera de todos modos:

.dog() {
    .leg, .tail { ... }
    .ears { ... }
    .fur { ... }
    .tail .toes { display:none; }
}

El caso de uso del 99.8% para extender mixins es permitir a los desarrolladores tener sus bibliotecas LESS masivas llenas de estilos que han acumulado a lo largo de los años. Esta enorme biblioteca estará llena de cosas como:

.clearfix() { ... }
.modal() { ... }
.alert-box() { 
    &:extend( .modal() ); 
    &.message { ... } 
    &.warning { ... } 
    &.error { ... } 
}
.grid-wrap() { ... }
.form-input() { ... }
.form-select() { ... }
.button( <strong i="16">@bgColor</strong>, <strong i="17">@textColor</strong> ) { ... }
[... thousands more like this ...]

Y podrían centrarse en estilos de escritura:

.page-wrap:extend( .grid-wrap(), .clearfix() ) { ... }
input[type="text"]:extend( .form-input ) { ... }
textarea:extend( .form-input() );

Incluso podrían hacer esto, si quisieran y ninguno de los estilos "modales" estaría presente en el resultado final porque no se están utilizando en este proyecto:

.inline-error:extend( .alert-box.error )

Sí, siento que @DesignByOnyx tiene razón. No creo que haya nada de malo en descubrir cosas más complejas más adelante. De hecho, creo que por ahora sería mejor implementar la extensión de mixins _sólo no paramétricos_ primero. Eso cubrirá probablemente del 80 al 90% de todos los casos de uso (permitiendo una estructura más orientada a objetos en las hojas de estilo, etc.). Todo lo demás puede esperar un par de parches, en mi opinión.

@DesignByOnyx y @calvinjuarez no podemos resolver esto más tarde ... tiene que estar codificado de una forma u otra. Si buscamos una solución y luego decidimos cambiarla, introducimos cambios importantes, lo cual no es bueno.

si podemos encontrar un enfoque que no admita escenarios marginales, estoy más que feliz, eso es lo que terminamos haciendo con el soporte extendido principal (se puede expandir con más palabras clave, si es necesario), pero necesitamos un plan para lo que se apoya y cómo.

@ seven-phase-max en la línea anterior, estaría feliz de ignorar los mixins paramétricos por ahora.

Mmm, parece que la fusión será lo más difícil de implementar.

  • pero se esta fusionando? Usaría el mismo enfoque que las extensiones existentes, por ejemplo, encuentra una coincidencia y se agrega a ella ... por lo que no se fusiona tanto como poner ambas extensiones en un tercer lugar, el mixin, que luego se genera como un especial caso en su genCSS

También creo que es muy probable que el segundo ejemplo de @ seven-phase-max sobre el alcance afecte a alguien: solo necesita una mezcla y una mezcla paramétrica vacía con el mismo nombre.

@lukeapage : +1: Cierto, puedo cavar eso. Buena llamada.

De hecho, creo que @ seven-phase-max lo ha hecho bien. Entonces: +1: allí también.

@lukeapage - No estaba tratando de defender un tipo de solución "de una forma u otra", sino más bien un enfoque que (como dijiste) no admite casos marginales. De hecho, ya hemos superado la capacidad del alcance "local" y hemos entrado en la fase "demasiado tarde para volver atrás" en mi opinión porque :extend funciona así:

.block { color: green; }

.component {
  .block { color: red; }    
  div:extend( .block ) {};
}

/*
.block,
.component div {
  color: green;
}
.component .block {
  color: red;
}
*/

No veo ninguna razón por la que el siguiente código deba funcionar de manera diferente al anterior, el beneficio es que no hay una clase .block en el resultado final:

.block() { color: green; }

.component {
  .block() { color: red; }  
  div:extend( .block() ) { };
}

/*
.component div {
  color: green;
}
*/

Por cierto, hay una ligera variación en nuestras convenciones de nomenclatura :) por ejemplo, para mí, "mixins paramétricos" significa cualquier mixin definido con parens, incluidos aquellos con 0 parámetros (es decir, .mixin() {} es un "paramétrico"). Y la mezcla "no paramétrica" ​​es simplemente un selector simple (es decir, .mixin {} ). Hasta ahora, supongo que esta deriva no creó ningún malentendido (por ejemplo, en la mayoría de los ejemplos anteriores, estaba claro por el contexto si .mixin() {} se refería como un mixin "no paramétrico"), pero ...
No se pierda que en los documentos un selector simple también se denomina "mixin" (tan pronto como se mezcla) y también es un mixin "no paramétrico" por diseño. Por lo tanto, referirse a .mixin() {} como a un "no paramétrico" únicamente puede ser bastante ambiguo (técnicamente, la diferencia está en la presencia o falta de definición de paréntesis y no en el número de argumentos).
Bien, este era mi habitual boo-boo-boo. :)

@lukeapage

Sería feliz ignorando los mixins paramétricos por ahora.

Es decir, ¿no admite extender para mixins con parámetros distintos de cero? Estoy bien con eso. Solo estaba tratando de estimar cómo se podría implementar (de una manera unificada sin delimitar mixins de parámetros cero y distintos de cero, de modo que no sea un obstáculo cuando / si el último salta eventualmente).

pero se esta fusionando? Usaría el mismo enfoque que las extensiones existentes, por ejemplo, encuentra una coincidencia y la agrega.

Bien, supongo que estaba pensando más en las posibles dificultades con la fusión de extensiones de mixins con argumentos reales: por ejemplo:

.b:extend(.a(1, 2, 3)) {}
.c:extend(.a(1, 2, 3)) {}

Por otro lado, sospecho que también hay sorpresas ocultas con mixins de parámetro cero, por ejemplo:

.a {color: red}
.a {width: 2px}

.b:extend(.a) {}   // creates two `.b` blocks (it is expected since there're two `.a` blocks anyway)

.c {.a}            // creates one `.c` block (OK, this is just how mixins work)

.d() {color: blue}
.d() {width: 10px}

.e {.d()}          // creates one `.e` block (OK, this is just how mixins work)

.f:extend(.d()) {} // tada! another room for complains if this creates two `.f` blocks :)

Bueno, tal vez esto sea demasiado profundo (y también demasiado menor para preocuparnos por ello en este momento).

.f:extend(.d()) {} // tada! another room for complains if this creates two .f blocks :)

Con la idea de que "dado que, en este ejemplo, .d() es paramétrico, no debería crear dos bloques .f ".

Sí, puedo ver su punto, dado que una mezcla resultaría en:

.f {
  color: #0000ff;
  width: 10px;
}

En mi humilde opinión, si tiene sentido hacerlo en pasos, tal vez solo explique eso, pero no _no_ implementaría algo para evitar una queja per se. Por supuesto, este es solo mi 2c. Y si se implementa con el comportamiento que describió, podría, en el momento de agregar la función, también crear una solicitud de función para "fusionar bloques CSS de selectores extendidos", solo para evitar las quejas ...?

pero no implementaría algo para evitar una queja per se.

Estoy absolutamente de acuerdo. Solo estoy tratando de predecir las sorpresas que podrían convertirse en una de esas "demasiado tarde para cambiar" aún más.

: +1: ¡sí, me gusta cómo piensas!

Me gusta que esta discusión aún continúe. Permítanme volver a algunos de los puntos de esta discusión. Primero, en cuanto al uso general, esto ha sido igual.

.mixin {} == .mixin() {}

Con la excepción de que .mixin {} obtiene salida como clase. Sé que en el analizador probablemente se tratan de manera diferente, pero en el uso, eliminan los pares de propiedad / valor.

Sentido:

.mixin1() {
    color: red;    
}
.mixin2 {
    color: blue;
}
.use1 {
    .mixin1;
    foo:bar;
}
.use2 {
    .mixin2;
    foo:bar;
}

Debido a este historial de menos sintaxis, tiene sentido que pueda hacer esto:

.mixin1() {
    color: red;    
}
.mixin2 {
    color: blue;
}
.use1 {
    &:extend(.mixin1);
    foo:bar;
}
.use2 {
    &:extend(.mixin2);
    foo:bar;
}

Para mí, eso no es controvertido, como hemos hablado a menudo: extender como un reemplazo directo de muchas instancias de uso original de mixin.

Para el profano, esto probablemente sería intuitivamente idéntico, porque históricamente se puede hacer referencia a .mixin1 de la siguiente manera, ya sea que esté escrito entre paréntesis o no:

.use1 {
    &:extend(.mixin1);
    foo:bar;
}
.use1 {
    &:extend(.mixin1());
    foo:bar;
}

Entonces, esperaría esto:

.mixin1() {
    color: red;    
}
.use1 {
    &:extend(.mixin1());
    foo:bar;
}
.use2 {
    &:extend(.mixin1());
    bar:foo;
}

... para dar salida ...

.use1, .use2 {
    color: red;    
}
.use1 {
    foo:bar;
}
.use2 {
    bar:foo;
}

Si mixin se define dos veces, se reemplaza dos veces cuando se extiende, al igual que su hermana, el selector de clases.

.mixin1() {
  color: red;
}
.mixin1() {
  width: 30px;
}
.use1 {
  &:extend(.mixin1);
  foo: bar;
}
.use2 {
  &:extend(.mixin1);
}
//output

.use1, .use2 {
  color: red;
}
.use1, .use2 { 
  width: 30px;
}
.use1 {
  foo: bar;
}

Básicamente, así es como funciona extender ahora si eliminara los paréntesis en las definiciones de mezcla, excepto, por supuesto, que el nombre de mezcla aparecería en la salida, por lo que tendría sentido seguir el comportamiento de extensión existente.

Con parámetros (mi caso de uso del 90%), lo mismo, excepto que se diferencian por entrada:

.col(@width) {
  width: @width;
  display: table-cell;
}

.col1:extend(.col(10%)) { }
.col2:extend(.col(10%)) { }
.col3:extend(.col(80%)) { }

//output 

.col1, .col2 {
  width: 10%;
  display: table-cell;
}
.col3 {
  width: 80%;
  display: table-cell;
}

Para mí, la razón para extender los mixins es agrupar los parámetros, lo que lleva a bibliotecas de mixin más potentes que pueden producir resultados muy concisos. Usarlos para mixins sin parámetros no es tan importante, ya que podría usar las funciones Less existentes hoy para producir el resultado deseado.

Gracias a todos por seguir impulsando esto. Creo que podría ser una adición bastante poderosa.

: +1 Gracias @ matthew-dean por el desglose completo. Estoy de acuerdo con todo lo que cubriste. ¿Podrías dar tu opinión sobre este escenario, que es uno de los temas de discusión reciente?

.mixin() { color: red; }

.component {
    .mixin() { color: blue; }

    > li:extend( .mixin() ) { ... }
}

La forma en que LESS funciona actualmente, solo se extienden los mixins en el alcance global, lo que significa que los estilos rojos se extenderían. Personalmente, estoy de acuerdo con este comportamiento, y aunque es probable que alguien escriba el código anterior y espere que prevalezcan los estilos azules , creo que el comportamiento "global" de la extensión es un detalle en la documentación.

// this is ".mixin()", which is being extended
.mixin() { color: red; }

.component {
    // this is ".component .mixin()", which is not. 
    .mixin() { color: blue; }

    > li:extend( .mixin() ) { ... }
}

Creo que el comportamiento "global" de la extensión es una línea en la documentación.

Completamente de acuerdo. Creo que es una idea terrible introducir un área gris aquí.

Para mí, lo importante es la coherencia. Si el comportamiento actual no extiende los selectores en el ámbito local, tampoco debería hacerlo con mixins. Si luego ampliamos los selectores en local, los mixins también deberían hacerlo. Las personas deberían poder confiar en un patrón de: extender que abarque toda la biblioteca.

(Aunque podría haber dicho más concisamente: "+1 al comentario de @jonschlinkert ". ;-)

En este punto, ¿alguien puede proporcionar un caso de uso que confunda esta función? Comience con esta descripción general completa de @ matthew-dean y las respuestas posteriores e intente ofrecer una situación del mundo real que no haya sido cubierta.

Felices vacaciones. Feliz Navidad. Felices Fiestas!

Muy buena descripción. Estoy de acuerdo con @ matthew-dean y todos los comentarios siguientes. : +1:

También estoy de acuerdo con @ matthew-dean. Parece un tipo estupendo y me gustaría estrechar su mano.

(-Anónimo)

@ matthew-dean palabra. : +1:

¡Podríamos hacer que el código del sistema de cuadrícula de Bootstrap sea mucho más limpio con esta función!

: +1: ¡de acuerdo @cvrebert! ¡sería bueno!

Solo volviendo a visitar. Creo que tenemos un consenso cercano y solo necesitamos implementación, ¿correcto?

Estoy tratando de encontrar más información sobre esto, pero es como un laberinto leyendo todo. ¿Se implementó esto alguna vez? Si es así, alguien me puede indicar amablemente el área apropiada en los documentos.

@ josh18 No, cuando una solicitud de función aún está abierta, esto generalmente significa que no está implementada.

Ok, gracias, pensé en comprobarlo dos veces por si me faltaba algo.

En algún momento planeo resumir las características abiertas / por implementar en la Wiki, pero aún no he tenido tiempo.

En algún momento planeo resumir las características abiertas / por implementar en la Wiki, pero aún no he tenido tiempo.

@ matthew-dean +1

¡Hola tios! Por lo que tengo entendido, esta función será algo similar a los marcadores de posición de SASS. Solo quería saber cuándo se implementará esto.

Hola,
Me resulta difícil predecir mi tiempo y otros contribuyentes simplemente
implementar cosas que les interesan, así que no estoy seguro. Todo lo que puedo decir es
que lo consideramos de alta prioridad, es la próxima gran cosa en mi lista.

Gracias por su respuesta. Espero ver esto implementado y funcionando. :)

+1 para esta función. Es extremadamente útil para reducir el tamaño de CSS.

+1 para esta función.

+1 para esta función.

+1 viendo con interés, ¡gracias!

: +1:

Han pasado DOS AÑOS desde que se creó este problema. Etiqueta de alta prioridad desde noviembre de 2014. El hito es 1.6.0 o 2.0.0. Excelente. Menos es 2.5 ahora.

@Grawl

¿Quiere decir que está listo para hacer relaciones públicas?

@ seven-phase-max Eso es más o menos lo que pensaba. Tal demostración de derecho. ;)

@ seven-phase-max lol no, solo soy frontend / diseñador.
@Celc se ve muy mal 😅

Han pasado DOS AÑOS desde que se creó este problema.

Sí, de todos modos, ¿por qué les estoy pagando a ustedes? ;-)

Lamentablemente, no puedo ayudar con la participación, ¡pero acepto esta solicitud!

Esta es una funcionalidad extremadamente importante para construir marcos complejos y efectivos.

3 años y contando. Afortunadamente, viene Sass v4 (con funciones con prefijo sass-* ) y puedo deshacerme de Less.

@stevenvachon No le

Por supuesto, las solicitudes de extracción son bienvenidas, de cualquier persona. Con mucho gusto fusionaremos una solicitud de extracción funcional con esta función.

No estoy tratando de lastimar a nadie, de hecho probablemente estoy tratando de evitarlo. Creo que es mejor expresar cómo uno puede sentirse y las nuevas direcciones que puede estar tomando como resultado. Creo que es mejor saber más temprano que tarde; antes de que todos se vayan. Por ejemplo, Bootstrap v4 no usará Less.js y estoy seguro de que afectará mucho su base de usuarios. Puede ignorar esta política todo lo que quiera, por supuesto.

@stevenvachon ¿por qué tan fuera de tema? Sass y Less son geniales. Me encanta el JS puro de menos. node-sass necesita un compilador de CA para instalarse, lo que puede ser un problema dependiendo del entorno. He usado la función : extend que ya está integrada en LESS y satisface todas mis necesidades. Ni siquiera sé por qué este tema sigue abierto.

Diablos, soy un desarrollador de rieles y uso gulp + LESS cuando no es un proyecto ruby.

¿Sin relación? Esta función no se ha implementado en 3 años y sería muy útil.

Preferiría que Sass estuviera escrito en JS, pero no lo es, y eso no es lo más importante. Sus características son. Sass nos permite extender los marcadores de posición, pero Less no nos permite extender los mixins.

Amigo, no es un tema fuera de lo común, ¡sino una característica muy esperada! (Aunque preferiría menos de todos modos, por varias razones)

Simplemente suplica ser hecho.

PD: En mi caso, soy un diseñador con solo un poco de conocimiento de js, principalmente cosas relacionadas con dom, muy lejos del desarrollador que puede contribuir a la base de código less.js, lo cual es una historia triste de todos modos)

Solo un partidario extremadamente interesado del proyecto)

Anuncio de servicio publico

En cualquier momento, puede enviar una solicitud de extracción o trabajar con un desarrollador para obtener una, y es muy probable que esta función se fusione. La biblioteca Less.js necesita contribuciones más regulares de personas como las personas en este hilo. . No es responsabilidad de nadie. Depende completamente de que una persona vea este hilo, o necesite esta función, y se tome el tiempo para hacerlo realidad.

Si su respuesta es que no es un desarrollador, entonces hay muchas OTRAS formas en las que puede apoyar este proyecto en roles que no sean de desarrollo, ya sea proporcionando la documentación necesaria para nuevas funciones o el diseño de soporte en el sitio web, ejecutando pruebas, proporcionando comentarios. sobre problemas, gestión de proyectos, responder preguntas sobre Stack Overflow, escribir publicaciones en blogs, tuitear sobre Less, contribuir a CSS y comunidades web, y escribir bibliotecas Less.

Muchas de estas tareas las realizan personas que son desarrolladores, por lo que el tiempo que podrían estar contribuyendo al desarrollo se dedica a estas otras tareas.

Si usted es un desarrollador y su respuesta es "No tengo tiempo", entonces esa es la razón exacta por la que este problema ha quedado abierto. Depende 100% de usted si se completa una función, por lo que preguntar por qué "alguien" no la ha completado no es útil. _Tú eres ese alguien. Sucederá, te garantizo que sucederá, siempre y cuando te involucres en este proyecto. Puede involucrarse en una de las herramientas de código abierto más populares en la web. ¿Puedes marcar la diferencia en la vida de ... miles? ¿Cientos de miles? Millones Y como beneficio adicional, puede asegurarse de que sus funciones favoritas aparezcan más temprano que tarde.

Si desea que suceda esto o cualquier otra característica, hágalo realidad . Nos encantaría tenerte. ¡Nos encantaría trabajar con usted! ¡Menos puede seguir mejorando y mejorando cuanto más grande crece esta comunidad!

Y, escuche, aprecio que a veces la gente realmente no tiene tiempo para contribuir y, sin embargo, realmente le gustaría que ocurriera una característica en particular. Esta bien. Solo diría que si estás en ese escenario, tu objetivo es la empatía y la gratitud por las personas que donan su tiempo (y a veces dinero) para ayudarte, y estoy seguro de que otras personas en la comunidad Less harán todo lo posible para continúen haciéndolo, en la medida de sus posibilidades.

Atentamente,
Matthew Dean, miembro del equipo central de Less.js

Ya apoyo mis propios proyectos y escucho sus solicitudes de funciones. Honestamente, no tengo tiempo para profundizar en el núcleo de Less.js.

Para aquellos que vienen aquí en busca de soporte de marcador de posición sass (o "clase silenciosa"), lea este comentario . No lo llevará hasta allí (debido a # 1851 y no tener tales clases en un archivo "referenciado"), pero es mejor que nada.

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

yggi49 picture yggi49  ·  7Comentarios

xblakestone picture xblakestone  ·  3Comentarios

pknepper picture pknepper  ·  3Comentarios

Oskariok picture Oskariok  ·  6Comentarios

briandipalma picture briandipalma  ·  6Comentarios