Less.js: : extender mixins

Criado em 12 fev. 2013  ·  112Comentários  ·  Fonte: less/less.js

Esta solicitação de recurso foi proposta como uma solução para este problema https://github.com/cloudhead/less.js/issues/1155

Esta é a sinopse

O mais incrível dos mixins é que eles aceleram o desenvolvimento, mantêm minha superfície de trabalho limpa, só preciso escrevê-los uma vez e sei qual será o resultado compilado. No entanto, uma desvantagem dos mixins é que eles não são SECOS. Especialmente quando você usa muito os mixins de "utilitários", como o clearfix. É aqui que extends _pode_ ser uma opção muito melhor. Na verdade, este é um ótimo caso de uso concreto para estender mixins . Basicamente, funcionaria como estender seletores aninhados, aceitar com mixins. Assim, os mixins não mudariam de forma alguma, eles ainda funcionariam da mesma maneira. Se você tem um mixin e não o usa, ele não aparecerá no CSS compilado. Se você usá-lo, suas propriedades ainda serão exibidas no código compilado em cada seletor onde foi usado. E se você _ extender _ um mixin, o seletor (ou seletores) estendendo o mixin aparecerá no lugar do mixin. Então, se você fizer isso:

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

e o resultado compilado será:

.navbar,
.banner {
   // clearfix stuff
}

Portanto, as propriedades dos mixins ainda são herdadas pelos seletores que as estendem, mas o mixin (seletor) em si não aparece no resultado compilado.

Isso tornaria os extends e mixins muito mais poderosos do que sozinhos.

feature request medium priority up-for-grabs

Comentários muito úteis

Anúncio de serviço público

A qualquer momento, você pode enviar uma solicitação pull ou trabalhar com um desenvolvedor para obter uma, e é muito provável que esse recurso seja integrado. A biblioteca Less.js precisa de contribuições mais regulares de indivíduos como as pessoas neste tópico . Não é responsabilidade de ninguém. É totalmente dependente de uma pessoa ver este tópico, ou precisar desse recurso, e dedicar um tempo para que isso aconteça.

Se sua resposta for que você não é um desenvolvedor, existem muitas OUTRAS maneiras de apoiar este projeto em funções não desenvolvimentistas, seja fornecendo a documentação necessária para novos recursos ou suporte de design no site, executando testes, fornecendo feedback sobre problemas, gerenciamento de projetos, respondendo a perguntas no Stack Overflow, escrevendo posts de blog, tweetando sobre Less, contribuindo para CSS e comunidades da web e escrevendo bibliotecas Less.

Muitas dessas tarefas estão sendo realizadas por indivíduos que são desenvolvedores, portanto, o tempo que poderiam estar contribuindo para o desenvolvimento é gasto nessas outras tarefas.

Se você _é_ um desenvolvedor e sua resposta for: "Não tenho tempo", então esse é o motivo exato pelo qual este problema está aberto. Depende 100% de você se um recurso é concluído, portanto, perguntar por que ele não foi concluído por "alguém" não é útil. _Você é esse alguém._ Vai acontecer, eu garanto_ que vai acontecer, se e quando você se envolver neste projeto. Você pode se envolver com uma das ferramentas de código aberto mais populares da web. Você pode fazer a diferença na vida de ... milhares? Centenas de milhares? Milhões? E como um benefício colateral, você pode garantir que seus recursos favoritos aconteçam mais cedo ou mais tarde.

Se você quer que esse ou qualquer recurso aconteça, faça acontecer . Nós amaríamos ter você. Adoraríamos trabalhar com você! Menos pode ficar cada vez melhor à medida que esta comunidade cresce!

E, ouça, eu aprecio que às vezes as pessoas realmente não têm absolutamente nenhum tempo para contribuir e ainda assim gostariam que um determinado recurso acontecesse. Isso é bom. Eu diria apenas que, se você está nesse cenário, busca empatia e gratidão pelas pessoas que doam seu tempo (e às vezes dinheiro) para ajudá-lo, e tenho certeza de que outras pessoas na comunidade Less farão o melhor para continue a fazê-lo, conforme for possível.

Sinceramente,
Matthew Dean, membro da equipe principal do Less.js

Todos 112 comentários

Eu gosto, mas só para ficar claro .. isso não permite que você faça algo que não podia fazer antes, apenas significa que você consegue ..

.navbar,
.banner {
    // clearfix stuff
}

ao invés de

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

ou eu entendi mal?

Eu adoraria ter ambos, mixins paramétricos e usuais, para ter

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

ou

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

sempre que precisar, sei que essa é a forma simular como os mixins já funcionam, então a questão principalmente ter flexibilidade e maneira de lidar melhor com a saída final do CSS em termos de otimização.

certamente

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

é mais curto que

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

e para exemplos mais complicados que podem ser críticos, e eu sei que algumas pessoas mudaram para SASS apenas por causa dessa falta

Mixins regulares não podiam mudar. Eles são praticamente um acessório de Less. @agatronic , sim, também vejo dessa forma. No entanto, existem desafios para isso, como seríamos capazes de estender mixins paramétricos? E se sim, como isso funcionaria? Supondo que isso fosse compatível, digamos que você estenda um mixin paramétrico duas vezes, mas use variáveis ​​diferentes a cada vez, como este:

.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));
}

Eu imagino que isso possa criar duas cópias do mixin, que não é menos código e nenhuma vantagem sobre os mixins regulares:

.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;
}

No entanto, você pode usar muito esse mixin em particular, então, quando usar o mixin novamente em .dropdown com as mesmas variáveis ​​de .banner , isso pode resultar em:

.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;
}

E é isso que torna isso interessante para mim. seria bom ouvir o feedback de outras pessoas também

@jonschlinkert sim, é uma ilustração ainda melhor, obrigado. como eu disse com as duas mãos nisso! mas entenda que está adicionando outro nível de cumplicidade e precisa ser feito / não feito com cuidado

A extensão no método que você faz referência pode ser alcançada facilmente com este padrão:

.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();
}

O acima está injetando mixins semi-extendidos nas 2 novas declarações.

Para o clearfix também é fácil usar um padrão semelhante abaixo, que não apenas criará o clearfix como uma classe, mas injetará esses estilos de clearfix em uma nova declaração.

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

@krismeister Acho que pode haver confusão sobre isso. O padrão que você descreve é, na verdade, apenas mixins aninhados ou um padrão de herança de mixin. Estende o trabalho no inverso disso.

@jonschlinkert Mixin inheritence - um ótimo nome. Parecia que ambos os exemplos acima estavam tentando herdar a saída do pai - o que é um recurso central da extensão. Você provavelmente concorda que a saída do meu exemplo foi a saída esperada.

Pelo que entendi, depois de reler seu comentário original, você gostaria que a saída fosse reunida em uma regra CSS. Embora tenha sido escrito como 2 originalmente.

Na verdade, :extend é muito legal. Eu vou ficar totalmente nerd, mas tudo se resume a "o que é movido para onde". Pense em um mixin como "transmitir as propriedades do mixin para o seletor que o utilizou". E pense em :extend como o inverso, "direcionando o seletor que o usou para o próprio mixin." Não as propriedades do _selector, apenas o próprio seletor. Então, se você fez isso:

.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;
}

Isso resultaria em:

// 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;
}

Esperançosamente, isso faz mais sentido. Fico feliz em ajudar a qualquer hora.

@agatronic , @matthewdl , @DesignByOnyx , apenas uma ideia, sei que é uma abordagem incomum, mas presumindo que não haja desafios técnicos para isso e supondo que permitamos uma lista de seletores separados por vírgulas, talvez extend _deve_ parecer mais com um array . O que você acha de mudar a sintaxe para: :extend[N] .

Eu acho que é mais fácil para os olhos também quando os mixins são estendidos:

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

Estou bem de qualquer maneira, mas algo parece certo sobre os colchetes.

@jonschlinkert - [] significa atributo em css, não array, onde :extend() foi escolhido por causa de seu link para pseudo seletores, então eu acredito fortemente que os colchetes normais deveriam permanecer.

bom ponto, eu concordo.

Eu concordo que os colchetes parecem e leem bem, mas sim, temos que seguir a sintaxe que já escolhemos.

polegar para cima para sintaxe extend (N), mais parece CSS da natureza, mesmo motivo que @agatronic

Estender mixins não é uma má ideia. Não tenho certeza sobre a sintaxe de exemplo, @jonschlinkert. Não que eu não goste; Na verdade, não entendo o que você escreveu.

Acho que o que você quer dizer é que você deseja definir classes que "puxam" o mesmo conteúdo mixin, mas não se repetem no CSS resultante. Eu não chamaria isso de mixins estendidos. Ou seja, você não está alterando a definição do mixin (da mesma forma que a definição de extensão faria com os seletores), você está na verdade alterando (estendendo) as classes resultantes.

Então, me corrija se eu estiver errado, mas seu exemplo de barra de navegação / banner / menu suspenso não seria compatível com:

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

Ou seja, estendendo as aulas como faria normalmente? Estou apenas tentando entender seu padrão de uso, e o uso de extend para mixins parece estar em desacordo com seu uso e nomenclatura para estender seletores. Você pode fornecer mais detalhes sobre por que você precisa / deseja referenciar o mixin em uma chamada de extensão, e não estender um seletor que faz referência ao mixin?

É assim que eu entendo

SAÍDA DE CSS FINAL DESEJADA

.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
}

O CAMINHO QUE VOCÊ TEM DE SEGUIR COM A VERSÃO ATUAL DE MENOS PARA OBTER A SAÍDA DESEJADA

.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
}

SUGESTÃO MENOS SINTAXE

.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
}

Enquanto as extensões podem ser úteis apenas quando você realmente tem uma quantidade de código compartilhado, em outros casos, o uso de mixins comuns tem preferência.

E apenas um pouco, amostra simulada ao vivo, com o objetivo de apenas brincar

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 disse, pode haver realmente um aumento de desempenho em certas circunstâncias para pessoas que são preguiçosas como eu :) para otimizar o código MENOS apenas porque é afetado ainda mais flexibilidade

Aqui está uma boa postagem no blog sobre extends que cobre várias coisas sobre como o SASS lida com extends, e provavelmente é sábio aprendermos como outros fizeram isso. http://designshack.net/articles/css/semantic-grid-class-naming-with-placeholder-selectors-in-sass-3-2/

Em particular, acredito que minha proposta para estender mixins iria essencialmente atingir o mesmo resultado final que os "marcadores de posição" do SASS, mas sem ter que criar classes apenas de marcadores de posição inúteis e supérfluas.

EDIT: sim, aqui está outro post que resume bem os espaços reservados. É exatamente o que estou propondo com a extensão de mixins http://maximilianhoffmann.com/article/placeholder-selectors

Eu pessoalmente prefiro isso acima de todos os outros recursos relacionados a extensões. Sem dúvida. Esta é uma afirmação forte, mas acho que não estou fazendo um bom trabalho ao explicá-la se os outros não concordarem. Isso é algo muito poderoso.

Eu sinto que SASS

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

é igual ao mixin paramétrico, projetado para extends exclusivamente, o que provavelmente não é tão ruim em termos de separação de interesses. mas sim, isso é CSS, e não deveria ser o mais simples possível?

@agatronic enquanto estamos falando, o que é essa extensão https://github.com/agatronic/less.js/blob/master/lib/less/tree/extend.js supostamente? observou que já está no ramo menos principal. desculpe pela pergunta noob embora.

@ dmi3y é a primeira versão de extend que foi retirada de um pull request pronto para 1.4.0 - ele representa o nó extend

obrigado @agatronic , agora vejo o quanto perdi;)

@ dmi3y sinta-se à vontade para continuar adicionando à conversa, vamos tentar manter esse problema em um nível mais alto para que possamos concluí-lo. Sinta-se à vontade para me enviar um e-mail pessoalmente, estou feliz em discutir como mixins e extensões funcionam com você (minhas informações de contato estão no meu perfil). Também um comentário rápido para evitar mais confusão neste tópico. Seu exemplo:

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

Esta é a sintaxe para um "espaço reservado" SCSS, que foi implementado na especificação SCSS para realizar algo semelhante ao que estou propondo com mixins estendidos. Mas isso não tem nada a ver com ser paramétrico. Mixins paramétricos são simplesmente _mixins que aceitam parâmetros_, o que significa que seus valores podem mudar a cada vez que são usados.

@matthewdl

Acho que o que você quer dizer é que você deseja definir classes que "puxam" o mesmo conteúdo mixin, mas não se repetem no CSS resultante

e

seu exemplo de barra de navegação / banner / suspenso não seria suportado por ...

Não, o ponto operativo está sendo perdido, é exatamente o contrário. Talvez a confusão tenha sido causada porque cometi o erro de focar em mixins paramétricos no meu exemplo.

Então, primeiro, acho importante delinear que nem todos os mixins são paramétricos, muitos são criados para _não_ aceitar parâmetros. Alguns mixins, como o clearfix, são usados ​​repetidamente sem alterar nenhuma variável quando são usados. Este é um caso de uso perfeito para explicar por que estender mixins seria vantajoso.

Paramétricos ou não, em toda a sua glória os mixins têm uma desvantagem: cada vez que um é usado, suas propriedades são duplicadas . Então, deixe-me tentar explicar como estender mixins funcionaria usando apenas "mixins regulares", e continuando com o exemplo que você usou acima.

Dado o seu exemplo, há dois pontos completamente independentes e não relacionados que precisam ser feitos:

  1. a classe banner ainda seria mostrada no CSS compilado se fosse estendida ou não, mas se a classe banner fosse uma mixin, ela só apareceria no CSS resultante se fosse usada (estendida ou mixada). Só isso é valioso. E
  2. Quando você _estende um mixin_, em vez de duplicar as mesmas propriedades exatas uma e outra vez, copiaríamos os próprios seletores reais para o local do mixin.

Mas este é apenas um exemplo. Considere que em um ponto no Twitter Bootstrap, o mixin .clearfix() sozinho foi usado mais de 20 vezes dentro de outros seletores E também foi aninhado dentro de 4 ou 5 outros mixins estruturais, como .container-fixed() , .make-row() e #grid > .core() . O que significa que aqueles mixins _também_ duplicavam as propriedades do mixin do Clearfix cada vez que eram usados. E isso não é exclusivo dessa estrutura.

Isto faz mais sentido? Portanto, em vez de ter as propriedades do clearfix mixin duplicadas mais de 20 vezes, agruparíamos os seletores que usam o clearfix mixin no lugar do próprio mixin e as propriedades seriam declaradas apenas uma vez . E, novamente, este é apenas um mixin, imagine o benefício líquido de estender a perda de mixins regulares, versus ter suas propriedades duplicadas. Como mencionei em algum lugar acima, mixins regulares ainda precisarão ser usados ​​sem serem estendidos às vezes, por especificidade e substituições, mas isso não diminui o valor de estender aqueles que não o fazem. Na verdade, eu criaria pessoalmente mixins adicionais para serem usados ​​especificamente com extend, que eu não usaria de outra forma.

E meu segundo exemplo acima focou em como extend funcionaria com mixins paramétricos, então espero que isso complete o quadro e faça mais sentido agora? Caso contrário, os artigos que vinculei acima devem esclarecer qualquer confusão. Estender mixins é extremamente poderoso e útil e permitiria a você obter o mesmo resultado líquido que estender seletores aninhados, mas com mixins especificamente em vez de quaisquer seletores aninhados. Isso permite que você organize seus seletores de uma forma que provavelmente forneça os resultados desejados e evite consequências indesejadas. @DesignByOnyx , @agatronic , @matthewdl , há algo que estou perdendo ou esquecendo aqui? Podemos fazer alguma coisa para esclarecer a confusão?

Obrigado. Acho que entendo o caso de uso e acho que esta linha diz melhor:

a classe banner era uma mistura e só apareceria no CSS resultante se fosse usada (estendida ou combinada)

Isso faz sentido para mim. Provavelmente o que estou prendendo é que a sintaxe geral de :extend ainda não é final. Mas, você faz casos persuasivos.

Eu diria que, uma vez que finalizamos para os blocos seletores, se o comportamento dos mixins estendidos acabar combinando com o comportamento dos seletores estendidos (com a principal diferença sendo aquela linha que você acabou de dizer, que nenhum seletor é gerado no CSS para um A MENOS que haja um uso inicial), isso é intuitivo para mim.

Ou seja, se eu também pudesse fazer algo assim (ou sintaxe equivalente):

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

... então sinalize para cima de mim. Mas, para mim, tudo isso depende do que / como / se resolvemos :extend para seletores. Mas, sintaxe à parte, como uma ideia de recurso, você está certo, é sólida.

@jonschlinkert, obrigado, aprecio muito seu endosso e, com certeza, farei o melhor para colocar minhas idéias da forma mais clara possível. Eu acho que é muito emocionante ouvir o que está acontecendo com o desenvolvimento futuro e, sim, ser ouvido. Vocês todos, façam um trabalho incrível com isso.

Sim, esse exemplo, tive que ser explícito com meu post anterior.

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

é tirado dos tutoriais SASS fornecidos por Jon e tem como objetivo principal evitar a destruição da saída em CSS de classes que não estariam em uso. Portanto, neste ângulo específico, poderia ser visto como um mixin paramétrico vazio no LESS. Quando você quiser usá-lo, mas não quiser, ele será enviado para a folha de estilo final.

Estou entrando nesta discussão e gostaria de esclarecer o seguinte comentário:

se a classe banner fosse um mixin, só apareceria no CSS resultante se fosse usado (estendido ou mixado)

Então, indo com um exemplo clearfix mais genérico, este é o MENOS e o 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;
}
*/

Eu originalmente esperava que a classe .clearfix permanecesse omitida do CSS compilado. Pessoalmente, eu não _necessito_ a classe no CSS compilado, pois não a estaria usando na marcação e seus bytes extras no meu CSS. Eu realmente não tenho uma opinião forte de qualquer maneira, mas um esclarecimento sobre esse ponto me ajudaria a fazer comentários melhores no futuro. Obrigado.

este é o ... CSS resultante ?:

Fico feliz que você esteja perguntando, mas não , apenas a classe .something apareceria no CSS resultante. Então você estava correto em sua expectativa original.

apenas leia o link dos marcadores de posição e sim, acho que estender mixins é uma maneira melhor e mais simples de fazer as coisas e obter a mesma funcionalidade.

Para calrificar seu ponto acima

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

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

e presumivelmente, se .clearfix() { definition for .clearfix { então chamá-lo com ou sem colchetes dentro da definição de extensão não fará diferença para a saída.

Usar a sintaxe de pseudo classe para o recurso de extensão é totalmente ERRADO,
porque "extend sth" NÃO é igual a "match sth", isso não significa nada sobre a estrutura DOM que um seletor deveria.

MENOS vocês "inventaram" muitas idéias ruins. O mais famoso é "reutilizar '.xxx (seletor de classe) como notação mixin. Pelo menos facilita a migração do CSS simples para o pré-processador. Mas: estender a sintaxe é a pior ideia que já ouvi.

Não quero dignificar esse tipo de discurso retórico sobre nossos problemas, mas não é a primeira vez que ouço essas coisas, então vamos falar sobre CSS e limpar o ar.

MENOS vocês "inventaram" muitas idéias ruins. O mais famoso é "reuse '.xxx (seletor de classe) como notação mixin ....: extend syntax é a pior ideia que já ouvi.

.xxx é chamado de mixin implícito. Funciona e é fácil de entender. Na verdade, essa sintaxe não é tão "invasiva" nas especificações CSS como, digamos, usar regras at para definir o estilo real. @keyframes é o que mais se aproxima do que seria descrito como estilo e pode _poderar_ ser considerado uma exceção ao que estou dizendo, já que são usados ​​identificadores que correspondem à produção de identificadores na sintaxe CSS. Além dos quadros-chave, em geral as regras em CSS são reservadas principalmente para configuração de nível superior e manipulação de estilo ou folha de estilo com base em informações "externas", ou seja, fora dos próprios estilos, como codificação de caracteres ( @charset ) ou respondendo às condições específicas do dispositivo ( @media ).

Além disso, posso ter ideias piores. Como usar at-rules para estilização é uma delas, usar duas at-rules para o mesmo recurso é outra. Claro, tudo depende de seus objetivos, se você deseja manipular estilos de forma programática sem tocá-los pessoalmente, provavelmente há vantagens em usar construções gramaticais mais obtusas e óbvias que podem ser mais fáceis de serem captadas por um analisador. Parece que você usa o Stylus, então estou interessado em ouvir seu ponto de vista sobre por que outras sintaxes são vantajosas.

"extend sth" NÃO é igual a "match sth", não significa nada sobre a estrutura DOM que um seletor deveria.

Correto. Pseudo-classes com nth _algo_ são descritas como pseudo-classes " estruturais " pela especificação CSS. No entanto, existem 6 outros tipos de pseudo-classes: "dinâmico", "negação", "destino", "em branco", "Estados do elemento de interface do usuário" e "idioma". Se a especificação CSS de fato descrevesse um recurso de "extensão", ela poderia se encaixar elegantemente como uma categoria entre as pseudo classes "negação" e "alvo".

As pseudo-classes permitem a seleção com base nas informações da árvore do documento, mas provavelmente esse não é o uso ideal do recurso de extensão.

totalmente errado

Uma comunidade maior do que todos os outros pré-processadores combinados não pode estar errada. O que mais há a dizer?

@hax - :extend . Após semanas de diferentes sugestões e deliberações entre desenvolvedores front-end muito experientes e usuários pesados ​​do LESS, chegamos a uma solução satisfatória com a sintaxe :extend . Se você tem uma sugestão melhor, acredite em mim - somos todos ouvidos.

Para adicionar a @jonschlinkert , .this:not(.that) { } e .this:matches(.that) { } e .this:extend(.that) { } são categoricamente semelhantes. Isto é: "Dado o seletor 'este', relacione-o ao seletor 'aquele' de uma maneira particular." Visto que LESS frequentemente estende conceitos e sintaxe introduzidos em CSS, é uma extensão bastante lógica da linguagem. Prestamos muita atenção às especificações CSS e, como resultado, refletimos suas idiossincrasias. Se houver estranheza no conceito, espero que comece primeiro no CSS. É por isso que em nossos mixin guardas, "AND" é representado pela palavra "e", e "OR" é representado por uma vírgula: porque é assim que funciona nas consultas de mídia. Nosso objetivo não é corrigir ou alterar o CSS, mas torná-lo muito mais fácil de trabalhar e tornar o LESS completamente familiar para os autores de CSS. :extend é um exemplo disso. Se você sabe como usar :not , você sabe como usar :extend .

E se usássemos uma sintaxe mais "implícita" para evitar o aninhamento de parênteses e para tornar mais fácil estender mixins paramétricos?

Hoje, usamos um mixin paramétrico como este:

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

Em vez de estender o mixin assim (como você pode estender uma classe normal):

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

Podemos estender assim:

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

A distinção é que o "mixin estendido" termina em ponto-e-vírgula e declara um valor ou valores dentro dos parênteses, .border-radius:extend(9px); , em vez de listar as classes a serem estendidas dentro dos parênteses e iniciar um novo bloco seletor com chaves, .border-radius:extend(.some-class) {} . IMHO, isso não é menos sutil do que mixins implícitos ( .border-radius; ), que é um dos recursos mais legais do LESS, novamente IMHO.

Na saída renderizada, qualquer "mixin paramétrico estendido" seria renderizado no lugar do mixin original, como este:

.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;
}

Então, eu pessoalmente gosto disso porque é um desvio o suficiente da sintaxe de extensão "normal" dentro dos blocos seletores para tornar óbvio o que está acontecendo, e vai junto com a sutileza de existirem menos convenções onde não há necessidade de explicar o que você está tentando realizar no código. Esse recurso está definitivamente no topo da minha lista pessoal de desejos.

Usando o exemplo do clearfix que dei em minha solicitação original, seria assim com minha sintaxe revisada:

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

Eu gosto de onde você quer chegar com isso. Acho que uma abordagem mais amigável é usar uma :extend no final da sintaxe mixin _existente_ como esta:

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

Algo sobre omitir os parênteses após :extend faz parecer que serve a um propósito diferente do que a sintaxe de extensão existente.

Eu poderia ir de qualquer maneira com isso, mas eu prefiro .border-radius:extend(9px); porque é consistente com a sintaxe de extensão, IMO ainda é óbvio que é um mixin, mas também implica que os parâmetros / valores estão sendo estendidos - o que ajudará a explicar porque a saída é "agrupada".

@jonschlinkert - a esta altura, tenho as suas opiniões em alta conta e

@DesignByOnyx obrigado pelas amáveis ​​palavras. O que você está dizendo faz muito sentido, minha "lente" de estende (em menos) tem sido algo como:

.this:extend(.that) {}

então seu ponto é consistente com minha própria visão. @matthewdl ou @lukeapage ,

Por que o compilador Less não pode "fazer a coisa certa" automaticamente? Em outras palavras, se eu tiver esse mixin declarado em meu código:

.someMixin {
    color: red;
}

E depois eu uso assim:

#someElement {
    .someMixin;
}

Por que o compilador não pode ser inteligente o suficiente para otimizar este código Less neste CSS:

.someMixin,
#someElement
{
    color:red;
}

Por que eu, como usuário, devo adicionar manualmente uma palavra-chave: extends para obter esse comportamento? O compilador deve ser inteligente o suficiente para perceber que essa otimização pode ser feita e, em seguida, fazê-lo.

Pessoalmente, eu acho isso: estender a ideia é confuso. Toda a noção de uma palavra-chave "extends" significa: "Pegue essa coisa X e adicione A, B e C a ela." Mas, neste contexto, você propõe redefinir estende a: "Essa coisa X é realmente igual a Y, então você pode simplesmente declarar Y e X como iguais e escrever uma vez." Isso vai contra a noção padrão de "estender" algo.

Sim, eu estava pensando exatamente a mesma coisa antes e ia postar, mas depois de pensar sobre isso, decidi que aplicar automaticamente o "comportamento de extensão" aos mixins é muito opinativo para Less.js. Especificamente, embora a herança do seletor (estender) seja um conceito incrível que é super benéfico para a redução de código, a grande maioria das reclamações que li sobre o recurso é que ele adiciona uma camada de abstração que torna difícil vasculhar o código e depure quando houver problemas.

Portanto, grandes mentes pensam da mesma forma, mas eu voto contra a ideia pessoalmente porque a) não devemos mexer com mixins "normais" até que o recurso extend esteja completamente estável e a especificação seja mais completa, b) Acho que muitos desenvolvedores querem fazer essa chamada por si próprios ec) muitas vezes as coisas parecem tão óbvias e simples, quando o fato da questão é que estamos esquecendo muitas das excentricidades sobre os mixins que fariam o seu sugestão difícil de implementar no mínimo, e provavelmente impossível de implementar enquanto ainda permite que os desenvolvedores usem todos os "mixin hacks" que nós ... ahem, eles passaram a conhecer e amar.

A sintaxe: extends () ainda é um hack muito desajeitado que não é intuitivo e difícil de explicar para novos usuários.

A melhor solução é simplesmente fazer o compilador otimizar automaticamente o CSS conforme descrito acima, quando o usuário tiver selecionado um estilo de saída apropriado (compactado, otimizado, etc). Se o usuário selecionar o estilo de saída não compactado, o compilador deve evitar essas otimizações e gerar menos código DRY.

Além disso, você pode resolver as dificuldades de depuração com mapas de origem. Eles podem facilmente apontar a localização do CSS compilado que vem de um mixin do Less.

@bdkjones , crie uma nova solicitação de recurso para "otimizar automaticamente o CSS" com suas sugestões de como fazer isso no código. Esse tipo de contribuição é sempre bem-vindo.

Ponto alcançado! Não tive a intenção de ser tão severo em meu último comentário; Eu me empolgo às vezes.

Quanto ao código, infelizmente estou totalmente ocupado com o CodeKit. Eu deixei vocês embaralharem as línguas!

De jeito nenhum! realmente, eu vi que você está envolvido com o CodeKit, adoraria ter sua contribuição contínua. Nem todos os recursos vão agradar a todos, mas feedback e opiniões fortes são as únicas coisas que mantêm as rodas girando!

@bdkjones O problema é a cascata. Em seu caso de uso, funciona, mas o agrupamento de seletores não teria o resultado desejado em todos os casos, já que possivelmente moveria os seletores "mais cedo" no documento, evitando declarações que estavam sobrescrevendo esses seletores.

Mas, eu concordo com suas declarações contra a sintaxe mixin extend conforme ela evoluiu aqui. O Seletor X deve estender o Seletor ou mixar Y, então isso parece estranho:

.border-radius(9px):extend;

Acho que estamos usando mal a sintaxe de extensão. Se a sintaxe de extensão como ela existe não se encaixa com mixins (o que é perfeitamente plausível), sugiro que encontremos a sintaxe certa para mixins, em vez de expandir a sintaxe de extensão de uma forma que destrua a metáfora, como @bdkjones aponta Fora.

Acho que estamos usando mal a sintaxe de extensão

Discordo. Se funcionar, use. Por que criar novas sintaxes sem motivo? Acho que temos um grande precedente para a sintaxe proposta, dou muitos exemplos e justificativas de apoio às minhas sugestões, mas sua opinião sobre as sintaxes propostas parece muito subjetiva. E já que você fez essa afirmação algumas vezes recentemente, pode explicar por que acha que a sintaxe está sendo abusada? Ou explique em que ponto uma sintaxe está sendo abusada? Ou compartilhe seus pensamentos sobre como os mixins devem ser estendidos, mas sem a sintaxe "extend"?


Em seu caso de uso, funciona, mas o agrupamento de seletores não teria o resultado desejado em todos os casos, já que possivelmente moveria os seletores "mais cedo" no documento, evitando declarações que estavam sobrescrevendo esses seletores.
...
Acho que estamos usando mal a sintaxe de extensão. Se a sintaxe de extensão como ela existe não se encaixa com mixins (o que é perfeitamente plausível), sugiro que encontremos a sintaxe certa para mixins, em vez de expandir a sintaxe de extensão de uma forma que destrua a metáfora, como bdkjones aponta .

Não. Ele não apontou nada, ele nos encorajou a tornar o Less mais fácil de usar - esse era o seu resultado final. Sua maneira sugerida de fazer isso estava equivocada, mas a intenção era boa. Ele não estava pensando na cascata que você acabou de apontar. Ao usar extend em geral, você deve levar em consideração a cascata. Acho que qualquer pessoa que usa extend ao invés de mixin sabe disso. Assim, é por isso que Less.js oferece a você a escolha de usá-lo quando fizer sentido ou _não_ quando não fizer. O fato de que o primeiro "C" em CSS significa cascata não nega a vantagem de consolidar estilos duplicados quando a cascata não é material. O que estou perdendo aqui?

Então, você pode esclarecer seu sentimento? Você é contra esse recurso ou a sintaxe? Se você é contra a sintaxe, por favor, proponha algo diferente para manter as coisas em movimento, caso contrário, não vamos atrapalhar o progresso de um recurso que é tão promissor para a linguagem.

Você é contra esse recurso ou a sintaxe?

Eu sou a favor do recurso, com certeza. Esta é uma direção óbvia. Eu revisei a sintaxe novamente neste tópico. Alguns pensamentos:

Primeiro, isso é estranho para mim:

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

Os parênteses duplos são estranhos. Mas, é uma adoção fiel da sintaxe de extensão existente, portanto, é justo. Então, é por isso que eu estava defendendo outra coisa, talvez algo diferente de estender.

Então há isso que você propôs, acho que por razões semelhantes:

.border-radius(9px):extend;

... ao qual tive uma reação alérgica, porque parece contrário às especificações de extensão existentes. Então é aí que me pareceu mau uso.

MAS

Percebi que há realmente duas opções aí. Uma é que fazemos algo diferente para os mixins. Mas a outra opção é revisarmos a especificação de extensão existente, para todas as coisas, incluindo 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;
}

Mas .... com um seletor cheio ( .some .random .selector ), ele começa a ler errado. Parece que apenas .selector tem extensão. E a palavra "estender" começa a se perder, quando é a palavra importante nesta declaração. Este não era o caso quando foi escrito como &:extend() (porque apareceu no início), mas essa sintaxe parece quebrar com os mixins.

Então, eu proporia uma destas opções:

// 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;
}

Acho que a discussão sobre a extensão de mixins e consultas de mídia destacou que nossa abordagem de sintaxe original para :extend não é tão flexível, especialmente quando queremos estender vários seletores e mixins.

Eu acho que é importante obter: estender certo. Se quisermos usar "extend" para mixins, então acho que temos que revisar a sintaxe de extend.

Eu não propus .border-radius(9px):extend; , @DesignByOnyx sim. Eu propus .border-radius:extend(9px);

Mas qualquer sintaxe está bem para mim. Ou poderíamos fazer .border-radius(9px) !extend; ou .border-radius:shamallamadingdongscoobiedoo(9px):extendmyass (jk), não importa para mim porque nada muda com o comportamento dos mixins ou extender.

Portanto, não tenho certeza de como você está descobrindo a necessidade de fazer tudo isso, provavelmente você está complicando demais as coisas para si mesmo.

Esta solicitação de recurso é expressamente sobre ter a capacidade de copiar as propriedades herdadas de um mixin _para o lugar do mixin_, e seguirá regras que já foram bem estabelecidas com o comportamento atual do mixin, e agora também têm precedência e comportamento idêntico ao o recurso <strong i="14">@import</strong> (reference) (que, aliás, tenho usado bastante na prática e adoro). Em poucas palavras:

  • Quando você usa um mixin, suas propriedades são copiadas para o local do seletor que está chamando o mixin.
  • Quando você usa extend, o seletor _extending_ é copiado para o lugar da classe _extended_.
  • Portanto, quando você estende um mixin, o seletor de chamada é copiado para o local do mixin.

Não tenho certeza por que você quer mesmo refazer o debate sobre a sintaxe para estender após dois anos de debate,> 100 postagens, muita pesquisa e já foi feito o caso de que é _muito mais_ flexível do que @extend .

A propósito, não tenho certeza do que você quer dizer aqui:

com um seletor completo (.alguns .seletor aleatório), ele começa a ler errado. Parece que apenas .selector tem extensão. E a palavra "estender" começa a se perder, quando é a palavra importante nesta declaração.

Não concordo que seja confuso, já que é assim que realmente funciona agora. Não é como dizer "Os desenvolvedores de CSS não sabem como funcionam os seletores agrupados"? E quanto a :hover ou :after ? Acho que os desenvolvedores de CSS podem descobrir isso muito bem, porque funciona da mesma maneira que outros pseduos.

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

Gosto da flexibilidade que isso oferece, pois posso (ou ambos) aplicar a extensão ao seletor, que é .some .random .selector , não .selector , ou posso colocá-lo dentro do bloco seletor.

Acho que a discussão sobre a extensão de mixins e consultas de mídia

Fechei o problema das consultas de mídia porque percebi que poderia ser resolvido com mixins estendidos. "Todos os caminhos levam a _____" mixins estendidos. ;-)

Eu gostaria de acrescentar meus dois centavos para dizer que os parênteses dentro de um parênteses - :extend( .some-mixin() ) - realmente não me incomodam muito, especialmente porque :extend( .some-selector ) já está estabelecido e foi discutido ad nauseam. Eu concordo que os parênteses duplos não são ideais de forma alguma e isso _faz_ parece meio estranho. Mas eu sinto que é importante que mixins e seletores sejam tratados da mesma forma em termos de "extensão", da mesma forma que são tratados da mesma forma no Less clássico:

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

Como tal, não me sinto muito mal (ou limitado) por fazer isto:

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

Mas eu sinto que é importante que mixins e seletores sejam tratados da mesma forma em termos de "extensão", da mesma forma que são tratados da mesma forma no Less clássico

Estou na mesma página nesse ponto.

Não sei por que você deseja refazer o debate sobre a sintaxe para estender após dois anos de debate,> 100 postagens

Não é uma questão de querer. Não, eu não quero. Ainda assim, nós meio que embaralhamos os mixins para tratarmos mais tarde. Só quero perguntar se temos certeza de que essa sintaxe funciona da maneira que queremos para tudo. Não há nada de errado em revisitar a questão se acharmos que ela não funciona ou é deselegante para alguns usos. LESS existe há muito tempo sem extensão. É mais importante acertar do que fazer rapidamente.

Então, estamos bem com isso?

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

parênteses dentro de parênteses -: extend (.some-mixin ()) - realmente não me incomoda muito, especialmente porque: extend (.some-selector) já está estabelecido

Sim, é verdade e, na verdade, já temos precedentes para parênteses duplos em Less.js também, E com a sintaxe de extensão existente. E o precedente que já foi estabelecido não é tão fácil aos olhos quanto o que estamos sugerindo com os mixins. Atualmente, podemos fazer isso:

.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;
}

Você encontrará até mesmo parênteses aninhados na sintaxe CSS existente .

Portanto, aqui temos os _parênteses aninhados_ e a sintaxe de _pseudo-classe_ aninhada. E eu não tenho nenhum problema com isso, é claro IMO.

Então eu concordo com @DesignByOnyx , essa era minha proposta original e parecia desagradável para os outros por algum motivo, então eu estava tentando encontrar outra sintaxe. Mas eu sou totalmente a favor de usar a sintaxe mixin antiga regular dentro dos parênteses da extensão.

Na verdade, a sintaxe original permitiria que várias classes ou mixins separados por vírgula fossem estendidos.

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

Faz o trabalho e é apertado. Não há queixas aqui.

Então, estamos bem com isso?

sim. completamente. Já é assim no CSS. Então, estou bem com isso.

sim. completamente. Já é assim no CSS. Então, estou bem com isso.

ASSIM DEVE SER APROVADO.

Pergunta, eu não acho que atualmente temos suporte para vários seletores em: extend, então estou me perguntando onde a palavra-chave "all" se encaixaria nesse formato, mas isso provavelmente deve ser parte de um problema separado.

Você apresentou seu caso, Sr. Schlinkert. Você deveria ter entrado em Direito. ;)

Não acho que atualmente temos suporte para vários seletores em: extend

Mas nós fazemos ;-) Eu fiz isso extensivamente. Acabei de fazer isso 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%);      
    }
  }
}

Você apresentou seu caso, Sr. Schlinkert. Você deveria ter entrado em Direito. ;)

Pfft, lol oh, pare!

Só quero acrescentar que acho que esta sintaxe:

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

é ótimo. Eu não acho os parênteses estranhos em tudo.

Mas, principalmente, eu só quero que vocês se apressem para que eu possa fazer todas as coisas legais em que estou trabalhando no SASS no meu pré-processador favorito: D

Obrigado pelo seu feedback, @mgerring !

1 Esperando por este recurso. Mantenha o bom trabalho :)

Para a postagem original:

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

Talvez isso não funcionou na hora da postagem? Mas isso resulta em algo muito próximo do que você queria:

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

@aaronmw , Sim, seu exemplo faz o mesmo, mas o ponto-chave desta proposta é a capacidade de estender um mixin definido em outro lugar (ou seja, quando você não pode ou não quer modificar o próprio mixin, por exemplo, outro arquivo, compartilhado biblioteca etc.)

Sim, de acordo com o ponto de @ seven-phase-max, isso pode ser feito da maneira que você descreve, mas não é idiomático.

Certo - desculpe, eu li muito mais sobre este tópico agora e vejo o que estamos buscando. A classe "esqueleto" que usei é apenas lixo na saída compilada porque a classe .clearfixed nunca seria explicitamente referenciada fora do mixin. &: extend (.clearfix ()) faz sentido para mim agora e é muito interessante. Por enquanto, vou lidar com as classes de esqueleto que afetam meu CSS.

Grande discussão aqui!

: +1:

Então, quando podemos esperar esse recurso? É muito útil para conceitos como OOCSS criar construções como uma "classe abstrata".

  • decidir como lidamos com aninhamento / escopo e mixin vs classe normal, por exemplo
.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?
  • lidamos com argumentos? combinamos mixins com os mesmos argumentos?
  • mude para-css-visitor para não remover as definições do mixin
  • faça com que o visitante estendido visite as definições do mixin e crie um novo conjunto de regras com a nova classe

Acho que a parte mais difícil é decidir _exatamente_ como deve funcionar.

decidir como lidamos com aninhamento / escopo e mixin vs classe normal, por exemplo

Eu tentaria interpretar a extensão mixin desta forma:
.b:extend(.a(1, 2, 3)) {} deve se comportar da mesma forma que criar um mixin não paramétrico anônimo (ou seja, seletor simples) no escopo de 'b' que chama .a(1, 2, 3) internamente e então estendido da maneira usual, isto é:

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

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

deve ser igual a este:

.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) {}

exceto nenhum #__ anon_a_1_2_3 aparece na saída. Acho que essa abordagem deve torná-la menos ou mais direta, sem inventar quaisquer regras especiais.

Assim, aplicando o conceito acima ao exemplo #thing .a , obtemos o seguinte:

.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 outro lado, os "parênteses opcionais" são algo muito pequeno de um ponto de vista prático, então também pode ser OK torná-lo mais estrito e exigir parênteses para mixins paramétricos dentro de extend (não há pressão sobre extend para herdar a sintaxe de chamada do mixin simples, já que não será totalmente compatível de qualquer maneira).

combinamos mixins com os mesmos argumentos?

Idealmente, sim, caso contrário, tornará a coisa toda inútil, por exemplo:

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

deve criar:

.b, .c {color: green}

Hmm, parece que a fusão será a coisa mais difícil de implementar.


Outro problema é o escopo, como surgiu recentemente em # 1730, os mixins usam o caminho de escopo 'relativo' e os usos de extensão 'absoluto', então temos uma espécie de conflito ao combinar os dois:

.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()) {} // -> ???
}

E é ainda mais confuso se reescrevermos este exemplo com mixins paramétricos.

Eu gostaria de oferecer meus dois centavos para dizer que este pode ser um bom momento para dar um passo atrás e dizer "como devem ser usados ​​mixins estendidos" - e eu acho que @donaldpipowitch está certo, está dizendo que traz um pouco da habilidade OOCSS . Como tal, não acho que devemos ficar muito atolados em como as subclasses ("propriedades", se preferir) serão estendidas de dentro da própria classe. Assim, por exemplo, os usuários terão certas "classes" (componentes) com "propriedades" (seletores aninhados):

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

Não acho que devemos nos concentrar em situações em que um usuário deseja fazer o seguinte:

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

Este não é apenas um cenário de caso marginal IMO, mas o usuário deve escrever seus estilos assim de qualquer maneira:

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

O caso de uso de 99,8% para estender mixins é permitir que os desenvolvedores tenham suas enormes bibliotecas LESS cheias de estilos que acumularam ao longo dos anos. Esta enorme biblioteca estará cheia de coisas 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 ...]

E eles podem se concentrar em estilos de escrita:

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

Eles poderiam até fazer isso, se quisessem, e nenhum dos estilos "modais" sequer estaria presente na saída final porque eles não estão sendo usados ​​neste projeto:

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

Sim, acho que @DesignByOnyx tem

@DesignByOnyx e @calvinjuarez não podemos simplesmente descobrir isso mais tarde .. tem que ser codificado de uma forma ou de outra. Se saltarmos para uma solução e decidirmos alterá-la mais tarde, introduziremos alterações significativas, o que não é bom.

se pudermos trabalhar em uma abordagem que não ofereça suporte a cenários marginais, estou mais do que feliz, isso é mais ou menos o que acabamos fazendo com o suporte estendido principal (ele pode ser expandido por mais palavras-chave, se necessário), mas precisamos de um plano para o que é suportado e como.

@ seven-phase-max na veia acima, eu ficaria feliz em ignorar os mixins paramétricos por enquanto.

Hmm, parece que a fusão será a coisa mais difícil de implementar.

  • mas está se fundindo? Eu usaria a mesma abordagem que as extensões existentes, por exemplo, ele encontra uma correspondência e anexa a ela .. então não está mesclando tanto, mas colocando ambas as extensões em um terceiro lugar, o mixin, que é então produzido como um especial caso em seu genCSS

Eu também acho que o segundo exemplo de @ seven-phase-max sobre o escopo provavelmente afetará alguém - você só precisa de um mixin e um mixin paramétrico vazio com o mesmo nome.

@lukeapage : +1: Verdade, eu posso

Na verdade, acho que @ seven-phase-max acertou. Então: +1: lá também.

@lukeapage - Eu não estava tentando defender um tipo de solução "de um jeito ou de outro", mas sim uma abordagem que (como você disse) não suporta casos marginais. Na verdade, já ultrapassamos a capacidade de escopo "local" e entramos na fase "tarde demais para voltar" IMO porque :extend funciona assim:

.block { color: green; }

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

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

Não vejo nenhuma razão para que o código a seguir funcione de maneira diferente do anterior - a vantagem é que não há .block classe na saída final:

.block() { color: green; }

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

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

A propósito, há um ligeiro desvio em nossas convenções de nomenclatura :) por exemplo, para mim, "mixins paramétricos" significa qualquer mixin definido com parênteses, incluindo aqueles com 0 parâmetros (ou seja, .mixin() {} é um "paramétrico"). E o mixin "não paramétrico" é apenas um seletor simples (ou seja, .mixin {} ). Até agora, acho que esse desvio não criou nenhum mal-entendido (por exemplo, na maioria dos exemplos acima, ficou claro pelo contexto se .mixin() {} foi referido como um mixin "não paramétrico"), mas ...
Não perca que na documentação um seletor simples também é chamado de "mixin" (assim que é misturado) e também é um mixin "não paramétrico" por design. Portanto, referir-se a .mixin() {} como sendo apenas "não paramétrico" pode ser bastante ambíguo (Tecnicamente a diferença está na presença ou na falta de definição dos parênteses e não no número de argumentos).
OK, este foi o meu boo-boo-boo usual. :)

@lukeapage

Eu ficaria feliz em ignorar os mixins paramétricos por enquanto.

Ou seja, não suporta extensão para mixins com parâmetros diferentes de zero? Estou bem com isso. Eu estava apenas tentando estimar como isso poderia ser implementado (de uma maneira unificada, sem delimitar mixins de parâmetros zero e diferentes de zero, de modo que não seja um obstáculo quando / se o último entrar eventualmente).

mas está se fundindo? Eu usaria a mesma abordagem que as extensões existentes, por exemplo, ele encontra uma correspondência e anexa a ela.

Certo, acho que estava pensando mais sobre as possíveis dificuldades com a fusão de extensões de mixins com args reais: por exemplo:

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

Por outro lado, suspeito que também haja surpresas ocultas com mixins de parâmetro zero, por exemplo:

.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 :)

Bem, talvez isso seja muito profundo (e também muito pequeno para se preocupar com isso no momento).

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

Com o pensamento de que "uma vez que, neste exemplo, .d() é paramétrico, não deve criar dois .f blocos"?

Sim, eu posso ver seu ponto, visto que um mixin resultaria em:

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

IMHO Se fizer sentido fazê-lo em etapas, talvez apenas explique isso, mas eu _não_ implementaria algo para evitar uma reclamação em si. Claro, este é apenas o meu 2c. E se for implementado com o comportamento que você descreveu, você poderia - no momento de adicionar o recurso - também criar uma solicitação de recurso para "mesclar blocos CSS de seletores estendidos", apenas para evitar as reclamações ...?

mas eu não implementaria algo para evitar uma reclamação em si.

Estou absolutamente de acordo. Estou apenas tentando prever quaisquer surpresas que podem se tornar uma daquelas "tarde demais para mudar" ainda mais.

: +1: sim, gosto de como você pensa!

Eu gosto que essa discussão ainda esteja acontecendo. Deixe-me voltar a alguns dos pontos desta discussão. Primeiro, no que diz respeito ao uso geral, isso tem sido igual.

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

Com a exceção de que .mixin {} obtém a saída como uma classe. Eu sei que no analisador eles provavelmente são tratados de forma diferente, mas em uso, eles descartam os pares propriedade / valor.

Significado:

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

Por causa desse histórico de sintaxe Less, faz sentido eu ser capaz de fazer isso:

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

Para mim, isso não é controverso, como já falamos frequentemente: estender como uma substituição imediata de muitas instâncias do uso do mixin original.

Para o leigo, isso provavelmente seria intuitivamente idêntico, porque .mixin1 pode ser historicamente referenciado da seguinte maneira, quer seja escrito entre parênteses ou não:

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

Então, eu esperaria isso:

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

... para produzir ...

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

Se o mixin for definido duas vezes, ele será substituído duas vezes quando estendido, assim como seu irmão, o seletor de classe.

.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;
}

É essencialmente assim que o extend funciona agora se você remover os parênteses nas definições do mixin, exceto, é claro, que o nome do mixin aparecerá na saída, então faria sentido seguir o comportamento existente do extend.

Com parâmetros (meu caso de uso de 90%), a mesma coisa, exceto que eles são diferenciados pela 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 mim, a razão para estender os mixins é agrupar os parâmetros, levando a bibliotecas de mixins mais poderosas que podem produzir uma saída muito concisa. Usá-los para mixins sem parâmetros não é tão importante, já que eu poderia simplesmente usar os recursos existentes do Less hoje para produzir o resultado desejado.

Obrigado a todos por continuarem a levar isso adiante. Acho que pode ser uma adição muito poderosa.

: +1 Obrigado @ matthew-dean pela análise abrangente - concordo com tudo o que você abordou. Você poderia opinar sobre este cenário, que é um dos temas de discussão recente:

.mixin() { color: red; }

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

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

Da forma como o LESS funciona atualmente, apenas mixins no escopo global são estendidos - o que significa que os estilos vermelhos seriam estendidos. Pessoalmente, estou bem com esse comportamento e, embora seja provável que alguém escreva o código acima e espere que os estilos azuis prevaleçam, acho que o comportamento "global" de extends é uma linha na documentação.

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

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

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

Eu acho que o comportamento "global" de extends é uma linha na documentação.

Totalmente de acordo. Acho uma péssima ideia introduzir uma área cinzenta aqui.

Para mim, é a consistência que é importante. Se o comportamento atual não estende os seletores no escopo local, nem deveria com mixins. Se posteriormente estendermos os seletores no local, os mixins também devem. As pessoas devem ser capazes de confiar em um padrão de: extend que é para toda a biblioteca.

(Embora eu pudesse ter dito de forma mais concisa: "+1 no comentário de @jonschlinkert ". ;-)

Nesse ponto, alguém pode fornecer um caso de uso que torne esse recurso confuso? Comece com esta visão geral abrangente de @ matthew-dean e as respostas a seguir e tente oferecer uma situação do mundo real que não foi abordada.

Boas festas. Feliz Natal. Felices Fiestas!

Visão geral realmente agradável. Eu concordo com @ matthew-dean e todos os comentários seguintes. : +1:

Eu também concordo com @ matthew-dean. Ele parece um sujeito bacana e gostaria de apertar sua mão.

(-Anônimo)

@ palavra matthew-dean. : +1:

Poderíamos deixar o código do sistema de grade do Bootstrap muito mais limpo com esse recurso!

: +1: concordou @cvrebert! seria bom!

Apenas revisitando. Acho que temos quase um consenso e só precisamos de implementação, correto?

Estou tentando encontrar mais informações sobre isso, mas é como um labirinto lendo tudo. Isso alguma vez foi implementado? Se sim, alguém pode gentilmente indicar a área apropriada nos documentos.

@ josh18 Não, quando uma solicitação de recurso ainda está aberta, isso geralmente significa que não foi implementada.

Ok, obrigado, pensei em verificar novamente para o caso de estar faltando alguma coisa.

Estou planejando em algum momento resumir recursos abertos / a serem implementados no Wiki, mas ainda não tive tempo.

Estou planejando em algum momento resumir recursos abertos / a serem implementados no Wiki, mas ainda não tive tempo.

@ matthew-dean +1

Oi, pessoal! Até onde eu entendo, esse recurso será um tanto semelhante aos marcadores de posição do SASS. Só queria saber quando isso será implementado?

Oi,
Acho difícil prever meu tempo e outros colaboradores apenas
implementar coisas em que estão interessados, então não tenho certeza. Tudo que posso dizer é
que consideramos alta prioridade, é a próxima grande coisa na minha lista.

Obrigado pela sua resposta. Estou ansioso para ver isso implementado e funcionando. :)

1 para este recurso. É extremamente útil para reduzir o tamanho do CSS.

1 para este recurso.

1 para este recurso.

1 assistindo com interesse, obrigado!

: +1:

já se passaram DOIS ANOS desde que esse problema foi criado. Tag de alta prioridade desde novembro de 2014. Milestone é 1.6.0 ou 2.0.0. Excelente. Menos é 2,5 agora.

@Grawl

Quer dizer que você está pronto para fazer um PR?

@ seven-phase-max Isso é basicamente o que eu pensei. Essa exibição de direito. ;)

@ seven-phase-max lol no, sou apenas frontend / designer.
@Celc parece muito ruim 😅

já se passaram DOIS ANOS desde que esse problema foi criado.

Sim, pelo que estou pagando a vocês, afinal? ;-)

Infelizmente não posso ajudar com a participação, mas eu voto bastante positivo neste pedido!

Esta é uma funcionalidade extremamente importante para a construção de estruturas complexas e eficazes

3 anos e contando. Felizmente, o Sass v4 está chegando (com funções prefixadas sass-* ) e posso me livrar do Less.

@stevenvachon Não

Claro, solicitações pull são bem-vindas, de qualquer pessoa. Teremos prazer em mesclar a solicitação de pull funcional com esse recurso.

Não estou tentando machucar ninguém, na verdade provavelmente estou tentando prevenir isso. Acho que é melhor expressar como a pessoa pode se sentir e os novos rumos que pode estar tomando como resultado. Acho que é melhor saber mais cedo ou mais tarde; antes que todos saiam. Por exemplo, o Bootstrap v4 não usará Less.js e tenho certeza de que isso afetará muito sua base de usuários. Você pode ignorar essa política o quanto quiser, é claro.

@stevenvachon por que tão offtopic? Sass e Less são ótimos. Eu amo o puro JS de menos. node-sass precisa de um compilador ac para ser instalado, o que pode ser uma dor dependendo do ambiente. Eu usei o recurso: extend que já vem embutido no LESS e atende a todas as minhas necessidades. Eu nem sei por que esse problema ainda está aberto.

Caramba, eu sou um desenvolvedor de rails e uso gulp + LESS quando não é um projeto ruby.

Fora do assunto? Este recurso não é implementado há 3 anos e seria muito útil.

Eu preferia que o Sass fosse escrito em JS, mas não é, e isso não é o mais importante. Suas características são. Sass nos permite estender espaços reservados, mas Less não nos permite estender mixins.

Cara, não é nada offtopic, mas um recurso altamente antecipado! (Mesmo que eu prefira menos de qualquer maneira, por várias razões)

Simplesmente implora para ser feito.

PS: No meu caso, eu sou um designer com apenas algum conhecimento de js, principalmente coisas relacionadas ao dom, muito longe de ser um desenvolvedor que pode contribuir para a base de código less.js. O que é uma história triste de qualquer maneira)

Apenas um apoiador extremamente interessado do projeto)

Anúncio de serviço público

A qualquer momento, você pode enviar uma solicitação pull ou trabalhar com um desenvolvedor para obter uma, e é muito provável que esse recurso seja integrado. A biblioteca Less.js precisa de contribuições mais regulares de indivíduos como as pessoas neste tópico . Não é responsabilidade de ninguém. É totalmente dependente de uma pessoa ver este tópico, ou precisar desse recurso, e dedicar um tempo para que isso aconteça.

Se sua resposta for que você não é um desenvolvedor, existem muitas OUTRAS maneiras de apoiar este projeto em funções não desenvolvimentistas, seja fornecendo a documentação necessária para novos recursos ou suporte de design no site, executando testes, fornecendo feedback sobre problemas, gerenciamento de projetos, respondendo a perguntas no Stack Overflow, escrevendo posts de blog, tweetando sobre Less, contribuindo para CSS e comunidades da web e escrevendo bibliotecas Less.

Muitas dessas tarefas estão sendo realizadas por indivíduos que são desenvolvedores, portanto, o tempo que poderiam estar contribuindo para o desenvolvimento é gasto nessas outras tarefas.

Se você _é_ um desenvolvedor e sua resposta for: "Não tenho tempo", então esse é o motivo exato pelo qual este problema está aberto. Depende 100% de você se um recurso é concluído, portanto, perguntar por que ele não foi concluído por "alguém" não é útil. _Você é esse alguém._ Vai acontecer, eu garanto_ que vai acontecer, se e quando você se envolver neste projeto. Você pode se envolver com uma das ferramentas de código aberto mais populares da web. Você pode fazer a diferença na vida de ... milhares? Centenas de milhares? Milhões? E como um benefício colateral, você pode garantir que seus recursos favoritos aconteçam mais cedo ou mais tarde.

Se você quer que esse ou qualquer recurso aconteça, faça acontecer . Nós amaríamos ter você. Adoraríamos trabalhar com você! Menos pode ficar cada vez melhor à medida que esta comunidade cresce!

E, ouça, eu aprecio que às vezes as pessoas realmente não têm absolutamente nenhum tempo para contribuir e ainda assim gostariam que um determinado recurso acontecesse. Isso é bom. Eu diria apenas que, se você está nesse cenário, busca empatia e gratidão pelas pessoas que doam seu tempo (e às vezes dinheiro) para ajudá-lo, e tenho certeza de que outras pessoas na comunidade Less farão o melhor para continue a fazê-lo, conforme for possível.

Sinceramente,
Matthew Dean, membro da equipe principal do Less.js

Já apoio meus próprios projetos e ouço seus pedidos de recursos. Sinceramente, não tenho tempo para mergulhar no núcleo do Less.js.

Para aqueles que vêm aqui para obter suporte de espaço reservado sass (ou "classe silenciosa"), leia este comentário . Não vai te levar até lá (devido ao # 1851 e ter essas classes não em um arquivo "referenciado"), mas é melhor do que nada.

Esta página foi útil?
0 / 5 - 0 avaliações