Skip to content

Commit

Permalink
Update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
matthew-dean committed May 8, 2023
1 parent 579e60c commit a83d035
Show file tree
Hide file tree
Showing 8 changed files with 6,123 additions and 185 deletions.
16 changes: 11 additions & 5 deletions content/features/mixins-parametric.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,17 @@ Parameters are currently either *semicolon* or *comma* separated.

Originally, parameters were only separated by commas, but the semi-colon was later added to support passing comma-separated list values to single arguments.

* 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;)`.
* As of Less 4.0, you can wrap a list value using a paren escape [`~()`], e.g. `.name(@param1: ~(red, blue))`. This is similar to the quote escape syntax: `~"quote"`
Note: As of Less 4.0, you can wrap a list value using a paren escape [`~()`], e.g. `.name(@param1: ~(red, blue))`. This is similar to the quote escape syntax: `~"quote"`. This may make semi-colon separators un-necessary in your code-base.

Examples:

* 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 a dummy semicolon to create a mixin call with one argument containing a comma-separated css list: `.name(1, 2, 3;)`. _Note: if the trailing semi-colon seems strange, you may prefer: `.name(~(1, 2, 3))`_
* Ways to write a comma separated default value:
- `@param-values: red, blue; .name(@param1: @param-values)`.
- `.name(@param1: red, blue;)`
- `.name(@param1: ~(red, blue))`

#### Overloading mixins

Expand Down
2 changes: 1 addition & 1 deletion content/features/mixins.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ Use the `!important` keyword after mixin call to mark all properties inherited b
Example:

```less
.foo (@bg: #f5f5f5; @color: #900) {
.foo (@bg: #f5f5f5, @color: #900) {
background: @bg;
color: @color;
}
Expand Down
171 changes: 165 additions & 6 deletions content/features/scope.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,171 @@
---
published: false
---

> How variables are evaluated
> Some additional scoping features of Less
## Mixin scope features

Intuitively, mixins have access to definition scope.

```less
#ns {
@a: one;
.mixin-1() {
prop: @a;
}
}
.rule {
#ns.mixin-1();
}

/* OUTPUTS:
.rule {
prop: one;
}
*/
```
### Deprecated mixin scope features

This is a list of mixin scope features that may be removed in future releases.

#### #1. (DEPRECATED) Mixins have access to caller scope.

```less
#ns {
.mixin-1() {
prop: @a;
}
}
.rule {
@a: one;
#ns.mixin-1();
}
/* OUTPUTS:
.rule {
prop: one;
}
*/
```
This is counter-intuitive because:
1. It is not typical in most other languages.
2. It's not immediately obvious when looking at the definition what output will be produced by the mixin.

**Preferred approach**: Pass in the variable you want to be visible to the mixin.
```less
#ns {
.mixin-1(@a) {
prop: @a;
}
}
.rule {
#ns.mixin-1(@a: one);
}
```
#### #2. (DEPRECATED) The caller scope has access to variables from the mixin

Mixins will push their variables into the caller scope, but _only_ if the variable is not locally defined.

```less
#ns {
.mixin-1() {
@a: one;
@b: two;
}
}
.rule {
@b: three;
#ns.mixin-1();
prop-1: @a;
prop-2: @b;
}
/* OUTPUTS:
.rule {
prop-1: one;
prop-2: three;
}
*/
```
This is counter-intuitive because:
1. A variable higher in the caller scope can be overridden.
2. It's also not a typical language behavior.
3. It differs from the behavior of detached rulesets.

Also, with the introduction of Maps, you can retrieve variable values (and mixins) directly.

**Preferred approach**:
```less
#ns {
.mixin-1() {
@a: one;
@b: two;
}
}
.rule {
@returns: #ns.mixin-1();
prop-1: @returns[@a];
prop-2: @returns[@b];
}
/* OUTPUTS:
.rule {
prop-1: one;
prop-2: two;
}
*/
```
#### #3. (DEPRECATED) The caller scope has access to mixins from the mixin

Similarly to deprecated variable behavior, mixins are also pushed into the caller scope. However, unlike variables, mixins with the same name as the merged scope mixin are merged.

```less
#ns {
.mixin-1() {
prop-1: one;
prop-2: two;
}
}
.rule {
#ns();
.mixin-1();
.mixin-1() {
prop-3: three;
}
}
/* OUTPUT:
.rule {
prop-1: one;
prop-2: two;
prop-3: three;
}
*/
```

**Preferred approach**: Call mixins directly.

```less
#ns {
.mixin-1() {
prop-1: one;
prop-2: two;
}
}
.rule {
.mixin-1() {
prop-3: three;
}
#ns.mixin-1();
.mixin-1();
}
/* OUTPUT:
.rule {
prop-1: one;
prop-2: two;
prop-3: three;
}
*/
```


## Tips & Tricks

Credit: [less/less.js/issues/1472]({{ site.coderepo }}/issues/1472#issuecomment-22213697)
Credit: [less/less.js/issues/1472](http://github.com/less/less.js/issues/1472#issuecomment-22213697)

Here is a trick for defining variables and keeping them in some private scope, preventing them from leaking to the global space.

Expand All @@ -19,7 +178,7 @@ Here is a trick for defining variables and keeping them in some private scope, p

.test {
height: @height;
width: @width;
width: @width;
}
}

Expand Down
29 changes: 17 additions & 12 deletions data/features.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,16 @@ published:
title: Parent Selectors
files: <%= features.base %>/parent-selectors.md

import-atrules:
title: "@import At-Rules"
files: <%= features.base %>/imports.md

extend:
title: Extend
files: <%= features.base %>/extend.md

merge:
title: Merge
title: Merge properties
files: <%= features.base %>/merge.md

mixins:
Expand All @@ -55,26 +59,27 @@ published:
mixin-aliasing:
title: Aliasing Mixins
files: <%= features.base %>/mixins-aliasing.md

css-guards:
title: CSS Guards
files: <%= features.base %>/css-guards.md


detached-rulesets:
title: Detached Rulesets
files: <%= features.base %>/detached-rulesets.md

import-atrules:
title: "@import At-Rules"
files: <%= features.base %>/imports.md
maps:
title: "Maps"
files: <%= features.base %>/maps.md

scope:
title: Scope
files: <%= features.base %>/scope.md

css-guards:
title: CSS Guards
files: <%= features.base %>/css-guards.md

plugin-atrules:
title: "@plugin At-Rules"
files: <%= features.base %>/plugins.md

maps:
title: "Maps <small>(NEW!)</small>"
files: <%= features.base %>/maps.md


# =============================================
Expand Down
Loading

0 comments on commit a83d035

Please sign in to comment.