Skip to content

Commit a1c3b26

Browse files
committed
Merge pull request #201 from SomMeri/detached-rulesets-1
Updated detached rulesets and mixins as functions
2 parents 651ddd0 + b32a33b commit a1c3b26

File tree

2 files changed

+213
-3
lines changed

2 files changed

+213
-3
lines changed

content/features/detached-rulesets.md

+164-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,29 @@
22
33
Released [v1.7.0]({{ less.master }}CHANGELOG.md)
44

5-
You may want to define a mixin that will abstract out either wrapping a piece of code in a media query or a non supported browser class name. You can now pass rulesets to mixins so that the mixin can wrap the content. E.g.
5+
Detached ruleset is a group of css properties, nested rulestes, media declarations or anything else stored in a variable. You can include it into a ruleset or another structure and all its properties are going to be copied there. You can also use it as a mixin argument and pass it around as any other variable.
6+
7+
Simple example:
8+
````less
9+
// declare detached ruleset
10+
@detached-ruleset: { background: red; };
11+
12+
// use detached ruleset
13+
.top {
14+
@detached-ruleset();
15+
}
16+
````
17+
18+
compiles into:
19+
````css
20+
.top {
21+
background: red;
22+
}
23+
````
24+
25+
Parentheses after detached ruleset call are mandatory. The `@detached-ruleset;` call would NOT work.
26+
27+
It is usefull when you want to define a mixin that abstracts out either wrapping a piece of code in a media query or a non supported browser class name. The rulesets can be passed to mixin so that the mixin can wrap the content. E.g.
628

729
```less
830
.desktop-and-old-ie(@rules) {
@@ -69,3 +91,144 @@ which will output
6991
}
7092
}
7193
```
94+
95+
Detached ruleset call unlocks (returns) all its mixins into caller the same way as mixin calls do. However, it does NOT return variables.
96+
97+
Returned mixin:
98+
````less
99+
// detached ruleset with a mixin
100+
@detached-ruleset: {
101+
.mixin() {
102+
color:blue;
103+
}
104+
};
105+
// call detached ruleset
106+
.caller {
107+
@detached-ruleset();
108+
.mixin();
109+
}
110+
````
111+
112+
Results in:
113+
````css
114+
.caller {
115+
color: blue;
116+
}
117+
````
118+
119+
Private variables:
120+
````less
121+
detached-ruleset: {
122+
@color:blue; //this variable is private
123+
};
124+
.caller {
125+
color: @color; //syntax error
126+
}
127+
````
128+
129+
## Scoping
130+
Detached ruleset can use all variables and mixins accessible on place where it is *defined* and where it is *called*. Otherwise said, both definition and caller scopes are available to it. If both scopes contains the same variable or mixin, declaration scope value takes precedence.
131+
132+
*Declaration scope* is the one where detached ruleset body is defined. Copying detached ruleset from one variable into another can not modify its scope. Ruleset does not gain access to new scopes just by being referenced there.
133+
134+
Lastly, detached ruleset can gain access to scope by being unlocked (imported) into it.
135+
136+
#### Definition and Caller Scope Visibility
137+
Detached mixin sees callers variables and mixins:
138+
````less
139+
@detached-ruleset: {
140+
caller-variable: @callerVariable; // variable is undefined here
141+
.callerMixin(); // mixin is undefined here
142+
};
143+
144+
selector {
145+
// use detached ruleset
146+
@detached-ruleset();
147+
148+
// define variable and mixin needed inside the detached ruleset
149+
@callerVariable: value;
150+
.callerMixin() {
151+
variable: declaration;
152+
}
153+
}
154+
````
155+
156+
compiles into:
157+
````css
158+
selector {
159+
caller-variable: value;
160+
variable: declaration;
161+
}
162+
````
163+
164+
Variable and mixins accessible form definition win over those available in caller:
165+
````less
166+
@variable: global;
167+
@detached-ruleset: {
168+
//will use global variable, because it is accessible
169+
//from detached-ruleset definition
170+
variable: @variable;
171+
};
172+
173+
selector {
174+
@detached-ruleset();
175+
@variable: value; //variable defined in caller - will be ignored
176+
}
177+
````
178+
179+
compiles into:
180+
````css
181+
selector {
182+
variable: global;
183+
}
184+
````
185+
186+
#### Referencing WONT Modify Detached Ruleset Scope
187+
Ruleset does not gain access to new scopes just by being referenced there:
188+
````less
189+
@detached-1: { scope-detached: @one @two; };
190+
.one {
191+
@one: visible;
192+
.two {
193+
@detached-2: @detached-1; // copying/renaming ruleset
194+
@two: visible; // ruleset can not see this variable
195+
}
196+
}
197+
198+
.usePlace {
199+
.one > .two();
200+
@detached-2();
201+
}
202+
````
203+
204+
throws an error:
205+
````
206+
ERROR 1:32 The variable "@one" was not declared.
207+
````
208+
209+
#### Unlocking WILL Modify Detached Ruleset Scope
210+
Detached ruleset gains access by being unlocked (imported) inside a scope:
211+
````less
212+
#space {
213+
.importer1() {
214+
@detached: { scope-detached: @variable; }; // define detached ruleset
215+
}
216+
}
217+
218+
.importer2() {
219+
@variable: value; // unlocked detached ruleset CAN see this variable
220+
#space > .importer1(); // unlock/import detached ruleset
221+
}
222+
223+
.usePlace {
224+
.importer2(); // unlock/import detached ruleset second time
225+
@detached();
226+
}
227+
````
228+
229+
compiles into:
230+
````css
231+
.usePlace {
232+
scope-detached: value;
233+
}
234+
````

content/features/mixins-as-functions.md

+49-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
> Return variables from mixins
1+
> Return variables or mixins from mixins
22
3-
All variables defined in a mixin are visible and can be used in caller's scope (unless the caller scope already has a variable with same name defined, including previously defined by another mixin call).
3+
Variables and mixins defined in a mixin are visible and can be used in caller's scope. There is only one exception, 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.
44

55
Example:
66

@@ -48,3 +48,50 @@ div {
4848
padding: 33px;
4949
}
5050
```
51+
<<<<<<< HEAD
52+
=======
53+
54+
Variable defined directly in callers scope can not be overriden. However, variable defined in callers parent scope is not protected and will be overriden:
55+
````less
56+
.mixin() {
57+
@size: in-mixin;
58+
@definedOnlyInMixin: in-mixin;
59+
}
60+
61+
.class {
62+
margin: @size @definedOnlyInMixin;
63+
.mixin();
64+
}
65+
66+
@size: globaly-defined-value; // callers parent scope - no protection
67+
````
68+
69+
Results in:
70+
````css
71+
.class {
72+
margin: in-mixin in-mixin;
73+
}
74+
````
75+
76+
Finally, mixin defined in mixin acts as return value too:
77+
````less
78+
.unlock(@value) { // outer mixin
79+
.doSomething() { // nested mixin
80+
declaration: @value;
81+
}
82+
}
83+
84+
#namespace {
85+
.unlock(5); // unlock doSomething mixin
86+
.doSomething(); //nested mixin was copied here and is usable
87+
}
88+
````
89+
90+
Results in:
91+
````css
92+
#namespace {
93+
declaration: 5;
94+
}
95+
````
96+
97+
>>>>>>> f945fa6948c69b5a84e402bc8eb8b2ead2735cfa

0 commit comments

Comments
 (0)