3

I'm trying to use LESS to dynamically generate a set of mixins that would help me write cleaner media query code. So far in my limited knowledge of the language I've put together code that looks like this:

@sizes: xxs, xs, sm, md, lg;

.mediaQueries(@iterator:1) when(@iterator <= length(@sizes)) {

    //Extract name
    @sizeName: extract(@sizes, @iterator);

    //Attempt to build min-width query 
    .MQ-min-@{sizeName} (@content) {
      @media (min-width: @screen-@{sizeName}) {
        @content();
      }
    }

    //Attempt to build max-width query 
    .MQ-max-@{sizeName} (@content) {
      @media (max-width: @screen-@{sizeName}) {
        @content();
      }
    }

    .mediaQueries((@iterator + 1));
}
.mediaQueries();

The goal is to have a set of mixins that would allow me to easily and cleanly define some CSS properties for a specific breakpoint, like so:

.generic-class {
  background: black;
  //Sizes @screen-sm and up 
  .MQ-min-sm({ 
    background: transparent;
  })
}

It doesn't work. Something to note, I'm trying to interpolate the size name into a variable name that would then output me a the px value of that variable into the @media query. Is something like this even possible?

Otherwise my compiler currently breaks on the start of the nested mixin (.MQ-min-@{sizeName} (@content) {) with the error:

Potentially unhandled rejection [2] Missing closing ')' in file ../mixins.less line no. 43

Is something like what I'm trying to achieve possible?

Harry
  • 87,580
  • 25
  • 202
  • 214
styke
  • 2,116
  • 2
  • 23
  • 51
  • What is the code in line 43? – Marcos Pérez Gude May 12 '16 at 10:49
  • Start of the first nested mixin - `.MQ-min-@{sizeName} (@content) {` – styke May 12 '16 at 10:50
  • Have you got any autoprefixer? Searching in google seems to be the problem. But there are not enough information. – Marcos Pérez Gude May 12 '16 at 10:53
  • No you can't dynamically set the name of a mixin (which is why the `@content` will give error). You are tying to use selector interpolation which is designed for *selectors* and not mixin names. – Harry May 12 '16 at 10:53
  • @Harry why the error is `missing closing ')'`? It's not very explanatory :( – Marcos Pérez Gude May 12 '16 at 10:54
  • @Harry Ah damn. Any suggestions on solutions that don't involve me harcoding all the mixins for the names involved? – styke May 12 '16 at 10:54
  • @MarcosPérezGude: I agree but it is possibly because Less doesn't even expect such a syntax with selector interpolation. – Harry May 12 '16 at 10:55
  • @styke: What is the content of `@content`? I am still not clear on how you are trying to use this. Can you add a full use-case into the question so that I can see if there is an alternate way? – Harry May 12 '16 at 10:57
  • @Harry `@content` is a paramter used to parse a ruleset that is then to be outputted in the media query. I've updated the post with an example of the desired effect. – styke May 12 '16 at 11:03
  • @styke: I expected that but just wanted to be doubly sure before I post an answer with assumptions :) – Harry May 12 '16 at 11:15

1 Answers1

3

I think the simplest way for you to achieve this is by using a single parametric mixin like given below. This avoids the need for all those iterations, dynamic mixin creations etc.

@sizes: xxs, xs, sm, md, lg;
@screen-xxs: 100px;
@screen-sm: 200px;

.MQ(@content, @sizeName, @max-min) { /* get ruleset, size name and min/max as input */
  @selector: ~"(@{max-min}-width: @{screen-@{sizeName}})"; /* form the media selector */
  @media @selector { /* use it */
    @content();
  }
}

.generic-class {
  background: black;
  .MQ({ 
        background: transparent;
      }, /* ruleset */
      sm, /* screen size */
      max /* min/max */
  );
}

If the mixins are for your own usage then this is all that you need. If it is for distribution as library then you may want to put some guards on @sizeName and @max-min variables to restrict invalid values.

Note: Less compiler always had a problem with the interpolation here - @media (min-width: @screen-@{sizeName}) also (I am not sure if it has been addressed) and that's why I created a temp variable.

Harry
  • 87,580
  • 25
  • 202
  • 214