化繁为简:使用LESS魔法优化媒体查询

91

使用less,将不同分辨率的css样式封装到一些css类中是个好主意。

我想做这样的事情:

footer {
  width: 100%;
}

.tablet {
  footer {
    width: 768px;
  }
}

.desktop {
  footer {
    width: 940px;
  }
}

最终应该是这样的结果:

footer {
  width: 100%;
}

@media screen and (min-width: 768px) {
  footer {
    width: 768px;
  }
}

@media screen and (min-width: 992px) {
  footer {
    width: 940px;
  }
}

平板电脑的外观可能类似于这样:

@media screen and (min-width: 768px) {
  .tablet {

  }
}

希望有人有一个好主意!


根据对@zzzzBov评论中的讨论,也许我们需要更清晰地了解您关于“什么”和“如何”实现它的问题。 - ScottS
8个回答

249

以下是我在项目中所做的:

@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;
  }
}

这样可以让您只定义媒体查询一次,然后在整个less文件中都可以使用。同时也更易于阅读。 :)


2
这太棒了,谢谢@Hai!在Visual Studio中有一个小问题,即在.less文件中使用@media时会生成警告消息:“样式规则中出现意外的'@'块”。但似乎并不是问题。 - Ian Campbell
为什么我不能将 @media 拉入第 1+2 行中定义的变量中? ➪ 遗憾的是,一个纯粹的 @tablet { ... 就无法解决这个问题,而 @media @tablet {... 则可以(当然,如果将其放入字符串中,则会导致 @media 值翻倍)。 - Frank N

123
我完全同意Hai Nguyen的回答(已被接受),但您可以通过这样做来进一步简化它:
@desktop:   ~"only screen and (min-width: 960px) and (max-width: 1199px)";
@tablet:    ~"only screen and (min-width: 720px) and (max-width: 959px)";

footer{
  width: 100%;
  @media @tablet {
    width: 768px;
  }
  @media @desktop {
    width: 940px;
  }
}

它本质上是同样的东西,但允许您将媒体查询嵌套在原始选择器内。它将特定元素的所有CSS保持在一起,使您的样式更加模块化(与分裂断点方法相比)。


阅读后,我发现这个Grunt任务可以在嵌套的MQ编译后对它们进行分组:https://github.com/buildingblocks/grunt-combine-media-queries去除冗余代码。 - Jazzy
这很清楚明了。我可以问一下,为什么在“only…”前面加上“~”? - Anthony_Z
在LESS中,一个波浪线~在一个字符串""字面量之前输出该字符串,因为在纯LESS中它可能是语法错误。 - Joseph Yancey
1
如果你尝试在“字面字符串”内进行操作会怎样呢?比如说,我想使用一个变量来包含屏幕分辨率,像这样:我能做类似这样的事情吗:“~“only screen and (min-width: @mySize - 20px)””。我知道这不起作用,但正确的方法是什么呢? - fablexis

48

+1给Nguyen和Yancey,还有一个额外的添加。

如果您想要宽度的明确定义,可以使用字符串插值和断点变量来完成。例如,在这里使用Bootstrap的规则进行严格限制以防止定义重叠。

@screen-xs-min:     480px;
@screen-sm-min:     768px;
@screen-md-min:     992px;
@screen-lg-min:     1200px;

@screen-xs-max:     (@screen-sm-min - 1);
@screen-sm-max:     (@screen-md-min - 1);
@screen-md-max:     (@screen-lg-min - 1);

@phone:             ~"only screen and (max-width: @{screen-xs-min})";
@phone-strict:      ~"only screen and (min-width: @{screen-xs-min}) and (max-width: @{screen-xs-max})";
@tablet:            ~"only screen and (min-width: @{screen-sm-min})";
@tablet-strict:     ~"only screen and (min-width: @{screen-sm-min}) and (max-width: @{screen-sm-max})";
@desktop:           ~"only screen and (min-width: @{screen-md-min})";
@desktop-strict:    ~"only screen and (min-width: @{screen-md-min}) and (max-width: @{screen-md-max})";
@large:             ~"only screen and (min-width: @{screen-lg-min})";

footer{
    width: 100%;
    @media @tablet {
        width: 768px;
    }
    @media @desktop {
        width: 940px;
    }
}

这个“-strict”到底是什么意思,从你写的内容中我无法理解这个结构。你能否指出一些相关的资料让我深入了解这个主题? - Kevkong
2
实际上,“strict-queries”是为了方便起见,只有在您希望您的CSS仅适用于单个屏幕范围时才应使用。当使用移动优先(例如,请参见:http://zellwk.com/blog/how-to-write-mobile-first-css/)时,我会说,它们的使用可能有点设计上的问题,我通常会尝试避免使用它们。但是根据情况,您可能希望针对某些(重要的)CSS进行定位,例如仅针对`@tablet`,并且不希望在`@desktop`和/或`@large`中覆盖它。在这些情况下,您可以使用严格查询(这里是`@tablet-strict`)。 - SunnyRed

11

你也可以像这样结合使用媒体查询

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

    @media @desktop, @tablet, @ipad{ 
    
    //common styles... 
    
    }

7
我们使用类似这样的设置:
@vp_desktop:    801px;
@vp_tablet:     800px;
@vp_mobile:     400px;

.OnDesktop(@rules) { @media screen and (min-width:@vp_desktop){ @rules(); } };
.OnTablet(@rules) { @media screen and (max-width:@vp_tablet){ @rules(); } };
.OnMobile(@rules) { @media screen and (max-width:@vp_mobile){ @rules(); } };

您只需要设置变量,混合处理其他部分,因此很容易维护但仍然灵活:

div {
  display: inline-block;
  .OnTablet({
    display: block;
  });
}

值得一提的是,虽然这种技术非常简单,但如果使用不当,你的CSS输出将充满媒体查询。我尝试将媒体查询限制为每个断点、每个文件1个。其中一个文件可以是header.less或search.less。
注意:除非您正在使用javascript编译器,否则此方法可能无法编译。

4
我正在使用这些mixin和变量。
.max(@max; @rules){@media only screen and (max-width: (@max - 1)){@rules();}}
.min(@min; @rules){@media only screen and (min-width: @min){@rules();}}
.bw(@min; @max; @rules){@media only screen and (min-width: @min) and (max-width: (@max - 1)){@rules();}}

@pad: 480px;
@tab: 800px;
@desktop: 992px;
@hd: 1200px;

所以这个……
footer{
    width: 100%;
    .bw(@tab,@desktop,{
        width: 768px;
    });
    .min(@desktop,{
        width: 940px;
    });
}

变成

footer {
  width: 100%;
}
@media only screen and (min-width: 800px) and (max-width: 991px) {
  footer {
    width: 768px;
  }
}
@media only screen and (min-width: 992px) {
  footer {
    width: 940px;
  }
}

0

这是我在项目中使用的:

    @mobile:   ~"only screen and (min-width: 320px) and (max-width: 767px)";
    @tablet:    ~"only screen and (min-width: 768px) and (max-width: 991px)";
    @ipad:    ~"only screen and (min-width: 992px) and (max-width: 1024px)";

    @media @mobile {
      .banner{
        width: auto;
      }
    }

    @media @tablet {
      .banner{
        width: 720px;
      }
    }

  @media @ipad {
      .banner{
        width: 920px;
      }
    }

0
@highdensity:  ~"only screen and (-webkit-min-device-pixel-ratio: 1.5)",
               ~"only screen and (min--moz-device-pixel-ratio: 1.5)",
               ~"only screen and (-o-min-device-pixel-ratio: 3/2)",
               ~"only screen and (min-device-pixel-ratio: 1.5)";

@mobile:        ~"only screen and (max-width: 750px)";
@tab:       ~"only screen and (min-width: 751px) and (max-width: 900px)";
@regular:        ~"only screen and (min-width: 901px) and (max-width: 1280px)";
@extra-large:  ~"only screen and (min-width: 1281px)";

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接