Using Less Variables in Media Queries

LESS CSS set variables in media query?

It would be nice, but this is impossible to do like this.

LESS compiles your media queries to actual media queries, so at compile time there is no indication of which media query will be relevant to the browser.

After compile time you just have CSS not less so you can't have variables anymore.

You can do this instead but it isn't as elegant:

@base_width: 100px;

@media all and (max-width: 768px) {
.something {
width: @base_width;
}
}

@media all and (min-width: 769px) {
.something {
width: @base_width * 2;
}
}

Using LESS variables in media queries

Due to Math Settings

LESS by default expects math operations to be in parenthesis (strict-math=on). So your variable needs those around the values to calculate correctly, like so:

@layout-max-width: (@num-cols * @item-width + @margins);

Then your original code will output as you expect.

css, change less variable with @media

Since I don't seem to be getting a lot of support for closing this as a duplicate of this question, I'll essentially repeat my answer (with some variety).

Remember @media is a CSS query, not a LESS query

The @media query is a CSS capability that allows the currently loaded CSS to respond to the media it is being presented on (typically some type of browser, but could be print, etc.).

LESS is a CSS preprocessor that creates CSS before it is loaded into the browser, and thus before the media is ever being checked (which is done in the CSS itself, after it has been generated by LESS).

So the proper method for LESS is to have the same type of output as straight CSS, which means you have to repeat the .menu selector in the @media query so that its value changes for the media type.

Final CSS Output Should Be Something Like

@media only screen and (max-width: 400px) {
.menu {
width: 100px;
}
}

.menu {
width: 300px;
}

There are various ways to generate something like that with LESS. Strictly taking your basic format above, there is this:

@menu-width: 300px; // default size

@media only screen and (max-width: 400px) {
.menu {
width: @menu-width - 200px; /* assuming you want it dynamic to default */
}
}

.menu {
width: @menu-width;
}

But also look at:

  • For the basic idea of LESS media queries: How can I use media queries more efficiently with LESS?
  • For discussion of getting media queries grouped and less repetition of selector code, see: Media Query grouping instead of multiple scattered media queries that match

Media queries in less with variables-need global variables

You can sort of achieve this by using list arrays for each property and screen-width (like the below sample):

@BWInputHeight: '20px','40px','60px'; // Height of the button for min-width=320 and min-width=768 respectively
@minwidths: '320px','768px','1024px'; // The widths for which you need the media queries to be created

.loop-column(@index) when (@index > 0) { // Loop to iterate through each value in @minwidths and form the corresponding output
.loop-column(@index - 1);
@width: extract(@minwidths, @index); // extracts width based on array index
@media (min-width: e(@width)){
.dataTables_filter input{
height: e(extract(@BWInputHeight,@index)); // extracts button height for the corresponding screen width
max-width: 135px;
display: inline-block;
padding: 1px 6px;
margin-right: 15px;
}
}
}

.loop-column(length(@minwidths)); // calling the function

Demo in Code-pen - Modify output area width to see difference and click the eye icon in CSS tab to see compiled CSS.

Note: As per this Stack Overflow thread, both dotless and less.js should be 99% compatible and hence I have given this answer. In case this doesn't work for you, I will happily have this answer removed.

Fancy Media Queries with some LESS Magic

Here is what I've done in my projects:

@desktop:   ~"only screen and (min-width: 960px) and (max-width: 1199px)";
@tablet: ~"only screen and (min-width: 720px) and (max-width: 959px)";

@media @desktop {
footer {
width: 940px;
}
}

@media @tablet {
footer {
width: 768px;
}
}

This allows you to only define your media queries once and you can use it throughout your less files. Also a little easier to read. :)

Changing variable value based on media query

This is impossible, variables are assigned values when the Sass is compiled to CSS.

what you can do is this:

$avatar_size: 200px;$avatar_tablet: 150px;$avatar_mobile: 100px;
@media (#{$tablet_size}) { img { width: $avatar_tablet; height: $avatar_tablet; }}
@media (#{$mobile_size}) { img { width: $avatar_mobile; height: $avatar_mobile; }}

Pass Less.js variable into media query

As seven-phases-max stated in the comments above, strict math is implied within @media queries.

LESS - Strict Math

With strict math on, only maths that is inside un-necessary parenthesis will be processed.

Therefore you need to wrap the variables that you want to be evaluated within parenthesis:

@browser-main-and-sidebar: (@main-width + @main-spacer + @sidebar-width + @outer-padding * 2);

..or:

@media (min-width: (@browser-main-and-sidebar)) {
max-width: @browser-main-and-sidebar;
}

Both of which will compile to the desired result of:

@media (min-width: 940px) {
max-width: 940px;
}


@outer-padding: 20px;
@main-width: 600px;
@main-spacer: 10px;
@sidebar-width: 290px;
@browser-main-and-sidebar: @main-width + @main-spacer + @sidebar-width + @outer-padding * 2;

@media (min-width: (@browser-main-and-sidebar)) {
max-width: @browser-main-and-sidebar;
}

Using rulesets in LESS for media queries

//  Variables for MQ's
@mq-mobile-portrait: 320px;

// Mixins
.mobile-portrait-only(@rules) {
@media (min-width: @mq-mobile-portrait) {
@rules();
}
}

Now you can use the following code:

div {
color: white;
.mobile-portrait-only({
color: white;
width: 100%;
max-width: 500px;
});
}

The above will compile into CSS code as follows:

div {
color: white;
}
@media (min-width: 320px) {
div {
color: white;
width: 100%;
max-width: 500px;
}
}

So detached rules are rules between {} assigned to a variable:

@detached: {};

Detached rules can be used as an argument for a mixin:

.mixin(@detached){}

You as call the above mixin with a detached rule as a parameter:

.mixin({color: red;});

or

 @detached: {color: red;} // watch out for the last declaration wins rule for variables  
.mixin(@detached);

Inside the mixin you should call the detached rules set to copy its properties and selectors (in fact you don't copy but insert them read for processing):

.mixin(@detached-rules) {
@detached-rules(); // parenthesis are required here
}

Finally for your example your code should look like that shown below:

    @gum: url();
@white: white;

// Variables for MQ's
@mq-mobile-portrait: 320px;

// Mixins
.mobile-portrait-only(@rules) {
@media (min-width: @mq-mobile-portrait) {
@rules();
}
}

section.footer {
height: 90px;
padding: 0 10px;
.mobile-portrait-only( {
padding-top: 10px;
background: @gum;
div.ftrLogo {
display: inline-block;
margin: 0;
height: 70px;
width: 45%;
div.smlLogo {
display: block;
background: url('../images/svg/small-logo2.svg');
width: 106px;
height: 49px;
margin: 0 auto;
padding: 0;
}
p.footer {
font-size: .375em;
color: @white;
text-align: center;
}
}
});
}


Related Topics



Leave a reply



Submit