4

Mixins with LESS are really simple:

.some-rules() {
  /* some rules */
}
.some-class {
  .some-rules;
}

However, suppose I've got a ruleset within a media query, like:

@media (min-width: 800px) {
  .my_ruleset {
    /* more rules */
  }
}

How can I include such a ruleset as a mixin?

My motivation here is that I am using Bootstrap. I am trying to avoid semantically polluting my markup with its selectors, and would rather incorporate its rulesets as mixins. That's simple enough given the first example above, but I'm not sure how to incorporate the @media selectors.


EDIT

Specifically, here is a summary of the code I am trying to use as a mixin:

.container {
  .container-fixed();
}

// ...

@media (min-width: @screen-sm) {
  .container {
    max-width: @container-sm;
  }

  // ...
}

@media (min-width: @screen-md) {
  .container {
    max-width: @container-md;
  }

  // ...
}


@media (min-width: @screen-lg-min) {
  .container {
    max-width: @container-lg;
  }

  // ...
}
Dmitry Minkovsky
  • 36,185
  • 26
  • 116
  • 160
  • What happens if you simply include it as a mixin? – SLaks Sep 01 '13 at 22:43
  • Not sure how I could do that. The mixin syntax is like `.selector[([args])]`. Concretely, I am trying to use `.container` from Bootstrap. It's extended by several `@media` queries, like say https://github.com/twbs/bootstrap/blob/master/less/grid.less#L118 and https://github.com/twbs/bootstrap/blob/master/less/grid.less#L196. You see those `@media` queries are, furthermore, parametric. Adding something like `@media (min-width: @screen-md);` to my selector doesn't work. – Dmitry Minkovsky Sep 01 '13 at 22:53
  • In LESS, `.container()` is the same thing as `.container`, which is the insufficient case in my question above. – Dmitry Minkovsky Sep 02 '13 at 00:55

3 Answers3

6

Just simply add:-

.my_ruleset {
    /* more rules */
  }

@media (min-width: 800px) {
  .my_ruleset;
}

If you want to add parameters to this for instance then:-

.my_ruleset(@myMargin:5px;) {
    margin:@myMargin;
  }

@media (min-width: 800px) {
  .my_ruleset(10px);
  /* New Rules*/
}
.
.
/* And so On */

Update:-

if you want to adapt this in a dynamic form take whole media query into mixin and play with it...

.container(
    @minSize:768px; 
    @maxSize:979px; 
    @myColor:green;
        /* So on */
) {
    @media (min-width: @minSize) and (max-width: @maxSize) {
      .my_ruleset {
            background-color:@myColor;
      }
      /* New Rules*/
    }
}

.container(0px,480px,black);
.container(481px,767px,blue);
.container(768px,979px,pink);
.container(980px,1200px,white);
.container(1700px,2200px,red);
SaurabhLP
  • 3,619
  • 9
  • 40
  • 70
  • Hi @SaurabhLP, thanks for the answer. I don't think this will work with my situation, though. I edited my question to include specific (and hopefully easy to understand) explanation of my problem. – Dmitry Minkovsky Sep 02 '13 at 13:48
  • @dimadima your idea is right, you can also use whole media query as a mixins... check my update... – SaurabhLP Sep 03 '13 at 06:21
2

EDIT

Checkout these two answers (class set in media query, media query grouping), I feel like they are very closely related to your question. Looking at the second answer I tried to put something together. The snippet is below, but you can also see a demo.tar.gz I put together as well.

main.less

@import "less/bootstrap"; /*Obviously, make sure to have all the less src :)*/

/*source: http://tinyurl.com/less-query */
.make-container(@min-width) {
  @media (min-width: @min-width) {
    .page-maker(@max-width) {
      .page {
        max-width: @max-width;
        .container-fixed();
      }
    }
    .make-page-style() when (@min-width=@screen-lg-min) {
      .page-maker(@container-lg);
    }
    .make-page-style() when (@min-width=@screen-md) {
      .page-maker(@container-md);
    }
    .make-page-style() when (@min-width=@screen-sm) {
      .page-maker(@container-sm);
    }
    .make-page-style();
  }
}
.make-container(@screen-sm);
.make-container(@screen-md);
.make-container(@screen-lg-min);

HTML

...
<body>
<div class="page">
...
</div>
...

OLD

have you tried using the following mixins (n is the number of columns):

.make-row()

.make-lg-comun(n)

.make-md-column(n)

.make-xs-column(n)

These mixins are used to semantically structure the page. For example, if you have the following markup:

<div class="main">

<div class="left">

</div>

<div class="right">

</div>

</div>

then in your less you can do:

.main{
.make-row();
}

.left{
.make-lg-column(5); /* makes five large desktop column */
}

.right{
.make-lg-column(7);
}

if this is not what you are looking for, perhaps elaborate on your intent more, maybe you won't need to do a lot of media queries.

Community
  • 1
  • 1
AJ Meyghani
  • 4,389
  • 1
  • 31
  • 35
  • Thank you for the suggestion. Just looked at those mixins. They're useful, but not as `.container` (or, `.container-fixed(), because `.container` is just a wrapper around `.container-fixed()`) replacements because they don't provide centering. They perform the functions that they're for, which is to size columns inside a row, possibly inside a container. My intention is to have a container that's centered on the screen and is responsive (which is why I don't want to lose the media queries). – Dmitry Minkovsky Sep 02 '13 at 01:07
  • I updated the answer with some relevant links that might help you with your question. This was something that also bothered me at some point as well. Take a look at the demo as well if you want. It might not be the best solution but I guess it could be a start. I looked at the compiled css and it does not seem to produce extra css, but it works. – AJ Meyghani Sep 02 '13 at 04:39
  • Yes, actually, thank you. There's a pull request to the Bootstrap repository that implements it: https://github.com/twbs/bootstrap/pull/10160, and I submitted my own slightly simpler version https://github.com/twbs/bootstrap/pull/10483 – Dmitry Minkovsky Sep 09 '13 at 01:18
0

You can use parent selector:

  @screen-sm: 400;
  @screen-md: 800;
  @screen-lg-min: 1000;

  .responsive(@width-sm, @width-md, @width-lg) {
    @media (min-width: @screen-sm) {
      & {
        max-width: @width-sm;
      }
    }

    @media (min-width: @screen-md) {
      & {
        max-width: @width-md;
      }
    }

    @media (min-width: @screen-lg-min) {
      & {
        max-width: @width-lg;
      }
    }
  }

  .container {
    .responsive(100px, 200px, 300px);
  }

Output:

@media (min-width: 400) {
  .container {
    max-width: 100px;
  }
}
@media (min-width: 800) {
  .container {
    max-width: 200px;
  }
}
@media (min-width: 1000) {
  .container {
    max-width: 300px;
  }
}