• home > webfront > style > less >

    详解less

    Author:[email protected] Date:

    CSS 彻底改变了 Web 页面的设计,但 CSS 仍然是静态的,而且在其句法发展方面受到限制。这些限制是有目的且合乎情理的,鼓励广泛加以实现。
    图 1.LESS 的官网介绍

    根据维基百科上的介绍,其实 LESS 是 Alexis Sellier 受 SASS 的影响创建的开源项目。当时 SASS 采用了缩进作为分隔符来区分代码块,而不是 CSS 中广为使用的括号。为了让 CSS 现有用户使用起来更为方便,Alexis 开发了 LESS 并提供了类似的功能。在一开始,LESS 的解释器也同样是由 Ruby 编写,后来才转而采用了 JavaScript. LESS 代码既可以运行在客户端,也可以运行在服务器端。在客户端只要把 LESS 代码和相应的 JavaScript 解释器在同一页面引用即可;而在服务器端,LESS 可以运行在 Node.js 上,也可以运行在 Rhino 这样的 JavaScript 引擎上。

    说一点题外话,其实现在的 SASS 已经有了两套语法规则:一个依旧是用缩进作为分隔符来区分代码块的;另一套规则和 CSS 一样采用了大括弧作为风格符。后一种语法规则又名 SCSS,在 SASS 3 之后的版本都支持这种语法规则。SCSS 和 LESS 已经越来越像了,它俩之间更详细的对比可以参考 此链接

    LESS 高级特性

    我们知道 LESS 拥有四大特性:变量、混入、嵌套、函数。这些特性在其他文章中已经有所介绍,这里就不复述了。其实,LESS 还拥有一些很有趣的特性有助于我们的开发,例如模式匹配、条件表达式、命名空间和作用域,以及 JavaScript 赋值等等。让我们来逐一看看这些特性吧。

    模式匹配:

    相信大家对 LESS 四大特性中的混入 (mixin) 依然印象深刻吧,您用它能够定义一堆属性,然后轻松的在多个样式集中重用。甚至在定义混入时加入参数使得这些属性根据调用的参数不同而生成不同的属性。那么,让我们更进一步,来了解一下 LESS 对混入的更高级支持:模式匹配和条件表达式。

    首先,让我们来回顾一下普通的带参数的混入方式:

    清单 1. 带参数(及参数缺省值)的混入
     .border-radius (@radius: 3px) { 
      border-radius: @radius; 
      -moz-border-radius: @radius; 
      -webkit-border-radius: @radius; 
     } 
     .button { 
      .border-radius(6px); 
     } 
     .button2 { 
      .border-radius(); 
     }
    清单 2. 混入生成的 CSS 代码
     .button { 
      border-radius: 6px; 
      -moz-border-radius: 6px; 
      -webkit-border-radius: 6px; 
     } 
     .button2 { 
      border-radius: 3px; 
      -moz-border-radius: 3px; 
      -webkit-border-radius: 3px; 
     }

    从上面这个例子可以看出,在混入我们可以定义参数,同时也可以为这个参数指定一个缺省值。这样我们在调用这个混入时如果指定了参数.border-radius(6px),LESS 就会用 6px来替换,如果不指定参数来调用 .border-radius(),LESS 就会用缺省的 3px来替换。现在,我们更近一步,不仅仅通过参数值来更改最终结果,而是通过传入不同的参数个数来匹配不同的混入。

    清单 3. 利用不同的参数个数来匹配不同的混入
     .mixin (@a) { 
      color: @a; 
      width: 10px; 
     } 
     .mixin (@a, @b) { 
      color: fade(@a, @b); 
     } 
    
     .header{ 
        .mixin(red); 
     } 
     .footer{ 
        .mixin(blue, 50%); 
     }
    清单 4. 不同参数个数调用后生成的 CSS 代码
     .header { 
      color: #ff0000; 
      width: 10px; 
     } 
     .footer { 
      color: rgba(0, 0, 255, 0.5); 
     }

    这个例子有些像 Java 语言中的方法调用有些类似,LESS 可以根据调用参数的个数来选择正确的混入来带入。现在,我们了解到通过传入参数的值,以及传入不同的参数个数能够选择不同的混入及改变它的最终代码。这两个例子的模式匹配都是非常容易理解的,让我们换个思路,上面的例子中参数都是由变量构成的,其实在 LESS 中定义参数是可以用常量的!模式匹配时匹配的方式也会发生相应的变化,让我们看个实例。

    清单 5. 用常量参数来控制混入的模式匹配
     .mixin (dark, @color) { 
      color: darken(@color, 10%); 
     } 
     .mixin (light, @color) { 
      color: lighten(@color, 10%); 
     } 
     .mixin (@zzz, @color) { 
      display: block; 
      weight: @zzz; 
     } 
     
     .header{ 
        .mixin(dark, red); 
     } 
     .footer{ 
        .mixin(light, blue); 
     } 
     .body{ 
        .mixin(none, blue); 
     }
    清单 6. 常量参数生成的 CSS 代码
     .header { 
      color: #cc0000; 
      display: block; 
      weight: dark; 
     } 
     .footer { 
      color: #3333ff; 
      display: block; 
      weight: light; 
     } 
     .body { 
      display: block; 
      weight: none; 
     }

    通过这个例子我们可以看出,当我们定义的是变量参数时,因为 LESS 中对变量并没有类型的概念,所以它只会根据参数的个数来选择相应的混入来替换。而定义常量参数就不同了,这时候不仅参数的个数要对应的上,而且常量参数的值和调用时的值也要一样才会匹配的上。值得注意的是我们在 body 中的调用,它调用时指定的第一个参数 none 并不能匹配上前两个混入,而第三个混入 .mixin (@zzz, @color)就不同了,由于它的两个参数都是变量,所以它接受任何值,因此它对三个调用都能匹配成功,因此我们在最终的 CSS 代码中看到每次调用的结果中都包含了第三个混入的属性。

    最后,我们把清单 1 中的代码做略微改动,增加一个无参的混入和一个常量参数的混入,您猜猜看最终的匹配结果会发生什么变化么?

    清单 7. 无参和常量参数的模式匹配
     .border-radius (@radius: 3px) { 
      border-radius: @radius; 
      -moz-border-radius: @radius; 
      -webkit-border-radius: @radius; 
     } 
    
     .border-radius (7px) { 
      border-radius: 7px; 
      -moz-border-radius: 7px; 
     } 
     .border-radius () { 
      border-radius: 4px; 
      -moz-border-radius: 4px; 
      -webkit-border-radius: 4px; 
     } 
    
     .button { 
      .border-radius(6px); 
     } 
     .button2 { 
      .border-radius(7px); 
     } 
     .button3{ 
     .border-radius();      
     }

    下面的结果可能会出乎您的意料,无参的混入是能够匹配任何调用,而常量参数非常严格,必须保证参数的值 (7px)和调用的值 (7px)一致才会匹配。

    清单 8. 加入了无参混入后生成的 CSS 代码
     .button { 
      border-radius: 6px; 
      -moz-border-radius: 6px; 
      -webkit-border-radius: 6px; 
      border-radius: 4px; 
      -moz-border-radius: 4px; 
      -webkit-border-radius: 4px; 
     } 
     .button2 { 
      border-radius: 7px; 
      -moz-border-radius: 7px; 
      -webkit-border-radius: 7px; 
      border-radius: 7px; 
      -moz-border-radius: 7px; 
      border-radius: 4px; 
      -moz-border-radius: 4px; 
      -webkit-border-radius: 4px; 
     } 
     .button3 { 
      border-radius: 3px; 
      -moz-border-radius: 3px; 
      -webkit-border-radius: 3px; 
      border-radius: 4px; 
      -moz-border-radius: 4px; 
      -webkit-border-radius: 4px; 
     }

    条件表达式

    有了模式匹配之后是方便了很多,我们能根据不同的需求来匹配不同的混入,但更进一步的就是利用条件表达式来更加准确,更加严格的来限制混入的匹配,实现的方式就是利用了 when这个关键词。

    清单 9. 利用条件表达式来控制模式匹配
     .mixin (@a) when (@a >= 10) { 
      background-color: black; 
     } 
     .mixin (@a) when (@a < 10) { 
      background-color: white; 
     } 
     .class1 { .mixin(12) } 
     .class2 { .mixin(6) }
    清单 10. 条件表达式生成的 CSS 代码
     .class1 { 
      background-color: black; 
     } 
     .class2 { 
      background-color: white; 
     }

    利用 When 以及 <, >, =, <=, >= 是十分简单和方便的。LESS 并没有停留在这里,而且提供了很多类型检查函数来辅助条件表达式,例如iscolorisnumberisstringiskeywordisurl等等。

    清单 11. 条件表达式中支持的类型检查函数
     .mixin (@a) when (iscolor(@a)) { 
      background-color: black; 
     } 
     .mixin (@a) when (isnumber(@a)) { 
      background-color: white; 
     } 
     .class1 { .mixin(red) } 
     .class2 { .mixin(6) }
    清单 12. 类型检查匹配后生成的 CSS 代码
     .class1 { 
      background-color: black; 
     } 
     .class2 { 
      background-color: white; 
     }

    另外,LESS 的条件表达式同样支持 AND 和 OR 以及 NOT 来组合条件表达式,这样可以组织成更为强大的条件表达式。需要特别指出的一点是,OR 在 LESS 中并不是用 or 关键字,而是用 , 来表示 or 的逻辑关系。

    清单 13. AND,OR,NOT 条件表达式
     .smaller (@a, @b) when (@a > @b) { 
        background-color: black; 
     } 
     .math (@a) when (@a > 10) and (@a < 20) { 
        background-color: red; 
     } 
     .math (@a) when (@a < 10),(@a > 20) { 
        background-color: blue; 
     } 
     .math (@a) when not (@a = 10)  { 
        background-color: yellow; 
     } 
     .math (@a) when (@a = 10)  { 
        background-color: green; 
     } 
    
     .testSmall {.smaller(30, 10) } 
     .testMath1 {.math(15)} 
     .testMath2 {.math(7)} 
     .testMath3 {.math(10)}
    清单 14. AND,OR,NOT 条件表达式生成的 CSS 代码
     .testSmall { 
      background-color: black; 
     } 
     .testMath1 { 
      background-color: red; 
      background-color: yellow; 
     } 
     .testMath2 { 
      background-color: blue; 
      background-color: yellow; 
     } 
     .testMath3 { 
      background-color: green; 
     }

    命名空间和作用域

    LESS 所带来的变量,混入这些特性其实很大程度上避免了传统 CSS 中的大量代码重复。变量能够避免一个属性多次重复,混入能够避免属性集的重复。而且使用起来更加灵活,维护起来也方便了许多,只要修改一处定义而无需修改多处引用的地方。现在,让我们更进一步,当我定义好了变量和混入之后,怎么能更好的控制和运用它们呢,怎么避免和其他地方定义的变量及混入冲突?一个显而易见的想法就是像其他语言一样引入命名空间和作用域了。首先我们来看一个 LESS 的作用域的例子。

    清单 15. 变量的作用域
     @var: red; 
     #page { 
      @var: white; 
      #header { 
        color: @var; 
      } 
     } 
     #footer { 
      color: @var; 
     }

    在这个例子里,可以看到 header 中的 @var会首先在当前作用域寻找,然后再逐层往父作用域中寻找,一直到顶层的全局作用域中为止。所以 header 的 @var在父作用域中找到之后就停止了寻找,最终的值为 white。而 footer 中的 @var在当前作用域没找到定义之后就寻找到了全局作用域,最终的结果就是全局作用域中的定义值 red。

    清单 16. 变量作用域例子生成的 CSS 代码
     #page #header { 
      color: #ffffff;  // white 
     } 
     #footer { 
      color: #ff0000;  // red 
     }

    了解了作用域之后让我们再来看一下命名空间,我们可以用命名空间把变量和混入封装起来,避免和其他地方的定义冲突,引用起来也十分方便,只要在前面加上相应的命名空间就可以了。

    清单 17. 命名空间的例子
     @var-color: white; 
     #bundle { 
      @var-color: black; 
    
      .button () { 
        display: block; 
        border: 1px solid black; 
        background-color: @var-color; 
      } 
      .tab() { color: red } 
      .citation() { color: black} 
      .oops {weight: 10px} 
     } 
    
     #header { 
        color: @var-color; 
        #bundle > .button; 
        #bundle > .oops;

    }

    这里可以看出,我们利用嵌套规则在 #bundle中建立了一个命名空间,在里面封装的变量以及属性集合都不会暴露到外部空间中,例如.tab(), .citation()都没有暴露在最终的 CSS 代码中。而值得注意的一点是 .oops 却被暴露在了最终的 CSS 代码中,这种结果可能并不是我们想要的。其实同样的例子我们可以在混入的例子中也可以发现,即无参的混入 .tab()是和普通的属性集 .oops不同的。无参的混入是不会暴露在最终的 CSS 代码中,而普通的属性集则会现在出来。我们在定义命名空间和混入时要小心处理这样的差别,避免带来潜在的问题。

    清单 18. 命名空间例子生成的 CSS 代码
     #bundle .oops { 
      weight: 10px; 
     } 
     #header { 
      color: #ffffff; 
      display: block; 
      border: 1px solid black; 
      background-color: #000000; 
      weight: 10px; 
     }

    JavaScript 赋值 (JavaScript Evaluation)

    如果能在 CSS 中使用一些 JavaScript 方法无疑是十分令人兴奋的,而 LESS 真正逐步加入这项功能,目前已经能使用字符串及数字的常用函数了,想要在 LESS 中运用 JavaScript 赋值只需要用反引号(`)来包含所要进行的操作即可。让我们看看实例吧。

    清单 19. JavaScript 赋值的例子
     .eval { 
        js: `1 + 1`; 
        js: `(1 + 1 == 2 ? true : false)`; 
        js: `"hello".toUpperCase() + '!'`; 
        title: `process.title`; 
     } 
     .scope { 
        @foo: 42; 
        var: `this.foo.toJS()`; 
     } 
     .escape-interpol { 
        @world: "world"; 
        width: ~`"hello" + " " + @{world}`; 
     } 
     .arrays { 
        @ary:  1, 2, 3; 
        @ary2: 1  2  3; 
        ary: `@{ary}.join(', ')`; 
        ary: `@{ary2}.join(', ')`; 
     }

    我们可以看到,在 eval 中我们可以用 JavaScript 做数字运算,布尔表达式;对字符串做大小写转化,串联字符串等操作。甚至最后能够获取到 JavaScript 的运行环境(process.title)。同样可以看到 LESS 的作用域和变量也同样在 JavaScript 赋值中使用。而最后的例子中,我们看到 JavaScript 赋值同样运用于数组操作当中。其实 LESS 的 JavaScript 赋值还有支持其他一些方式,不过目前尚未公布出来。

    清单 20. JavaScript 赋值生成的 CSS 代码
     .eval { 
      js: 2; 
      js: true; 
      js: "HELLO!"; 
      title: "/Users/Admin/Downloads/LESS/Less.app/Contents/Resources/engines/bin/node"; 
     } 
     .scope { 
      var: 42; 
     } 
     .escape-interpol { 
      width: hello world; 
     } 
     .arrays { 
      ary: "1, 2, 3"; 
      ary: "1, 2, 3"; 
     }
     

    LESS 开发的实用工具 – LESS.app

    在 LESS 开发中,我们可以用 LESS 提供的 JavaScript 脚本来在运行时解析,将 LESS 文件实时翻译成对应的 CSS 语法。如下面这个例子:

    清单 21. helloworld.html
     <link rel="stylesheet/less" type="text/css" href="helloworld.less"> 
     <script src="less.js" type="text/javascript"></script> 
    
     <div class="helloworld">Hello World!</div>

    从上面的示例可以看出,在 helloworld.less 引入之后我们还添加了一个 JavaScript 文件,这个文件就是 LESS 的解释器,可以在 LESS 的官方网站上下载此文件。需要注意的是,要注意 LESS 文件和 LESS 解释器的引入顺序,确保所有的 LESS 文件都在 LESS 解释器之前。

    看到这里也许有人会说,实时解析的话方便倒是方便,可以性能上不就有损耗了么?比起普通 CSS 来说多了一道解释的手续。也许还有的人对写好的 LESS 文件不太放心,希望能看到解析之后的 CSS 文件来检查下是否是自己希望的内容。这两个问题其实都是能够解决的,LESS 提供了服务端的方案,使用 npm 安装 LESS 之后就能够将您所有的 LESS 文件批量转化成 CSS 文件,然后您拿到 CSS 文件就可以随心所欲了,检查生成的内容是否有误,也可以直接在 HTML 中引用,再也不用添加 LESS 的 JavaScript 文件来解析它了。关于这部分的详细安装信息,可以直接参考 LESS 官网上的介绍,这里就不复述了。

    不过,对于 Mac 用户来说还有一个更方便的工具可以使用,它就是 less.app. 这是一个第三方提供的工具,使用起来十分方便,我们可以在下图所示的界面上添加 LESS 文件所在的目录,此工具就会在右侧列出目录中包含的所有 LESS 文件。最酷的是,从此您就不用再操心惦记着要把 LESS 文件编译成 CSS 文件了,这个工具会在您每次修改完保存 LESS 文件时自己执行编译,自动生成 CSS 文件。这样,您就可以随时查看 LESS 代码的最终效果,检查目标 CSS 是否符合您的需要了,实在是太方便了!

    图 2. 导入 LESS 文件夹的界面,左侧可添加存放在多个不同路径的文件夹。

    图 2. 导入 LESS 文件夹的界面,左侧可添加存放在多个不同路径的文件夹。

    图 3. 编译结果界面,在此可手动批量编译所有 LESS 文件。

    图 3. 编译结果界面,在此可手动批量编译所有 LESS 文件。
     

    删除魔法值

    看到 清单 1 的开发人员很可能立刻注意到那些违反开发者本能的内容,即硬编码到 CSS 中的值,这些值有时被揶揄为 “魔法值 (magic value)”。LESS 中最重要的特性之一是变量。清单 3 是使用变量的一个 LESS 基本示例版本:

    清单 3. 使用 LESS 中的变量的基本 CSS 示例 (listing3.css)
     @main-text-color: red; 
     @main-text-size: 12px; 
     @main-text-bg: green; 
    
     p { 
      color: @main-text-color; 
      font-size: @main-text-size; 
      background-color: @main-text-bg; 
     }

    清单 3 不是语法正确的 CSS,因此您不能在 HTML 中将 listing1.css 替换为 listing3.less 。您还必须更新主机 HTML 来调用 JavaScript 编译器,如清单 4 所示:

    清单 4. 引用基本 CSS 示例 LESS 版本的 HTML (listing4.html)
     <head> 
        <link rel="stylesheet/less" type="text/css" href="listing3.less"> 
     </head> 
     <body> 
        <p>This is a paragraph</p> 
        <script src="less.js" type="text/javascript"></script> 
     </body>

    请注意,在 清单 4 中,我将 script 标记放在页面 body 的结尾处。传统上,大多数开发人员将 script 标记放在 head 中。但将它们放在body 中是合法的,这利用了这样一个事实(引用自 HTML 4 规范),即 “script 元素按照加载文档的顺序进行求值”。如今许多站点在临近结束时都有一些脚本,因此主要内容的加载不会因为任何脚本处理而延迟。

     

    服务器端编译

    到目前为止,我已经向您展示:开发和部署 LESS 便于快速使用浏览器,但却是有代价的。每次页面加载时,编译用的 JavaScript 都运行于用户的浏览器之上,这耗尽了计算资源并减缓了页面加载。如果在浏览器中加载 清单 4 ,并检查 JavaScript 控制台,则会看到一条消息:“less: css generated in 36ms”。36 毫秒的时间并不算长,但它代表着额外的不必要计算和时间。快速页面加载在 Web 上很重要。

    在转入生产模式之后,使用一个服务器端 JavaScript 工具将 LESS 编译到 CSS 中。Node.js 是一个流行选项,被记录在 LESS 站点上。我喜欢使用 Mozilla 的独立 JavaScript 项目 Rhino。要使用 Rhino 和 LESS,请下载并安装 Rhino(参见 参考资料)。将 js.jar 放在一个方便进行构建的位置。您需要一个特殊版本的 less.js,该版本可在 GitHub 完整下载的 LESS 中下载中找到(参见 参考资料)。本文中使用的版本是 less.js-master/dist/less-rhino-1.4.0.js。将 less-rhino-1.4.0.js 放在保存 Rhino JAR 的地方。下面准备将 LESS 代码编译到 CSS 中。

    要编译 listing3.less,请切换到 listing3.less 所在的目录并执行以下命令:

     java -jar js.jar less-rhino-1.4.0.js listing3.less > listing3.css

    编译操作会将生成的 CSS 放在 listing3.css 文件中。该文件的内容如下:

     p { 
      color: #ff0000; 
      font-size: 12px; 
      background-color: #008000; 
     }

    在 listing3.css 中,LESS 变量被替换,颜色名称被替换为 RGB 形式(比如 red 被替换为 #ff0000 )。现在您可以按照常用方法将 listing3.css 部署到一台服务器中。

     

    LESS 替代注释语法

    LESS 的一个小小的增强是,编写单行注释的方式变得简单了。清单 5 显示了来自 W3C CSS 教程的一个标准注释示例:

    清单 5. 使用注释的 CSS 示例 (listing 5.css)
     p { 
      color: red; 
      /* This is a comment */ 
      font-size: 12px; 
     }

    清单 6 中的 LESS 代码等同于 清单 5 :

    清单 6. 与使用简化注释的清单 5 等同的 LESS 代码 (listing6.less)
     p { 
      color: red; 
      // This is a comment 
      font-size: 12px; 
     }

    清单 6 使用的语法对于程序员来说很常见,而且键入起来稍微容易一些。但鉴于处理 LESS 的方式,这种注释并不出现在生成的 CSS 中。如果您想为浏览器查看器保留注释(例如用于版权声明),则必须使用标准的 CSS 注释语法。

    W3C 教程其余内容专注于 CSS 选择器语法和常见属性的细节。此时,我要将重心转向 LESS 的更广泛使用,这是大多数 Web 开发人员在实践过程中越来越多遇见的情形。

     

    创建响应式设计

    在 2010 年,许多 Web 设计人员开始倡导一种称为 响应式设计 的页面设计方法。从一开始,就需要构建灵活的 Web 页面,在从小型手机到比常用台式机更大的显示设备中查看它们。

    响应式设计的核心是 CSS3 媒体查询,该查询是一种根据用户显示器的性质(特别是尺寸)来调用 CSS 规则的标准方式。LESS 使我们能够更容易地展现使用媒体查询来实现响应式设计的 CSS。出于演示之目的,我将 developerWorks 博主 Bob Leah 的优秀响应式设计 示例 的一个 LESS 版本组合起来。在文章的代码包(参见 下载)中,它是 responsive.less。

    运算符

    responsive.less 中的一项关键技术是使用变量设置基本的方框大小,然后根据可视区的大小调整方框。我使用 LESS 运算符来进行缩放。例如,清单 7 中的代码段使用乘法运算符来缩放横幅图像:

    清单 7. LESS 中乘法的使用
     #banner img { 
      max-width: (@bannerwidth * @scale); 
      max-height: (@mainheight * @scale); 
     }

    在 清单 7 中,@bannerwidth 和 @mainheight 是根据 @scale 因子缩减的默认值。最新的 LESS 版本要求您将包含运算符的所有表达式放在圆括号中,以避免语法混淆。

    嵌套规则

    LESS 最有用的功能之一是嵌套 CSS 规则。嵌套规则有助于您以简单易懂的方式组织代码。在清单 8(responsive.less 中的一段经过修改的摘录片段)中,我在媒体查询内嵌套了通用的 CSS 规则:

    清单 8. LESS 中嵌套规则的使用
     @media (min-width: 401px) and (max-width: 800px) { 
      @scale: 0.75 
      #banner { width: (@bannerwidth * @scale); } 
      #banner img { 
        max-width: (@bannerwidth * @scale); 
        max-height: (@mainheight * @scale); 
      } 
      #main { width: (@mainwidth * @scale - @extrabuffer); } 
      #main-content { 
        width: (@maincontentwidth * @scale * 0.75 - @extrabuffer); 
        float: left; 
      } 
     }

    清单 8 中的嵌套规则等同于清单 9 中多个独立的 CSS 规则:

    清单 9. 等同于清单 8,但无嵌套规则
     @scale: 0.75 
    
     @media (min-width: 401px) and (max-width: 800px) and #banner { 
       width: (@bannerwidth * @scale); 
     } 
    
     @media (min-width: 401px) and (max-width: 800px) and #banner img { 
     { 
      max-width: (@bannerwidth * @scale); 
      max-height: (@mainheight * @scale); 
     } 
    
     @media (min-width: 401px) and (max-width: 800px) and #main { 
       width: (@mainwidth * @scale - @extrabuffer); 
     } 
    
     @media (min-width: 401px) and (max-width: 800px) and #main-content { 
        width: (@maincontentwidth * @scale * 0.75 - @extrabuffer); 
        float: left; 
     }

    清单 9 中的版本没有提供这些密切相关规则的自然分组,而且还因为反复指定媒体查询而违反了 DRY(不要重复自己)原则。

    mixins

    LESS 减少重复的另一种方式是让您指定可添加到其他规则中的一组规则。在 responsive.less 中,我使用了此 mixin 技术来跨两个不同的媒体查询表达常见规则,如清单 10 所示:

    清单 10. LESS 中 mixins 的使用
     .media-body (@scale: 0.75) { 
      #banner { width: (@bannerwidth * @scale); } 
      #banner img { 
        max-width: (@bannerwidth * @scale); 
        max-height: (@mainheight * @scale); 
      } 
      #main { width: (@mainwidth * @scale - @extrabuffer); } 
      #main-content { 
        width: (@maincontentwidth * @scale * 0.75 - @extrabuffer); 
        float: left; 
      } 
      #widget-container { 
        width: (@widgetoutwidth * @scale * 0.75 - @extrabuffer); 
        float: right; 
      } 
      .widget-content { 
        width: (@widgetinwidth * @scale * 0.75 - @extrabuffer); 
      } 
     } 
    
     //Rules for viewing from 401px to 800px 
     @media (min-width: 401px) and (max-width: 800px) { 
      .media-body; 
     } 
    
     //Rules for viewing smaller than 400px 
     @media (max-width: 400px)  { 
      .media-body(0.3); 
      //Extra manipulation of some rules 
      #main-content { padding: 0px; } 
      #widget-container { width: padding: 0px; } 
      .widget-content { margin: 5px; } 
      .widget-text { display: none; } 
     }

    Mixins 可以接受参数,比如 清单 10 中方框大小的比例因子。默认的比例因子是 0.75 清单 10 在可视区中使用从 401px 到 800px 的默认大小。为了在小于 400px 的尺寸下进行查看,比例因子被更改为 0.3 ,并且在该区域添加了一些额外规则。

    图 2 显示了 responsive.html 的浏览器显示,它使用了 responsive.less。我减小了浏览器的宽度,以满足小于 400px 的宽度的媒体查询,这样一来您就可以看到页面在小型移动设备上是什么样子。

    图 2. responsive.html 的低宽度浏览器输出

    宽度缩减的 Safari 浏览器中的 responsive.html 屏幕截图,用于模拟小型移动设备上的页面外观

    在我 Mac 上的 Safari 中,当浏览器宽度接近 500px 时,小于 400px 的宽度的媒体查询被触发。该行为引出了一个重要观点。媒体查询基于视区这一概念。视区是可视浏览器空间的数量,用 CSS 像素进行定义,并通过设备和浏览器进行确定。CSS 像素不同于设备像素;例如,如果用户缩放浏览器视图,那么像素模型之间的关系就会发生变化(参见 参考资料)。此外,设备和浏览器设置的视区大小不同于实际显示的窗口大小。在 图 2 中就是如此:窗口大约是 500px,但 CSS 将其作为 400px 宽的视区加以处理。这一现象强调了这样一个事实:与所有 Web 开发技术一样,响应式设计需要完善的跨设备测试。

     

    结束语

    我是一名软件架构师兼开发人员,但绝不是一名 Web 设计人员。凭借 LESS,我可以利用我的编程技能快速开发更便于理解和维护的 CSS。变量和 mixins 使我能够快速做出调整,查看其效果,无需在整个 CSS 文件内四处移动,查找我需要进行相关更改的内容。

    响应式设计是经济适用的可管理移动 Web 设计中的一项公认的关键技术。它在针对打印等可访问性和其他演示模式的设计中也很有用。由于为应对媒体查询而应用的多种样式处理起来很繁琐,所以 LESS 简化和组织 CSS 代码的功能愈发有价值。


    转载本站文章《详解less》,
    请注明出处:https://www.zhoulujun.cn/html/webfront/style/less/2015_0811_239.html