Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
380 views
in Technique[技术] by (71.8m points)

less - CSS pre-processor with a possibility to define variables in a @media query

Currently, I am using LESS as my main CSS pre-processor. I have (and I am sure a lot of people have this need) to define variables in a @media query like:

@media screen and (max-width: 479px) {
    myVar: 10px;
}
@media screen and (min-width: 480px) and (max-width: 767px) {
    myVar: 20px;
}
@media screen and (min-width: 768px) {
    myVar: 30px;
}

.myElement {
    padding: @myVar;
}

This doesn't work in LESS, because of the compiling nature (@myVar is defined within a scope of each particular @media only, but not globally). Even if I define @myVar globally before the media queries, it is not updated in accordance to the media queries and .myElement gets that initial value no matter what.

So, the question is, is it possible to achieve this in any other CSS pre-processor, or we are doomed to override the .myElement within each media query? Not a problem in this simplest example, but in real projects this could save a lot of time and copy/pasting.

EDIT: Not a solution, but a workaround for my particular project:

  1. Set font-size on <html> to base font-size
  2. myVar LESS variable is defined in rem instead of px as a derivative of the base font-size
  3. Use @media queries to adjust base font-size for different media.
  4. OPTIONAL Use REM unit polyfill for browsers, that don't yet support rem (http://caniuse.com/#search=rem). This will not work in IE 8 and below, but not because of lack of support for remit doesn't support media queries. So IE8 and below get full-size media-queries-free stylesheet anyway.

Code snippet:

@myVar: .77rem; // roughly 10px, 20px and 30px respectively

html { font-size: 13px }
@media screen and (min-width: 480px) and (max-width: 767px) {
    html { font-size: 26px }
}
@media screen and (min-width: 768px) {
    html { font-size: 39px }
}

.myElement {
    padding: @myVar;
}

Here is a JSBin with more extensive example that mixes different font-size elements with differently measured blocks.

Easy and flexible for my needs. Hopefully will be helpful for somebody else.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Let me answer more directly the question:

"Is it possible to achieve this in any other CSS pre-processor, or we are doomed to override the .myElement within each media query?"

The answer actually resides in the question. Because LESS (and other similar tools) is a "pre-processor," the @media means nothing to it at compilation time, because it is not looking at the media state of the browser for its preprocessing. The @media state is only relevant after the preprocessing, at which point any @someVariable has already been calculated. This is why what you are trying to do cannot work. Your @myVar can only be output as a single value in a CSS style sheet, and that output occurs before the browser state is ever evaluated by @media.

So it does not have to do with the "global" or "local" scope of a media query, but the fact that LESS compiles the code into CSS utilizing the variables, and it is the CSS (not LESS) that pays attention to the @media query information.

For some further discussion on building media queries with LESS in such a way that they are all together and not scattered throughout the code, see this question.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...