/docs/docs.html
HTML | 347 lines | 273 code | 74 blank | 0 comment | 0 complexity | 366d447dbb21fc4ea7c4c0f8c93f6b27 MD5 | raw file
- <!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>