forked from leafo/lessphp
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdocs.html
More file actions
347 lines (273 loc) · 14.6 KB
/
docs.html
File metadata and controls
347 lines (273 loc) · 14.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" href="style.css" media="screen" />
<link rel="alternate" type="application/rss+xml" title="lessphp changelog feed" href="http://leafo.net/lessphp/feed/" />
<title>Documentation - lessphp</title>
</head>
<body>
<h1>Documentation - lessphp v0.2.0</h1>
<div class="content">
<ul id="nav">
<li><a href="#start">Getting Started</a></li>
<li><a href="#language">The Language</a>
<ul><li><a href="#vars">Abstract Properties (Variables)</a></li></ul>
<ul><li><a href="#pvalues">Property Values & Expressions</a></li></ul>
<ul><li><a href="#nested">Nested Blocks</a></li></ul>
<ul><li><a href="#mixins">Mixins & Namespace Access</a></li></ul>
<ul><li><a href="#ablocks">Abstract Blocks</a></li></ul>
<ul><li><a href="#args">Mixin Arguments</a></li></ul>
<ul><li><a href="#import">Import Statement</a></li></ul>
<ul><li><a href="#strings">String Mixins</a></li></ul>
<ul><li><a href="#misc">Miscellaneous</a></li></ul>
<ul><li><a href="#differences">Differences from Ruby LESS</a></li></ul>
</li>
<li><a href="#interface">The Interface</a></li>
</ul>
<p><strong>lessphp</strong> is a compiler that generates css from a small superset language that adds
many additional features seen in other languages. It is based off an original Ruby implementation
called <a href="http://lesscss.org/">LESS</a>. For the most part, <strong>lessphp</strong> is syntactically
compatible with LESS, with the exception of a few things noted below.</p>
<a name="start"></a>
<h2>Getting Started</h2>
<p>Download the latest version of <strong>lessphp</strong> <a href="http://leafo.net/lessphp/">here</a>.</p>
<p>You can also find the latest development version in the <a href="http://github.com/leafo/lessphp">git repository</a>.</p>
</div>
<a name="language"></a>
<h1>The Language</h1>
<div class="content">
<br />
<p><strong>lessphp</strong> is a data description language built on top of CSS. The two major components of the language are
blocks and property-value pairs. A block is a scope for a collection of property-value pairs.</p>
<p>Blocks and properties have special characteristics depending on how they are named.</p>
<p>It is important to realize that a block's state does not change over time. When a block is defined, all of its properties are constant. The best way to demonstrate this is to look at the following LESS snippet:</p>
<pre class="code">
body {
color: @val;
@val: blue;
}</pre>
<p>Because the state of the block is not changing over time, but constant after its creation,
the color property is printed with the value <code>blue</code>.
<a name="vars"></a>
<h2>Abstract Properties (Variables)</h2>
<p>Abstract properties are defined with a name starting with <code>@</code>. These types of properties are special in two ways: first, they are not included in the output of the compiler. Second, they can be easily accessed in the values of other properties just by writing their name. If a property is referenced but can not be found, a blank string is returned.</p>
<p>As a LESS programmer, it means that you can define a collection of hidden values that can be referenced in other locations.</p>
<pre class="code">
@mycolor: #fff;
body {
color: @mycolor;
}
pre {
color: @mycolor;
}</pre>
<p>Also take note that you can define abstract properties in the global scope.</p>
<a name="pvalues"></a>
<h2>Property Values & Expressions</h2>
<p>All properties have at least one value. The value is a list of expressions separated by spaces or commas.
An expression is any CSS value with optional mathematical operators applied to it. The operators only function
with number and color value types.<p>
<p>Operations on units will keep the unit of the rightmost value,
unless it is unit-less, then the leftmost unit will be kept for the result. See the following examples below.<p>
<pre class="code">body {
color: #001 + #abc; // evaulates to #aabbdd:
width: 3430px + 22; // evaluates to 3452px;
margin: (1.5em / 2) + 2px; // evaluates to 2.85px;
margin: 20 + 2px; // evaluates to 22px;
font-family: "Some " + "Family"; // evaluates to "Some Family"
}</pre>
<p>It is important to notice that in the example above the output will print the margin property twice.
A single property name can hold more than one value; older values are not overwritten.</p>
<a name="nested"></a>
<h2>Nested Blocks</h2>
<p>Blocks can be nested inside of each other in order to achieve the same effect as listing out the
path of identifiers in CSS. This can help to increase organization of your LESS code and reduce
the amount of repeated tag names you have to type.</p>
<pre class="code">body {
a {
color: green;
:hover {
color: blue;
}
}
}</pre>
<a name="mixins"></a>
<h2>Mixins & Namespace Access</h2>
<p>Any block can be "mixed" into the current block. This means that all properties and blocks
in the target block are brought into the current block. It is possible to achieve the same effect
with just CSS and HTML, but there are some additional features discussed below that make it worthwhile
to utilize LESS-style mixing.</p>
<p>The syntax is as follows:<p>
<pre class="code">
.myclass {
@fonts: Helvetica, Arial;
margin: 1.0em;
line-spacing: 150%;
a {
background-color: black;
}
}
pre {
.myclass;
font-family: @fonts; // uses the mixed in variable
}
div.notice {
.myclass;
}</pre>
<p>If you want to mix in a specific block within another block you can use the <code>></code> namespace operator.
Additionally you can pull out specific values of properties from blocks using the <code>[ ]</code> operator.
<pre class="code">// using .myclass from above
li {
.myclass > a; // just mix in properties from 'a' tag in .myclass
fonts: .myclass[@fonts];
padding: .myclass['margin'];
}</pre>
<a name="ablocks"></a>
<h2>Abstract Blocks</h2>
<p>Abstract blocks are like any other blocks, but their names start with a <code>@</code>. Like abstract properties, they are not
included in the compiler's output. This allows you to utilize mixins without adding any unused blocks to the output.
You can also use an abstract class to define a package of invisible, but extractable blocks and properties.<p>
<pre class="code">@mypackage {
.coolColors {
color: pink;
background-color: green;
}
.hotColors {
color: red;
background-color: orange;
}
}
p {
@mypackage > .coolColors;
}
div {
@mypackage; // inserts both classes into this block
}</pre>
<p>It is possible to give an abstract block the same name as an abstract property; their names will not collide.
Block names and property names exist in different spaces. For example:</p>
<pre class="code">@color(@color:red) { color: @color; } // this is valid
</pre>
<a name="args"></a>
<h2>Mixin Arguments</h2>
<p>All blocks have the option of taking argument lists, and the arguments can have default values.</p>
<pre class="code">@some_mixin(@width: 200px;@radius) {
border-radius: @radius;
width: @width
}
.first {
@some_mixin(300px; 2em);
}
.second {
@some_mixin(;4px); // blank argument takes default value
}</pre>
<a name="import"></a>
<h2>Import Statement</h2>
<p>If you have multiple LESS files, you can combine them into a single CSS file during compilation using the
<code>@import</code> directive. LESS import uses the same syntax as CSS import. If it can find the file specified
then it will pull it into the compiler in place of the statement. If the file can't be found, the statement is
printed to the output. The following are all valid:</p>
<pre class="code">@import "file";
@import 'file.less';
@import url("file");
@import url('file');
@import url(file); </pre>
<p>Note that if it fails to find a file it will append <code>.less</code> to the filename and try again.
This means <code>@import 'somefile'</code> and <code>@import 'somefile.less'</code> will
both import the file <code>somefile.less</code>.
<a name="strings"></a>
<h2>String Mixins</h2>
<p>It is possible to access the value of an abstract property from a string using <code>{ }</code> operators.</p>
<pre class="code">@image_folder: darktheme;
.header {
background-image: url(/images/{@image_folder}/header.png);
}</pre>
<p>The <code>{ }</code> syntax will also work in any string value type, which is any text
wrapped in single or double quotes</p>
<a name="misc"></a>
<h2>Miscellaneous</h2>
<p>As mentioned before, all properties hold constant data. This includes abstract values. While it may be convenient to
think of them as variables, they don't have the ability to vary. For convenience, some tricks were implemented to
make self referencing properties evaluate in order as if they had changing state. Consider the following statement:</p>
<pre class="code">
@what: 1;
body {
@what: @what + 1;
@what: @what + 2;
.class {
@what: @what + 1;
width: @what;
}
}
#something {
@what: 200;
body > .class;
}</pre>
<p>In the output, <code>body .class</code> has width set to 5, and <code>#something</code> has width set to 201. It appears from that result that
the property <code>@what</code> is being incremented. But, as mentioned above, the name <code>@what</code> stores a series of unchanging values.
The values use delayed evaluation, so each value holds an equation.</p>
<p>What this means is that the values of the properties don't change while the block is parsed, only additional property-value pairs are added
to the block's definition.
When the block's is compiled into CSS, the equations and property references are solved using the data in the scope. Technically, it is
ambiguous what value to use for referencing a variable, because the single name can store multiple values.<p>
<p>The approach taken in <strong>lessphp</strong> is to use the most recent value. This gives the appearance that the block is parsed line by line.
In order to prevent infinite loops when a variable references itself, a single value in the set of all values for a given name can only be used once in
the chain of dereferencing.</p>
<a name="differences"></a>
<h2>Differences from Ruby LESS</h2>
<p class="important">Report missing ones <a href="http://github.com/leafo/lessphp/issues">here</a>.</p>
<ul>
<li>Arguments to mixins are separated by <code>;</code> instead of <code>,</code>.
<p><b>Rationale</b>: the value of a css property can contain commas, so by using a comma as an argument separator you limit the kinds of input you can pass to a mixin.</p>
</li>
</ul>
</div>
<a name="interface"></a>
<h1>The PHP Interface</h1><br />
<div class="content">
<p>There are a few ways to interface with the compiler. The easiest is to have it
compile a LESS file when the page is requested. The static function
<code>less::ccompile</code>, checked compile, will compile the inputed LESS file only when it
is newer than the output file.<p>
<pre class="code">
<span class="PreProc">require</span> '<span class="String">lessc.inc.php</span>';
<span class="Statement">try</span> <span class="Delimiter">{</span>
lessc<span class="Operator">::</span>ccompile<span class="Delimiter">(</span>'<span class="String">input.less</span>', '<span class="String">out.css</span>'<span class="Delimiter">)</span>;
<span class="Delimiter">}</span> <span class="Statement">catch</span> <span class="Delimiter">(</span><span class="Function">exception</span> <span class="Operator">$</span><span class="Identifier">ex</span><span class="Delimiter">)</span> <span class="Delimiter">{</span>
<span class="Statement">exit</span><span class="Delimiter">(</span>'<span class="String">lessc fatal error:<br /></span>'<span class="Operator">.</span><span class="Operator">$</span><span class="Identifier">ex</span><span class="Type">-></span>getMessage<span class="Delimiter">())</span>;
<span class="Delimiter">}</span>
</pre>
<br />
<p>Note that all failures with lessc are reported through exceptions.
If you need more control then you can make your own instance of <code>lessc</code>.</p>
<pre class="code">
<span class="PreProc">require</span> '<span class="String">lessc.inc.php</span>';
<span class="Operator">$</span><span class="Identifier">less</span> <span class="Operator">=</span> <span class="PreProc">new</span> lessc<span class="Delimiter">(</span>'<span class="String">path/to/style.less</span>'<span class="Delimiter">)</span>;
<span class="Function">file_put_contents</span><span class="Delimiter">(</span>'<span class="String">path/to/style.css</span>', <span class="Operator">$</span><span class="Identifier">less</span><span class="Type">-></span>parse<span class="Delimiter">())</span>;
</pre>
<br />
<p>In addition to loading from a file, you can also parse from a string like so:</p>
<pre class="code">
<span class="PreProc">require</span> '<span class="String">lessc.inc.php</span>';
<span class="Operator">$</span><span class="Identifier">less</span> <span class="Operator">=</span> <span class="PreProc">new</span> lessc<span class="Delimiter">()</span>;
<span class="Operator">$</span><span class="Identifier">style</span> <span class="Operator">=</span> '<span class="String"><style type="text/css"></span>'<span class="Operator">.</span>
<span class="Operator">$</span><span class="Identifier">less</span><span class="Type">-></span>parse<span class="Delimiter">(</span>'<span class="String">.block { padding: 3 + 4px }</span>'<span class="Delimiter">)</span><span class="Operator">.</span>
'<span class="String"></style></span>';
</pre>
<h2>Import Directoy</h2>
<p>When using the <code>@import</code> directive, the compiler searches for files
in the <code>$importDir</code> public property of <code>lessc</code>. If the compiler is loaded with a filename
(either in the constructor or using <code>ccompile</code>) it will extract the directory and set that as the
import directory</p>
<h2>Library Functions</h2>
<p>Functions within the compiler class that are prefixed with <code>lib_</code> are visible visible to the less
code while it is being parsed. The easiest way to add your own functions is to subclass <code>lessc</code> and insert
the implementations.</p>
<br />
<br />
<hr />
<p class="foot">
<a href="http://leafo.net/lessphp/">http://leafo.net/lessphp</a> - Last updated March 9th 2010</p>
</div>
</body>
</html>