less / less.js

Less. The dynamic stylesheet language.
http://lesscss.org
Apache License 2.0
17.03k stars 3.4k forks source link

Mixins should accept LESS blocks #965

Closed rbu closed 10 years ago

rbu commented 12 years ago

It would be helpful if mixins had access to a content block passed to them, so one could encapsulate media queries or browser hacks in a central place and reference them symbolically.

This is basically the "Passing Content Blocks to a Mixin" feature of SASS: http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#mixin-content

In LESS this would mean something like:

.mobile() {
  @media all and (max-device-width: 480px) {
    @content
  }
}
.big-desktop-button {
  ...
  .mobile {
    display:none;
  }
}
GulinSS commented 11 years ago

+1

hubertgrzeskowiak commented 11 years ago

+1

jcc8 commented 11 years ago

+1 - Bounty here: https://www.catincan.com/bounty/mixins-should-accept-less-blocks-issue-965-less-less-js-github

Crowdfund issue & get merged into main branch to collect.

parisholley commented 11 years ago

Here is a SASS mixin library I wrote using display: table that I think shows a good idea of how powerful this feature could be (semantics aside). I'm obviously making many assumptions/compromises but there is so much more you can do with this type of functionality.

https://github.com/parisholley/tablespooncss

seven-phases-max commented 11 years ago

Just my +1 to support SomMeri's syntax proposal... We could also have another syntax for this kind of stuff (in addition to the "expanded rule at the point of assignment"):

.block {
    size: 2;
}

#use-something {
    .something(@variable);
    @variable: .block;
    /* ^ assign any arbitrary "name" to a variable (at this point nothing indicates
    that the variable points to a mixin - it's only a "raw" value and we can use
    it just as any other variable - for example putting it as a CSS property value) 
    */
}

.something(@value) {
    @value(); 
    // ^ now the parens show that variable's value
    // is a mixin name and we want to expand it here
}

The idea behind this syntax is a possibility to provide arguments for the expansion at any level if the variable points to a parametric mixin, i.e.:

.something(@value) {
    @a: 1;
    @b: 2;
    @value(@a, @b); 
}
seven-phases-max commented 11 years ago

I've just noticed a "minor" problem with 18462037's @variable: .block(); syntax. Look at it... Yes, it looks exactly like calling a .block function and assigning its return value to the @variable. And even if this feature ("mixin returning a value with direct assignment to a variable") is somewhat anticipated (?) for the moment or even barely appear in LESS at all, it would be a good idea to keep this syntax reserved just in case (as we never know how the things will evolve). After all, @variable: .mixin(); will confuse users if it has "not a function call" semantics.

So thinking of possible alternatives: Actually, as soon as we have a "{} block as a variable or mixin parameter" syntax, i.e.:

#use-mixin {
  .mixin(@variable);
  @variable: { /* ... */};
}
#short-expression-use-mixin {
  .mixin({ /* ... */ });
}

­­... we won't need any special syntax for a "named mixin assignment" as we'll be able to do it with:

#use-mixin {
  .mixin(@variable);
  @variable: {.block()};
}
#short-expression-use-mixin {
  .mixin({.block()});
}

And though @variable: {.block()}; or @variable: {.block}; are probably not absolutely equal to 18462037's @variable: .block(); (different points of expansion?) their results promise to be similar.

lukeapage commented 11 years ago

Just sketching and thinking about how this could be accomplished with mixin extends.. what do you think about this?

.a :extend(.b()) {
    .c {
        color: black;
    }
}
@media x {
    .b() {
    }
}
@media y {
    .b() {
    }
}

essentially you make a template, put your mixin in the template and then extend the template...

matthew-dean commented 10 years ago

Per discussion on other issue threads, +1 to @seven-phases-max's proposal of assigning mixins to variables.

nelsonpecora commented 10 years ago

I'll also +1 @seven-phases-max's proposal. The .mixin(@variable); / .mixin({ key: value; key: value; }); syntax feels very intuitive for me (in fact, I tried to use it before finding out it didn't work).

lukeapage commented 10 years ago

Implemented and will be in 1.7 release soon, see #1859. seperate issue for passing mixins.

katomonster commented 10 years ago

+1

nelsonpecora commented 10 years ago

By the by, I can confirm this is working in 1.7.

AndrewEastwood commented 9 years ago

is it working right now?

seven-phases-max commented 9 years ago

@AndrewEastwood See the docs.

AndrewEastwood commented 9 years ago

Thanks