快速入门
概览
变量(Variables)
混合(Mixins)
嵌套(Nesting)
运算(Operations)
转义(Escaping)
函数(Functions)
命名空间和访问符
映射(Maps)
作用域(Scope)
注释(Comments)
导入(Importing)
Less.js 用法
命令行用法
浏览器使用
Less.js选项
预装插件
程序化使用
API
Contributing to Less.js
Less 函数手册
逻辑函数
字符串函数
列表函数
数学函数
类型函数
其他功能
颜色定义函数
颜色通道函数
颜色操作函数
颜色混合函数
进阶指南
合并
父选择器
扩展
变量
Mixins
CSS Guards
Detached Rulesets
@import At-Rules
@plugin At-Rules
Maps (NEW!)
Less入门文档
网站首页
Mixins
"mix-in" properties from existing styles You can mix-in class selectors and id selectors, e.g. ```less .a, #b { color: red; } .mixin-class { .a(); } .mixin-id { #b(); } ``` which results in: ```less .a, #b { color: red; } .mixin-class { color: red; } .mixin-id { color: red; } ``` Currently and historically, the parentheses in a mixin call are optional, but optional parentheses are deprecated and will be required in a future release. ```less .a(); .a; // currently works, but deprecated; don't use ``` ### Not Outputting the Mixin If you want to create a mixin but you do not want that mixin to be in your CSS output, put parentheses after the mixin definition. ```less .my-mixin { color: black; } .my-other-mixin() { background: white; } .class { .my-mixin(); .my-other-mixin(); } ``` outputs ```less .my-mixin { color: black; } .class { color: black; background: white; } ``` ### Selectors in Mixins Mixins can contain more than just properties, they can contain selectors too. For example: ```less .my-hover-mixin() { &:hover { border: 1px solid red; } } button { .my-hover-mixin(); } ``` Outputs ```less button:hover { border: 1px solid red; } ``` ### Namespaces If you want to mixin properties inside a more complicated selector, you can stack up multiple id's or classes. ```less #outer() { .inner { color: red; } } .c { #outer > .inner(); } ``` Both > and whitespace are optional ```less // all do the same thing #outer > .inner(); #outer .inner(); #outer.inner(); ``` Namespacing your mixins like reduces conflict with other library mixins or user mixins, but it can also be a way to "organize" groups of mixins. Example: ```less #my-library { .my-mixin() { color: black; } } // which can be used like this .class { #my-library.my-mixin(); } ``` ### Guarded Namespaces If a namespace has a guard, mixins defined by it are used only if the guard condition returns true. A namespace guard is evaluated exactly the same way as a guard on mixin, so the following two mixins work the same way: ```less #namespace when (@mode = huge) { .mixin() { /* */ } } #namespace { .mixin() when (@mode = huge) { /* */ } } ``` The default function is assumed to have the same value for all nested namespaces and mixin. Following mixin is never evaluated, one of its guards is guaranteed to be false: ```less #sp_1 when (default()) { #sp_2 when (default()) { .mixin() when not(default()) { /* */ } } } ``` ### The !important keyword Use the !important keyword after mixin call to mark all properties inherited by it as !important: Example: ```less .foo (@bg: #f5f5f5, @color: #900) { background: @bg; color: @color; } .unimportant { .foo(); } .important { .foo() !important; } ``` Results in: ```less .unimportant { background: #f5f5f5; color: #900; } .important { background: #f5f5f5 !important; color: #900 !important; } ``` ### Parametric Mixins #### How to pass arguments to mixins Mixins can also take arguments, which are variables passed to the block of selectors when it is mixed in. For example: ```less .border-radius(@radius) { -webkit-border-radius: @radius; -moz-border-radius: @radius; border-radius: @radius; } ``` And here's how we can mix it into various rulesets: ```less #header { .border-radius(4px); } .button { .border-radius(6px); } ``` Parametric mixins can also have default values for their parameters: ```less .border-radius(@radius: 5px) { -webkit-border-radius: @radius; -moz-border-radius: @radius; border-radius: @radius; } ``` We can invoke it like this now: ```less #header { .border-radius(); } ``` And it will include a 5px border-radius. You can also use parametric mixins which don't take parameters. This is useful if you want to hide the ruleset from the CSS output, but want to include its properties in other rulesets: ```less .wrap() { text-wrap: wrap; white-space: -moz-pre-wrap; white-space: pre-wrap; word-wrap: break-word; } pre { .wrap() } ``` Which would output: ```less pre { text-wrap: wrap; white-space: -moz-pre-wrap; white-space: pre-wrap; word-wrap: break-word; } ``` #### Mixins with Multiple Parameters Parameters are either semicolon or comma separated. It is recommended to use semicolon. The symbol comma has double meaning: it can be interpreted either as a mixin parameters separator or css list separator. Using comma as mixin separator makes it impossible to create comma separated lists as an argument. On the other hand, if the compiler sees at least one semicolon inside mixin call or declaration, it assumes that arguments are separated by semicolons and all commas belong to css lists: two arguments and each contains comma separated list: `.name(1, 2, 3; something, else)`, three arguments and each contains one number: `.name(1, 2, 3)`, use dummy semicolon to create mixin call with one argument containing comma separated css list: `.name(1, 2, 3;)`, comma separated default value: `.name(@param1: red, blue;)`. It is legal to define multiple mixins with the same name and number of parameters. Less will use properties of all that can apply. If you used the mixin with one parameter e.g. .mixin(green);, then properties of all mixins with exactly one mandatory parameter will be used: ```less .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); } ``` compiles into: ```less .some .selector div { color-1: #008000; color-2: #008000; padding-2: 2; } ``` #### Named Parameters A mixin reference can supply parameters values by their names instead of just positions. Any parameter can be referenced by its name and they do not have to be in any special order: ```less .mixin(@color: black; @margin: 10px; @padding: 20px) { color: @color; margin: @margin; padding: @padding; } .class1 { .mixin(@margin: 20px; @color: #33acfe); } .class2 { .mixin(#efca44; @padding: 40px); } ``` compiles into: ```less .class1 { color: #33acfe; margin: 20px; padding: 20px; } .class2 { color: #efca44; margin: 10px; padding: 40px; } ``` #### The @arguments Variable @arguments has a special meaning inside mixins, it contains all the arguments passed, when the mixin was called. This is useful if you don't want to deal with individual parameters: ```less .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); } ``` Which results in: ```less .big-block { -webkit-box-shadow: 2px 5px 1px #000; -moz-box-shadow: 2px 5px 1px #000; box-shadow: 2px 5px 1px #000; } ``` #### Advanced Arguments and the @rest Variable You can use ... if you want your mixin to take a variable number of arguments. Using this after a variable name will assign those arguments to the variable. ```less .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 ``` Furthermore: ```less .mixin(@a; @rest...) { // @rest is bound to arguments after @a // @arguments is bound to all arguments } ``` ### Pattern-matching Sometimes, you may want to change the behavior of a mixin, based on the parameters you pass to it. Let's start with something basic: ```less .mixin(@s; @color) { ... } .class { .mixin(@switch; #888); } ``` Now let's say we want .mixin to behave differently, based on the value of @switch, we could define .mixin as such: ```less .mixin(dark; @color) { color: darken(@color, 10%); } .mixin(light; @color) { color: lighten(@color, 10%); } .mixin(@_; @color) { display: block; } ``` Now, if we run: ```less @switch: light; .class { .mixin(@switch; #888); } ``` We will get the following CSS: ```less .class { color: #a2a2a2; display: block; } ``` Where the color passed to `.mixin` was lightened. If the value of `@switch` was `dark`, the result would be a darker color. Here's what happened: - The first mixin definition didn't match because it expected `dark` as the first argument. - The second mixin definition matched, because it expected `light`. - The third mixin definition matched because it expected any value. Only mixin definitions which matched were used. Variables match and bind to any value. Anything other than a variable matches only with a value equal to itself. We can also match on arity, here's an example: ```less .mixin(@a) { color: @a; } .mixin(@a; @b) { color: fade(@a; @b); } ``` Now if we call `.mixin` with a single argument, we will get the output of the first definition, but if we call it with two arguments, we will get the second definition, namely `@a` faded to `@b`. ### Using Mixins as Functions Selecting properties and variables from mixin calls #### Property / value accessors Released v3.5.0 Starting in Less 3.5, you can use property/variable accessors to select a value from an evaluated mixin's rules. This can allow you to use mixins similar to functions. Example: ```less .average(@x, @y) { @result: ((@x + @y) / 2); } div { // call a mixin and look up its "@result" value padding: .average(16px, 50px)[@result]; } ``` Results in: ```less div { padding: 33px; } ``` #### Overriding mixin values If you have multiple matching mixins, all rules are evaluated and merged, and the last matching value with that identifier is returned. This is similar to the cascade in CSS, and it allows you to "override" mixin values. ```less // library.less #library() { .mixin() { prop: foo; } } // customize.less @import "library"; #library() { .mixin() { prop: bar; } } .box { my-value: #library.mixin[prop]; } ``` Outputs: ```less .box { my-value: bar; } ``` #### Unnamed lookups If you don't specify a lookup value in [`@lookup`] and instead write `[]` after a mixin or ruleset call, all values will cascade and the last declared value will be selected. Meaning: the averaging mixin from the above example could be written as: ```less .average(@x, @y) { @result: ((@x + @y) / 2); } div { // call a mixin and look up its final value padding: .average(16px, 50px)[]; } ``` The output is the same: ```less div { padding: 33px; } ``` The same cascading behavior is true for rulesets or variables aliased to mixin calls. ```less @dr: { value: foo; } .box { my-value: @dr[]; } ``` This outputs: ```less .box { my-value: foo; } ``` #### Unlocking mixins & variables into caller scope DEPRECATED - Use Property / Value Accessors Variables and mixins defined in a mixin are visible and can be used in caller's scope. There is only one exception: a variable is not copied if the caller contains a variable with the same name (that includes variables defined by another mixin call). Only variables present in callers local scope are protected. Variables inherited from parent scopes are overridden. Note: this behavior is deprecated, and in the future, variables and mixins will not be merged into the caller scope in this way. Example: ```less .mixin() { @width: 100%; @height: 200px; } .caller { .mixin(); width: @width; height: @height; } ``` Results in: ```less .caller { width: 100%; height: 200px; } ``` Variables defined directly in callers scope cannot be overridden. However, variables defined in callers parent scope is not protected and will be overridden: ```less .mixin() { @size: in-mixin; @definedOnlyInMixin: in-mixin; } .class { margin: @size @definedOnlyInMixin; .mixin(); } @size: globaly-defined-value; // callers parent scope - no protection ``` Results in: ```less .class { margin: in-mixin in-mixin; } ``` Finally, mixin defined in mixin acts as return value too: ```less .unlock(@value) { // outer mixin .doSomething() { // nested mixin declaration: @value; } } #namespace { .unlock(5); // unlock doSomething mixin .doSomething(); //nested mixin was copied here and is usable } ``` Results in: ```less #namespace { declaration: 5; } ``` ### Recursive Mixins #### Creating loops In Less a mixin can call itself. Such recursive mixins, when combined with Guard Expressions and Pattern Matching, can be used to create various iterative/loop structures. Example: ```less .loop(@counter) when (@counter > 0) { .loop((@counter - 1)); // next iteration width: (10px * @counter); // code for each iteration } div { .loop(5); // launch the loop } ``` Output: ```less div { width: 10px; width: 20px; width: 30px; width: 40px; width: 50px; } ``` A generic example of using a recursive loop to generate CSS grid classes: ```less .generate-columns(4); .generate-columns(@n, @i: 1) when (@i =< @n) { .column-@{i} { width: (@i * 100% / @n); } .generate-columns(@n, (@i + 1)); } ``` Output: ```less .column-1 { width: 25%; } .column-2 { width: 50%; } .column-3 { width: 75%; } .column-4 { width: 100%; } ``` ### Mixin Guards Guards are useful when you want to match on expressions, as opposed to simple values or arity. If you are familiar with functional programming, you have probably encountered them already. In trying to stay as close as possible to the declarative nature of CSS, Less has opted to implement conditional execution via guarded mixins instead of if/else statements, in the vein of @media query feature specifications. Let's start with an example: ```less .mixin(@a) when (lightness(@a) >= 50%) { background-color: black; } .mixin(@a) when (lightness(@a) < 50%) { background-color: white; } .mixin(@a) { color: @a; } ``` The key is the when keyword, which introduces a guard sequence (here with only one guard). Now if we run the following code: ```less .class1 { .mixin(#ddd) } .class2 { .mixin(#555) } ``` Here's what we'll get: ```less .class1 { background-color: black; color: #ddd; } .class2 { background-color: white; color: #555; } ``` #### Guard Comparison Operators The full list of comparison operators usable in guards are: `>`, `>=`, `=`, `=<`, `<`. Additionally, the keyword `true` is the only truthy value, making these two mixins equivalent: ```less .truth(@a) when (@a) { ... } .truth(@a) when (@a = true) { ... } ``` Any value other than the keyword true is falsy: ```less .class { .truth(40); // Will not match any of the above definitions. } ``` Note that you can also compare arguments with each other, or with non-arguments: ```less @media: mobile; .mixin(@a) when (@media = mobile) { ... } .mixin(@a) when (@media = desktop) { ... } .max(@a; @b) when (@a > @b) { width: @a } .max(@a; @b) when (@a < @b) { width: @b } ``` #### Guard Logical Operators You can use logical operators with guards. The syntax is based on CSS media queries. Use the and keyword to combine guards: ```less .mixin(@a) when (isnumber(@a)) and (@a > 0) { ... } ``` You can emulate the or operator by separating guards with a comma ,. If any of the guards evaluate to true, it's considered a match: ```less .mixin(@a) when (@a > 10), (@a < -10) { ... } ``` Use the not keyword to negate conditions: ```less .mixin(@b) when not (@b > 0) { ... } ``` #### Type Checking Functions Lastly, if you want to match mixins based on value type, you can use the is functions: ```less .mixin(@a; @b: 0) when (isnumber(@b)) { ... } .mixin(@a; @b: black) when (iscolor(@b)) { ... } ``` Here are the basic type checking functions: - `iscolor` - `isnumber` - `isstring` - `iskeyword` - `isurl` If you want to check if a value is in a specific unit in addition to being a number, you may use one of: - `ispixel` - `ispercentage` - `isem` - `isunit` ### Aliasing Mixins Released v3.5.0 #### Assigning mixin calls to a variable Mixins can be assigned to a variable to be called as a variable call, or can be used for map lookup. ```less #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]; } ``` This would output: ```less .navbar { background: black; border: 1px solid grey; } ``` #### Variable calls Entire mixin calls can be aliased and called as variable calls. As in: ```less #library() { .rules() { background: green; } } .box { @alias: #library.rules(); @alias(); } ``` Outputs: ```less .box { background: green; } ``` Note, unlike mixins used in root, mixin calls assigned to variables and called with no arguments always require parentheses. The following is not valid. ```less #library() { .rules() { background: green; } } .box { @alias: #library.colors; @alias(); // ERROR: Could not evaluate variable call @alias } ``` This is because it's ambiguous if variable is assigned a list of selectors or a mixin call. For example, in Less 3.5+, this variable could be used this way. ```less .box { @alias: #library.colors; @{alias} { a: b; } } ``` The above would output: ```less .box #library.colors { a: b; } ```
上一篇:
合并
下一篇:
CSS Guards