Less 入门手册

301 阅读11分钟

Less入门与提升

使用vscode插件进行操作

less 会在保存后自动转化为css文件因此编辑的html绑定好对应css代码就可以了

变量

@变量名:变量值;

选择器就使用@{变量}

作为URL:@{url}路径的时候就可以这样写

提升篇:

1.变量可以是属性名也可以是部分属性名,也可以出现嵌套变量名

2.变量名不必提前声明,也可以放后面声明,不需要那么严谨

3.如果只有多个相同声明就选最下面的为变量值

4.copy 属性 用$属性名

5.引入less

//1.变量可以是属性名也可以是部分属性名,也可以出现嵌套变量名
@primary:  green;
@secondary: blue;

.section {
  @color: primary;

  .element {
    color: @@color;
  }
}
//2.变量名不必提前声明,也可以放后面声明,不需要那么严谨
.lazy-eval {
  width: @var;
  @a: 9%;
}

@var: @a;
@a: 100%;
//or
.lazy-eval {
  width: @var;
}

@var: @a;
@a: 9%;
//编译后
.lazy-eval {
  width: 9%;
}
//4.copy 属性 用$属性名,同样是出现属性最下原则
.widget {
  color: #efefef;
  background-color: $color;
}
//编译后
.widget {
  color: #efefef;
  background-color: #efefef;
}

嵌套

选择器具有父子关系可以省略相同的关系

父类包裹子类

父类与子类选择器要使用& (相当于父类的代号)

&表示所有的父类

#header {
  color: black;
  .navigation {
    font-size: 12px;
  }
  .logo {
    width: 300px;
  }
}
clearfix {
  display: block;
  zoom: 1;

  &:after {
    content: " ";
    display: block;
    font-size: 0;
    height: 0;
    clear: both;
    visibility: hidden;
  }
}

提升篇

//&可以用于重复命名类
.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;
  }
}
//编译后
.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;
    }
  }
}
//编译后
.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');
    }
  }
}
//编译后
.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;
  }
}
//编译后
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;
}

Extend伪类

Extend是一个Less伪类,它把它放在的选择器与它所引用的选择器合并,就是公用属性,公用的是括号里面规则的属性(括号里面要先好)

nav ul {
  &:extend(.inline);
  background: blue;
}
.inline {
  color: red;
}
//编译后
nav ul {
  background: blue;
}
.inline,
nav ul {
  color: red;
}
//同样的写法
.c:extend(.d all) {
  // extends all instances of ".d" e.g. ".x.d" or ".d.x"
}
//也可以合并写
.e:extend(.f) {}
.e:extend(.g) {}

// the above and the below do the same thing
.e:extend(.f, .g) {}
//可以分开写
.bucket {
  tr & { // nested ruleset with target selector
    color: blue;
  }
}
.some-class:extend(tr .bucket) {} // nested ruleset is recognized
//编译后
tr .bucket,
.some-class {
  color: blue;
}

//******不能共用属性的情况
.a.class,
.class.a,
.class > .a {
  color: blue;
}
.test:extend(.class) {} // this will NOT match the any selectors above
//or
*.class {
  color: blue;
}
//编译后
.noStar:extend(.class) {} // this will NOT match the *.class selector
//同时不能识别特别表达方式
link:hover:visited {
  color: blue;
}
.selector:extend(link:visited:hover) {}
//********选择具体子节点也不行
:nth-child(1n+3) {
  color: blue;
}
.child:extend(:nth-child(n+3)) {}
//编译后
:nth-child(1n+3) {
  color: blue;
}
//属性选择器的多种表达都是可以的
[title=identifier] {
  color: blue;
}
[title='identifier'] {
  color: blue;
}
[title="identifier"] {
  color: blue;
}

.noQuote:extend([title=identifier]) {}
.singleQuote:extend([title='identifier']) {}
.doubleQuote:extend([title="identifier"]) {}
//编译后
[title=identifier],
.noQuote,
.singleQuote,
.doubleQuote {
  color: blue;
}

[title='identifier'],
.noQuote,
.singleQuote,
.doubleQuote {
  color: blue;
}

[title="identifier"],
.noQuote,
.singleQuote,
.doubleQuote {
  color: blue;
}
//all的使用当你在extend参数中最后指定all关键字时,它告诉Less将该选择器作为另一个选择器的一部分来匹配。该选择器将被复制,然后选择器中仅有的匹配部分将被替换成extend,成为一个新的选择器
.a.b.test,
.test.c {
  color: orange;
}
.test {
  &:hover {
    color: green;
  }
}
.replacement:extend(.test all) {}
//编译后
.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
//or
.bucket {
  color: blue;
}
.some-class:extend(@{variable}) {} // interpolated selector matches nothing
@variable: .bucket
//放括号外面可以
.bucket {
  color: blue;
}
@{variable}:extend(.bucket) {}
@variable: .selector;    
//@media 里面的只能匹配里面的,下一级@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;
  }
}
//编译后
@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;
  }
}
//重复共用不会删除
.alert-info,
.widget {
  /* declarations */
}
//编辑后
.alert:extend(.alert-info, .widget) {}
.alert-info,
.widget,
.alert,
.alert {
  /* declarations */
}
//extend 可以只写一个类就行了
<a class="animal bear">Bear</a>
.animal {
  background-color: black;
  color: white;
}
.bear {
  background-color: brown;
}
//可以写成下面的形式
<a class="bear">Bear</a>
.animal {
  background-color: black;
  color: white;
}
.bear {
  &:extend(.animal);
  background-color: brown;
}

总之,extend可以解决许多重复代码问题

混合

一个选择器包裹另外一个选择器的属性而不是父子关系(类似与函数调用)

定义的"函数"不会出现在css

无参数类型,中间没有括号或是插入空格是无效的

#menu a {
  color: #111;
  .bordered();
}

.post a {
  color: red;
  .bordered();
}
.bordered {
  border-top: dotted 1px black;
  border-bottom: solid 2px black;
}
//已经写好规则可以直接采用无参数形式引用
.my-mixin {
  color: black;
}
.my-other-mixin() {
  background: white;
}
.class {
  .my-mixin();
  .my-other-mixin();
}
//编译后
.my-mixin {
  color: black;
}
.class {
  color: black;
  background: white;
}
//带有父类选择器的融合
.my-hover-mixin() {
  &:hover {
    border: 1px solid red;
  }
}
button {
  .my-hover-mixin();
}
//编辑后
button:hover {
  border: 1px solid red;
}
//复杂的重叠结构可以简化
#outer() {
  .inner {
    color: red;
  }
}
//比如
.c {
  #outer.inner();
}
//在 mixin 调用后使用 !important 关键字将其继承的所有属性标记为 !important:
.foo (@bg: #f5f5f5; @color: #900) {
  background: @bg;
  color: @color;
}
.unimportant {
  .foo();
}
.important {
  .foo() !important;
}
//编辑
.unimportant {
  background: #f5f5f5;
  color: #900;
}
.important {
  background: #f5f5f5 !important;
  color: #900 !important;
}


也可以使用类似构造器的形式调用,使用有参形式

#menu a {
  color: #111;
  .bordered(2px);
}

.post a {
  color: red;
  .bordered(2px);
}
.bordered(@W) {
  border-top: dotted @W black;
  border-bottom: solid 2px black;
}
//如果内部已经定义好了数值就可以进行无参调用
.border-radius(@radius: 5px) {
  -webkit-border-radius: @radius;
     -moz-border-radius: @radius;
          border-radius: @radius;
}
#header {
  .border-radius();
}
//多参数传递时
//多变量用逗号隔开可以是值,变量,赋值的变量,列表.name(@param1: ~(red, blue))
// 进行重载,只要形参都有值就会调用
.mixin(@color) {
  color-1: @color;
}
.mixin(@color, @padding: 2) {
  color-2: @color;
  padding-2: @padding;
}
.mixin(@color, @padding, @margin: 2) {
  color-3: @color;
  padding-3: @padding;
  margin: @margin @margin @margin @margin;
}
.some .selector div {
  .mixin(#008000);
}
//编译后
.some .selector div {
  color-1: #008000;
  color-2: #008000;
  padding-2: 2;
}
// 实参会顶替带值的形参
.mixin(@color: black; @margin: 10px; @padding: 20px) {
  color: @color;
  margin: @margin;
  padding: @padding;
}
.class1 {
  .mixin(@margin: 20px; @color: #33acfe);
}
.class2 {
  .mixin(#efca44; @padding: 40px);
}
//编译后
.class1 {
  color: #33acfe;
  margin: 20px;
  padding: 20px;
}
.class2 {
  color: #efca44;
  margin: 10px;
  padding: 40px;
}
//@arguments 在 mixin 中具有特殊含义,它包含调用 mixin 时传递的所有参数。 如果您不想处理单个参数,这很有用(会根据形参数据一一代入)
.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);
}
//编译后
.big-block {
  -webkit-box-shadow: 2px 5px 1px #000;
     -moz-box-shadow: 2px 5px 1px #000;
          box-shadow: 2px 5px 1px #000;
}
//灵活的参数设置 ... 
.mixin(...) {        // matches 0-N arguments
.mixin() {           // matches exactly 0 arguments
.mixin(@a: 1) {      // matches 0-1 arguments
.mixin(@a: 1, ...) { // matches 0-N arguments
.mixin(@a, ...) {    // matches 1-N arguments
    .mixin(@a, @rest...) {
   // @rest is bound to arguments after @a
   // @arguments is bound to all arguments
}
// 开关选择规则
    .mixin(dark, @color) {
    color: darken(@color, 10%);
  }
  .mixin(light, @color) {
    color: lighten(@color, 10%);
  }
  .mixin(@_, @color) {
    display: block;
  }

  @switch: light;

.class {
  .mixin(@switch, #888);
}
//编译后
    .class {
  color: #a2a2a2;
  display: block;
}
//抢夺定义定义两个数就用第二个代替  
    .mixin(@a) {
  color: @a;
}
.mixin(@a, @b) {
  color: fade(@a, @b);
}
 //用函数形式调用
    .average(@x, @y) {
  @result: ((@x + @y) / 2);
}

div {
  // call a mixin and look up its "@result" value
  padding: .average(16px, 50px)[@result];
}
 //函数调用形式
   #theme.dark.navbar {
  .colors(light) {
    primary: purple;
  }
  .colors(dark) {
    primary: black;
    secondary: grey;
  }
}

.navbar {
  @colors: #theme.dark.navbar.colors(dark);
  background: @colors[primary];
  border: 1px solid @colors[secondary];
}
    //编译后
    .navbar {
  background: black;
  border: 1px solid grey;
}
// 嵌套调用
 #library() {
  .colors() {
    background: green;
  }
}
.box {
  @alias: #library.colors();
  @alias();
}
 //编译后
    .box {
  background: green;
}
  //开关选择属性(用函数判断实现)
    @config: {
  option1: true;
  option2: false;
}

.mixin() when (@config[option1] = true) {
  selected: value;
}

.box {
  .mixin();
}
  //编译后
.box {
  selected: value;
}
 //多重嵌套函数使用的方法
        @config: {
  @dark: {
    primary: darkblue;
  }
  @light: {
    primary: lightblue;
  }
}
//编译后
.box {
  @lookup: dark;
  color: @config[@@lookup][primary];
}

@规则嵌套和冒泡

@ 规则(例如 @media 或 @supports)可以与选择器以相同的方式进行嵌套。@ 规则会被放在前面,同一规则集中的其它元素的相对顺序保持不变。这叫做冒泡(bubbling)

component {
  width: 300px;
  @media (min-width: 768px) {
    width: 600px;
    @media  (min-resolution: 192dpi) {
      background-image: url(/img/retina2x.png);
    }
  }
  @media (min-width: 1280px) {
    width: 800px;
  }
}

运算

算术运算符 +-*/ 可以对任何数字、颜色或变量进行运算。如果可能的话,算术运算符在加、减或比较之前会进行单位换算。计算的结果以最左侧操作数的单位类型为准。如果单位换算无效或失去意义,则忽略单位。无效的单位换算例如:px 到 cm 或 rad 到 % 的转换。

// 所有操作数被转换成相同的单位
@conversion-1: 5cm + 10mm; // 结果是 6cm
@conversion-2: 2 - 3cm - 5mm; // 结果是 -1.5cm

// conversion is impossible
@incompatible-units: 2 + 5px - 3cm; // 结果是 4px

// example with variables
@base: 5%;
@filler: @base * 2; // 结果是 10%
@other: @base + @filler; // 结果是 15%

乘法和除法不作转换。因为这两种运算在大多数情况下都没有意义,一个长度乘以一个长度就得到一个区域,而 CSS 是不支持指定区域的。Less 将按数字的原样进行操作,并将为计算结果指定明确的单位类型你还可以对颜色进行算术运算:。

可以使用特殊的函数进行计算

@var: 50vh/2;
width: calc(50% + (@var - 20px));  // 结果是 calc(50% + (25vh - 20px))

转义

转义(Escaping)允许你使用任意字符串作为属性或变量值。任何 ~"anything"~'anything' 形式的内容都将按原样输出,除非 interpolation。使用字符表示值不可以不用转义

@min768: (min-width: 768px);
.element {
  @media @min768 {
    font-size: 1.2rem;
  }
}

函数

用于快速实现某些功能具体操作

@base: #f04615;
@width: 0.5;

.class {
  width: percentage(@width); // returns `50%`
  color: saturate(@base, 5%);
  background-color: spin(lighten(@base, 25%), 8);
}

命名空间与访问符

对内部的部分属性进行分组,并且可以用于外部混合

#bundle() {
  .button {
    display: block;
    border: 1px solid black;
    background-color: grey;
    &:hover {
      background-color: white;
    }
  }
  .tab { ... }
  .citation { ... }
}
#header a {
  color: orange;
  #bundle.button();  // 还可以书写为 #bundle > .button 形式
}

映射

直接从一个混合集里获取元素

#colors() {
  primary: blue;
  secondary: green;
}

.button {
  color: #colors[primary];
  border: 1px solid #colors[secondary];
}

//编译结果
.button {
  color: blue;
  border: 1px solid green;
}

作用域

变量的主要范围就近原则由内到外

注释

/ *

多行注释 */

//单行注释

导入

“导入”的工作方式和你预期的一样。你可以导入一个 .less 文件,此文件中的所有变量就可以全部使用了。如果导入的文件是 .less 扩展名,则可以将扩展名省略掉如果该文件的扩展名是.css,它将被视为CSS,并且@import语句保持原样(见下面的内联选项)。如果它有任何其他扩展名,它将被视为Less并被导入如果它没有扩展名,.less将被附加,它将被作为一个导入的Less文件。导入可以设置选项

@import "library"; // library.less
@import "typo.css";

Less提供了对CSS @import at-rule的一些扩展,为你对外部文件的处理提供了更多的灵活性。

语法。@import (keyword) "filename";

以下的导入选项已经实现。

reference:使用一个Less文件,但不输出它 在混合与拓展的时候调用就会使用不会显示原来的属性 inline:在输出中包括源文件,但不处理它 less:将文件视为Less文件,不管文件的扩展名是什么 css:将该文件视为CSS文件,不管其扩展名是什么 once: 只包含一次文件(这是默认行为)。 multiople:多次包含同样文件 可选的:在没有找到文件时继续编译 每个@import允许有一个以上的关键词,你必须用逗号来分隔这些关键词。

例子。@import(可选,参考)"foo.less"。

插入插件

Using a @plugin at-rule is similar to using an @import for your .less files. 用于插入js文件

@plugin "my-plugin";  // automatically appends .js if no extension
@plugin "my-plugin";
.show-me-pi {
  value: pi();
}
//编译结果
.show-me-pi {
  value: 3.141592653589793;
}
//插件符合作用域规则
.el-1 {
    @plugin "lib1";
    value: foo();
}
.el-2 {
    @plugin "lib2";
    value: foo();
}
//
.el-1 {
    value: foo;
}
.el-2 {
    value: bar;
}

maps

@sizes: {
  mobile: 320px;
  tablet: 768px;
  desktop: 1024px;
}

.navbar {
  display: block;

  @media (min-width: @sizes[tablet]) {
    display: inline-block;
  }
}
    //编译后
    
    .navbar {
  display: block;
}
@media (min-width: 768px) {
  .navbar {
    display: inline-block;
  }
}