less语法


//定义变量
@base: #f938ab;
@light-blue: @base + #111;
?
.header {
color: @light-blue;
}
//mixins
.bordered {
   border-top: dotted 1px black;
   border-bottom: solid 2px black;
}
.menu a {
   color: @111;
   .bordered;
}
.post a {
   color: red;
   .bordered;
}
//级联语法
.header {
color: black;
.nav {
font-size: 12px;
}
&:after { //即.header:after
content: "";
clear: both;
}
}
//条件指令的嵌套与冒泡
.screen-color {
 @media screen {
   color: green;
   @media (min-width: 768px) {
     color: red;
  }
}
 @media tv {
   color: black;
}
}
//输出css
@media screen {
 .screen-color {
   color: green;
}
}
@media screen and (min-width: 768px) {
 .screen-color {
   color: red;
}
}
@media tv {
 .screen-color {
   color: black;
}
}
//非条件指令
#a {
 color: blue;
 @font-face {
   src: made-up-url;
}
 padding: 2 2 2 2;
}
//输出css
#a {
 color: blue;
}
@font-face {
 src: made-up-url;
}
#a {
 padding: 2 2 2 2;
}
//算数运算
// numbers are converted into the same units
@conversion-1: 5cm + 10mm; // result is 6cm
@conversion-2: 2 - 3cm - 5mm; // result is 1.5cm
?
// conversion is impossible
@incompatible-units: 2 + 5px - 3cm; // result is 4px
?
// example with variables
@base: 5%;
@filler: @base * 2; // result is 10%
@other: @base + @filler; // result is 15%
?
@base: 2cm * 3mm; // result is 6cm
?
//大于ff或小于00将被四舍五入为ff或00
@color: #224488 / 2; //results in #112244
background-color: #112244 + #111; // result is #223355
//模板字符串
.weird-element {
 content: ~"^//* some horrible but needed css hack";
}
//输出css
.weird-element {
 content: ^//* some horrible but needed css hack;
}
//命名空间和访问器
#bundle {
 .button {
   display: block;
   border: 1px solid black;
   background-color: grey;
   &:hover {
     background-color: white
  }
}
}
?
#header a {
 color: orange;
 #bundle > .button;
}

作用域: Scope in Less is very similar to that of programming languages. Variables and mixins are first looked for locally, and if they aren't found, the compiler will look in the parent scope, and so on.

//import
@import "library"; // library.less
@import "typo.css";
//选择器变量
@my-selector: banner;
?
// Usage
.@{my-selector} {
 font-weight: bold;
 line-height: 40px;
 margin: 0 auto;
}
?
//compile to
.banner {
 font-weight: bold;
 line-height: 40px;
 margin: 0 auto;
}
//URL拼接
// Variables
@images: "../img";
?
// Usage
body {
 color: #444;
 background: url("@{images}/white-sand.png");
}
//import变量拼接
// Variables
@themes: "../../src/themes";
?
// Usage
@import "@{themes}/tidal-wave.less";
//属性变量名拼接
@property: color;
?
.widget {
@{property}: #0ee;
 background-@{property}: #999;
}
?
//compile to
.widget {
 color: #0ee;
 background-color: #999;
}
//通过变量定义变量
@fnord:  "I am fnord.";
@var:    "fnord";
content: @@var;
?
//compile to
content: "I am fnord.";
//变量延迟加载
.lazy-eval {
 width: @var;
}
?
@var: @a;
@a: 9%;
?
//compile to
.lazy-eval-scope {
 width: 9%;
}
//覆写规则
// library
@base-color: green;
@dark-color: darken(@base-color, 10%);
?
// use of library
@import "library.less";
@base-color: red;
//dark-color is a dark red
//extend
nav ul {
 &:extend(.inline);
 background: blue;
}
.inline {
 color: red;
}
?
//compile to
nav ul {
 background: blue;
}
.inline,
nav ul {
 color: red;
}
//继承句法
//以下两段等价
.a:extend(.b) {}
// the above block does the same thing as the below block
.a {
 &:extend(.b);
}
?
//以下两段注意区别
.c:extend(.d all) {
 // extends all instances of ".d" e.g. ".x.d" or ".d.x"
}
.c:extend(.d) {
 // extends only instances where the selector will be output as just ".d"
}
?
//多继承
//以下两段等价
.e:extend(.f) {}
.e:extend(.g) {}
?
// the above an the below do the same thing
.e:extend(.f, .g) {}
?
//继承子选择器
.bucket {
 tr { // nested ruleset with target selector
   color: blue;
}
}
.some-class:extend(.bucket tr) {}
// nested ruleset is recognized
//"*"会导致继承时的不匹配, 其本身无意义
*.class {
 color: blue;
}
.noStar:extend(.class) {} // this will NOT match the *.class selector
//伪类的顺序会导致继承不匹配
link:hover:visited {
 color: blue;
}
.selector:extend(link:visited:hover) {}
?
//compile to
link:hover:visited {
 color: blue;
}
//nth表达式里 n+3 和 1n+3 等价,但会导致继承不匹配
:nth-child(1n+3) {
 color: blue;
}
.child:extend(:nth-child(n+3)) {}
?
//compile to
:nth-child(1n+3) {
 color: blue;
}
//选择 class 属性中同时有 name1 和 name2 的所有元素
.name1.name2 {}
//extend all
//:extend(.test all)表示继承所有包含.test的选择器
.a.b.test,
.test.c {
 color: orange;
}
.test {
 &:hover {
   color: green;
}
}
?
.replacement:extend(.test all) {}
?
//compile to
.a.b.test,
.test.c,
.a.b.replacement,
.replacement.c {
 color: orange;
}
.test:hover,
.replacement:hover {
 color: green;
}
//选择器为变量的无法被继承
@variable: .bucket;
@{variable} { // interpolated selector
 color: blue;
}
.some-class:extend(.bucket) {} // does nothing, no match is found
?
//compile to
.bucket {
 color: blue;
}
//@media声明中的选择器无法继承声明外的选择器
@media print {
 .screenClass:extend(.selector) {} // extend inside media
 .selector { // this will be matched - it is in the same media
   color: black;
}
}
.selector { // ruleset on top of style sheet - extend ignores it
 color: red;
}
@media screen {
 .selector {  // ruleset inside another media - extend ignores it
   color: blue;
}
}
?
//compile to
@media print {
 .selector,
 .screenClass { /* ruleset inside the same media was extended */
   color: black;
}
}
.selector { /* ruleset on top of style sheet was ignored */
 color: red;
}
@media screen {
 .selector { /* ruleset inside another media was ignored */
   color: blue;
}
}
//@media声明中的选择器无法继承其子@media声明的选择器
@media screen {
 .screenClass:extend(.selector) {} // extend inside media
 @media (min-width: 1023px) {
   .selector {  // ruleset inside nested media - extend ignores it
     color: blue;
  }
}
}
?
//compile to
@media screen and (min-width: 1023px) {
 .selector { /* ruleset inside another nested media was ignored */
   color: blue;
}
}
//顶级选择器可继承任何选择器
@media screen {
 .selector {  /* ruleset inside nested media - top level extend works */
   color: blue;
}
 @media (min-width: 1023px) {
   .selector {  /* ruleset inside nested media - top level extend works */
     color: blue;
  }
}
}
?
.topLevel:extend(.selector) {} /* top level extend matches everything */
?
//compile to
@media screen {
 .selector,
 .topLevel { /* ruleset inside media was extended */
   color: blue;
}
}
@media screen and (min-width: 1023px) {
 .selector,
 .topLevel { /* ruleset inside nested media was extended */
   color: blue;
}
}
//无冗余检查
.alert-info,
.widget {
 /* declarations */
}
?
.alert:extend(.alert-info, .widget) {}
?
//compile to
.alert-info,
.widget,
.alert,
.alert {
 /* declarations */
}
//mixins
//()可选
.a, #b {
 color: red;
}
.mixin-class {
 .a();
}
.mixin-id {
 #b;
}
?
//compile to
.a, #b {
 color: red;
}
.mixin-class {
 color: red;
}
.mixin-id {
 color: red;
}
//创建mixin时添加括号可不编译该选择器
.my-mixin {
 color: black;
}
.my-other-mixin() {
 background: white;
}
.class {
 .my-mixin;
 .my-other-mixin;
}
?
//compile to
.my-mixin {
 color: black;
}
.class {
 color: black;
 background: white;
}
//命名空间
#outer {
 .inner {
   color: red;
}
}
?
.c {
 #outer > .inner;
}
?
//空格和">"可选
// all do the same thing
#outer > .inner;
#outer > .inner();
#outer .inner;
#outer .inner();
#outer.inner;
#outer.inner();
//受保护的命名空间(条件命名空间)
#namespace when (@mode=huge) {
 .mixin() { /* */ }
}
?
#namespace {
 .mixin() when (@mode=huge) { /* */ }
}
//调用mixin时添加!important关键字表示继承的所有属性标记为!important
.foo (@bg: #f5f5f5, @color: #900) {
 background: @bg;
 color: @color;
}
.unimportant {
 .foo();
}
.important {
 .foo() !important;
}
?
//compile to
.unimportant {
 background: #f5f5f5;
 color: #900;
}
.important {
 background: #f5f5f5 !important;
 color: #900 !important;
}
//带参mixin
.border-radius(@radius) {
 -webkit-border-radius: @radius;
    -moz-border-radius: @radius;
         border-radius: @radius;
}
?
//参数可带默认值
.border-radius(@radius: 5px) {
 -webkit-border-radius: @radius;
    -moz-border-radius: @radius;
         border-radius: @radius;
}
?
//具名参数
.mixin(@color: black; @margin: 10px; @padding: 20px) {
 color: @color;
 margin: @margin;
 padding: @padding;
}
.class1 {
 .mixin(@margin: 20px; @color: #33acfe);
}
.class2 {
 .mixin(#efca44; @padding: 40px);
}
?
//compile to
.class1 {
 color: #33acfe;
 margin: 20px;
 padding: 20px;
}
.class2 {
 color: #efca44;
 margin: 10px;
 padding: 40px;
}
//@arguments变量整体赋值
.box-shadow(@x: 0; @y: 0; @blur: 1px; @color: #000) {
 -webkit-box-shadow: @arguments;
    -moz-box-shadow: @arguments;
         box-shadow: @arguments;
}
.big-block {
 .box-shadow(2px; 5px);
}
?
//compile to
.big-block {
 -webkit-box-shadow: 2px 5px 1px #000;
    -moz-box-shadow: 2px 5px 1px #000;
         box-shadow: 2px 5px 1px #000;
}
//@rest变量, 下例表示匹配@a后的所有变量
.mixin(@a; @rest...) {
  // @rest is bound to arguments after @a
  // @arguments is bound to all arguments
}
//mixin的重载 + 常量作形参 起 判断作用
.mixin(dark; @color) {
 color: darken(@color, 10%);
}
.mixin(light; @color) {
 color: lighten(@color, 10%);
}
.mixin(@_; @color) {
 display: block;
}
?
//使用
@switch: light;
?
.class {
 .mixin(@switch; #888);
}
//在mixin里定义变量, 调用它们时即可注入这些变量
.mixin() {
 @width:  100%;
 @height: 200px;
}
?
.caller {
 .mixin();
 width:  @width;
 height: @height;
}
?
//compile to
.caller {
 width:  100%;
 height: 200px;
}
//在mixin中定义mixin, 调用以注入mixin
.unlock(@value) { // outer mixin
 .doSomething() { // nested mixin
   declaration: @value;
}
}
?
#namespace {
 .unlock(5); // unlock doSomething mixin
 .doSomething(); //nested mixin was copied here and is usable
}
?
//compile to
#namespace {
 declaration: 5;
}
//打包 media查询 和 不支持的类名(包含空格)
//{***: **;} 的语句可以作为参数
.desktop-and-old-ie(@rules) {
 @media screen and (min-width: 1200) { @rules(); }
 html.lt-ie9 &                       { @rules(); }
}
?
header {
 background-color: blue;
?
 .desktop-and-old-ie({
   background-color: red;
});
}
?
//compile to
header {
 background-color: blue;
}
@media screen and (min-width: 1200) {
 header {
   background-color: red;
}
}
html.lt-ie9 header {
 background-color: red;
}

一条原则, mixin内的所有内容都会被return出去

A detached ruleset sees the caller's variables and mixins (但全局变量会覆盖调用时的局部变量)

//拿不到@one变量
@detached-1: { scope-detached: @one @two; };
.one {
 @one: visible;
 .two {
   @detached-2: @detached-1; // copying/renaming ruleset
   @two: visible; // ruleset can not see this variable
}
}
?
.use-place {
 .one > .two(); //报错
 @detached-2();
}

import语句可放在任意位置

import options

Syntax: @import (keyword) "filename";

可同时使用多关键字

  • reference: use a Less file but do not output it

  • inline: include the source file in the output but do not process it

  • less: treat the file as a Less file, no matter what the file extension

  • css: treat the file as a CSS file, no matter what the file extension

  • once: only include the file once (this is default behavior)

  • multiple: include the file multiple times

  • optional: continue compiling when file is not found

//mixin守卫
.mixin (@a) when (lightness(@a) >= 50%) {
 background-color: black;
}
.mixin (@a) when (lightness(@a) < 50%) {
 background-color: white;
}
.mixin (@a) {
 color: @a;
}
.class1 { .mixin(#ddd) }
.class2 { .mixin(#555) }
?
//compile to
.class1 {
 background-color: black;
 color: #ddd;
}
.class2 {
 background-color: white;
 color: #555;
}

运算符: >,>=,=,=<,<

//类型检查函数
iscolor
isnumber
isstring
iskeyword
isurl
?
//带单位的值
ispixel
ispercentage
isem
isunit
//默认mixin
.mixin (@a) when (@a > 0) { ... }
.mixin (@a) when (default()) { ... } // matches only if first mixin does not, i.e. when @a <= 0
//mixin守卫可用于普通css选择器
button when (@my-option = true) {
 color: white;
}
//通过 & 可连接多个mixin守卫
button when (@my-option = true) {
 color: white;
}
& when (@my-option = true) {
 button {
   color: white;
}
 a {
   color: blue;
}
}
//循环
.generate-columns(4);
?
.generate-columns(@n, @i: 1) when (@i =< @n) {
 .column-@{i} {
   width: (@i * 100% / @n);
}
 .generate-columns(@n, (@i + 1));
}
?
//compile to
.column-1 {
 width: 25%;
}
.column-2 {
 width: 50%;
}
.column-3 {
 width: 75%;
}
.column-4 {
 width: 100%;
}
//属性名后添加 +, 表示多个遇到多个该属性时不覆盖, 而是合并, 并以 ","分隔
.mixin() {
 box-shadow+: inset 0 0 10px #555;
}
.myclass {
 .mixin();
 box-shadow+: 0 0 20px black;
}
?
//compile to
.myclass {
 box-shadow: inset 0 0 10px #555, 0 0 20px black;
}
//属性名后添加 +_, 表示多个遇到多个该属性时不覆盖, 而是合并, 并以 空格 分隔
.mixin() {
 transform+_: scale(2);
}
.myclass {
 .mixin();
 transform+_: rotate(15deg);
}
?
//compile to
.myclass {
 transform: scale(2) rotate(15deg);
}
//&- 符号
.button {
 &-ok {
   background-image: url("ok.png");
}
 &-cancel {
   background-image: url("cancel.png");
}
?
 &-custom {
   background-image: url("custom.png");
}
}
?
//compile to
.button-ok {
 background-image: url("ok.png");
}
.button-cancel {
 background-image: url("cancel.png");
}
.button-custom {
 background-image: url("custom.png");
}
.link {
 & + & {
   color: red;
}
?
 & & {
   color: green;
}
?
 && {
   color: blue;
}
?
 &, &ish {
   color: cyan;
}
}
?
//compile to
.link + .link {
 color: red;
}
.link .link {
 color: green;
}
.link.link {
 color: blue;
}
.link, .linkish {
 color: cyan;
}
//意味着多层嵌套的时候 & 符号不好用
.grand {
 .parent {
   & > & {
     color: red;
  }
?
   & & {
     color: green;
  }
?
   && {
     color: blue;
  }
?
   &, &ish {
     color: cyan;
  }
}
}
?
//compile to
.grand .parent > .grand .parent {
 color: red;
}
.grand .parent .grand .parent {
 color: green;
}
.grand .parent.grand .parent {
 color: blue;
}
.grand .parent,
.grand .parentish {
 color: cyan;
}
//通过 & 符号改变选择器嵌套顺序
.header {
 .menu {
   border-radius: 5px;
   .no-borderradius & {
     background-image: url('images/button-background.png');
  }
}
}
?
//compile to
.header .menu {
 border-radius: 5px;
}
.no-borderradius .header .menu {
 background-image: url('images/button-background.png');
}
//& 可以用来生成组合, 外层选择器列表以 逗号 分隔时
p, a, ul, li {
 border-top: 2px dotted #366;
 & + & {
   border-top: 0;
}
}
?
//compile to
p,
a,
ul,
li {
 border-top: 2px dotted #366;
}
p + p,
p + a,
p + ul,
p + li,
a + p,
a + a,
a + ul,
a + li,
ul + p,
ul + a,
ul + ul,
ul + li,
li + p,
li + a,
li + ul,
li + li {
 border-top: 0;
}