Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

possible conditions? #191

Closed
panicnot opened this issue Feb 4, 2011 · 12 comments
Closed

possible conditions? #191

panicnot opened this issue Feb 4, 2011 · 12 comments

Comments

@panicnot
Copy link

panicnot commented Feb 4, 2011

is it possible to add if conditions into Parametric Mixins?

@cloudhead
Copy link
Member

nope. I'm experimenting with pattern-matching to achieve similar results in a more declarative way.

@rconnamacher
Copy link

I'd also like to see support for conditionals, using a syntax similar to CSS @media. They'll be very useful when using node.js to target different device types.

Say I have a less file that's intended for both mobile and desktop use. Mobile browsers have limited bandwidth but very modern CSS support, while desktop needs to retain a lot of hacks for old browsers (especially IE).

So, in the base LESS file, have the following:

@output: "mobile";

(or @output: "desktop")

Then, in a gradient mixin from an included file:

.vertical-gradient(@top, @bottom) {
    @when (@output: "desktop") {
        background: -moz-linear-gradient(top, @top, @bottom);
        background: -o-linear-gradient(top, @top, @bottom);
        -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='@{top}', EndColorStr='@{bottom}');";
        behavior: url('/path/to/IE/hack');
    }
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0, @top), color-stop(1, @bottom) );
    background: linear-gradient(top, @top, @bottom);
}

This way desktop browsers get the full cross-browser shebang, but mobile browsers only get what's broadly supported for mobile.

Likewise, I could envision this for a few more use cases:

  • Creating a block with header logos or other background images, using a conditional to serve smaller images to mobile browsers than to desktop. While it's possible to do with @media queries, the default images would be loaded along with the smaller targeted images, causing the page to load slowly. Using server-side conditionals would cause pages to load much more quickly.
    • Adding boolean flags to mixins, such as @enable-ie-hacks to control mixin output on a case-by-case basis.

(If people don't like @when, @if could also be the keyword. I think @when feels more css-y.)

@cloudhead
Copy link
Member

But how would the compiler know where the file will be used?

@matthew-dean
Copy link
Member

@cloudhead - I think what he's saying is there's tons of instances where we want to create a LESS library, like Bootstrap, etc. In order to do that, we want to turn on / off (or reconfigure) sections of LESS code based on a single variable. I think the use of "mobile" and "desktop" are just arbitrary values that are being changed in a template, not dependent on environment.

There's a lot that I'd like to do with LESS, but I'm holding off on creating reusable libraries, because it seems far too complex without conditionals. I'd want a user to easily change a set of variables, and then change included code / color schemes, gradient choices (or lack of gradients), put light text on dark, or dark text on light backgrounds based on some simple choices.

Without conditional statements, LESS code is actually MORE complex than it would be with it.

I understand the desire to make things simple and declarative, but I think simple conditional statements is the most important thing for creating a thriving LESS ecosystem.

@cloudhead
Copy link
Member

I'm experimenting with mixin 'guards' (inspired by functional languages), they should allow the same power as conditionals, without the atrocity of @if/@end blocks inside the stylesheet. There is working code in master, but I'm going to need some feedback and simple use-cases as the implementation is not complete yet. Here's what it looks like:

.mixin(@a) ? @a < 0 {
    ...
}
.mixin(@a) ? @a > 0 {
   ...
}
.mixin(@a) {                    /* the value of @a doesn't matter */
   ...
}

.class {
     .mixin(-1); /* this will include the first and last mixin */
     .mixin(0); /* this will include the last mixin */
     .mixin(5); /* this will include the second and last mixin */
}

Currently it only works with numbers, but I can easily extend it to other things. Looking at the example above, I could add string and keyword matching, allow the var to be a global, and it would do the trick:

/* NOT IMPLEMENTED */
@output: mobile;

.mixin () ? @output = desktop {
   ...
}
.mixin () ? @output = mobile {
  ...
}

@matthew-dean
Copy link
Member

Hmm.... That's an interesting approach. So, essentially, you're overloading mixins. (At least, that's what C# calls it.) Looks pretty awesome.

It looks similar to JavaScript's conditional operators. You could also easily extend it to variables.

@theme: 'light';
@lightText: #AAA;
@darkText: #333;

@text: @theme == 'light' ? @lightText : @darkText;
// or direct assignment
color: @theme == 'light' ? @lightText : @darkText;

@matthew-dean
Copy link
Member

Maybe if you had an experimental branch, I could add a preferences panel in Crunch for people who want to use the alternate compiler (toggling on/off the experimental build). So, you could get some people doing tests immediately in a GUI environment. As long as I could push out documentation from somewheres in Crunch, it would let people try out new features. Any, that's just a tangent, but I love the progress so far!

@cloudhead
Copy link
Member

Yea, it is a form of overloading, except based on a runtime value. Here's where it comes from: http://en.wikipedia.org/wiki/Guard_(computing).

So far I haven't needed to change anything in the language, this is more of an addition, ie: everything from 1.1.6 should work just fine with the inclusion of mixin guards, and I want to keep it that way. So you could consider the current master branch to be an experimental version, compared to 1.1.6.

I'll keep working on it, probably adding support for strings and keywords soon.

Also note that there is an implicit matching, the equivalent of an =, when a non-variable is included as the arguments:

.mixin(mobile, @var) { ... }
.mixin(desktop, @var) { ... }

@env: mobile;

.class {
  .mixin(@env, 42); /* will include the 1st mixin only */
}

This is somewhat cleaner and better in certain circumstances.

@matthew-dean
Copy link
Member

Wow, that is crazy sweet. Can't wait to try it out!

@alixaxel
Copy link

alixaxel commented Jan 1, 2012

This seems awesome, good job.

@quasiperfect
Copy link

could this be done ?

.border-radius(@a:5px,@b:@a,@c:@a,@d:@a) {
    border-radius:@a ((@b <> @a)?(@b):(@a))  ((@c <> @a)?(@c):(@a)) ((@d <> @a)?(@d):(@a));
}

or is is possible now can someone give a example ?

@lukeapage
Copy link
Member

this appears closed by the introduction of mixin guards.

strk pushed a commit to CartoDB/carto that referenced this issue Nov 2, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants