PageRenderTime 47ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/docs/docs.md

https://github.com/conzi/lessphp
Markdown | 502 lines | 359 code | 143 blank | 0 comment | 0 complexity | 28f013a6cb43edffe1262bc146b8e6de MD5 | raw file
  1. # Documentation - lessphp v0.3.0
  2. * Getting Started
  3. * The Language
  4. * Line Comments
  5. * Variables
  6. * Expressions
  7. * String Interpolation
  8. * Nested Blocks
  9. * Mixins
  10. * Import
  11. * Built In Functions
  12. * PHP Interface
  13. * Setting Variables From PHP
  14. * Custom Functions
  15. * Command Line Interface
  16. **lessphp** is a compiler that generates CSS from a superset language which
  17. adds a collection of convenient features often seen in other languages. All CSS
  18. is compatible with LESS, so to get started you don't need to rewrite your CSS.
  19. It is based off the original and defunct Ruby implementation
  20. in addition to the current JavaScript one, [less.js](http://lesscss.org).
  21. <a name="start"></a>
  22. ## Getting Started
  23. The homepage for **lessphp** can be found at
  24. [http://leafo.net/lessphp/](http://leafo.net/lessphp).
  25. You can follow development at the project's
  26. [github](https://github.com/leafo/lessphp).
  27. Including **lessphp** in your project is as simple as dropping the single
  28. include file into your code base and running the appropriate compile method as
  29. described in the [PHP Interface](#php-interface).
  30. <a name="language"></a>
  31. ## The Language
  32. **lessphp** is very easy to learn because it generally functions how you would
  33. expect it to. If you feel something is challenging or missing, feel free to
  34. open an issue on the [bug tracker](https://github.com/leafo/lessphp/issues).
  35. The following is an overview of the features provided.
  36. <a name="comments"></a>
  37. ### Line Comments
  38. Simple but very useful; line comments are started with `//`:
  39. // this is a comment
  40. body {
  41. color: red; // as is this
  42. /* block comments still work also */
  43. }
  44. <a name="vars"></a>
  45. ### Variables
  46. Variables are identified with a name that starts with `@`. To declare a
  47. variable, you create an appropriately named CSS property and assign it a value:
  48. @family: "verdana";
  49. body {
  50. @mycolor: red;
  51. font-family: @family;
  52. color: @color;
  53. border-bottom: 1px solid @color;
  54. }
  55. Variable declarations will not appear in the output. Variables can be declared
  56. in the outer most scope of the file, or anywhere else a CSS property may
  57. appear. They can hold any CSS property value.
  58. Variables are only visible for use from their current scope, or any enclosed
  59. scopes.
  60. <a name="pvalues"></a>
  61. <a name="exps"></a>
  62. ### Expressions
  63. Expressions let you combine values and variables in meaningful ways. For
  64. example you can add to a color to make it a different shade. Or divide up the
  65. width of your layout logically. You can even concatenate strings.
  66. Use the mathematical operators to evalute an expression:
  67. @width: 960px;
  68. .nav {
  69. width: @width / 3;
  70. color: #001 + #abc; // evaluates to #aabdd
  71. }
  72. .body {
  73. width: 2 * @width / 3;
  74. font-family: "hel" + "vetica"; // evaluates to "helloworld"
  75. }
  76. Parentheses can be used to control the order of evaluation. They can also be
  77. used to force an evaluation for cases where CSS's syntax makes the expression
  78. ambiguous.
  79. The following property will produce two numbers, instead of doing the
  80. subtraction:
  81. margin: 10px -5px;
  82. To force the subtraction:
  83. margin: (10px -5px); // produces 5px
  84. It is also safe to surround mathematical operators by spaces to ensure that
  85. they are evaluated:
  86. margin: 10px - 5px;
  87. Division has a special quirk. Due to CSS font shorthand syntax, we need to be
  88. careful about how we place spaces. In the following example we are using font
  89. size and lineheight shorthand. No division should take place:
  90. .font {
  91. font: 20px/80px "Times New Roman";
  92. }
  93. In order to force division we can surround the `/` by spaces, or we can wrap
  94. the expression in parentheses:
  95. .font {
  96. // these two will evaluate
  97. font: 20px / 80px "Times New Roman";
  98. font: (20px/80px) "Times New Roman";
  99. }
  100. <a name="strings"></a>
  101. ### String Interpolation
  102. String interpolation lets us insert variables into strings using `{` and `}`.
  103. There are two kinds of strings, implicit and explicit strings. Explicit strings
  104. are wrapped by double quotes, `"hello I am a string"`, or single quotes `'I am
  105. another string'`. Implicit strings only appear when using `url()`. The text
  106. between the parentheses is considered a string and thus string interpolation is
  107. possible:
  108. @path: "files/";
  109. body {
  110. background: url({@path}my_background.png);
  111. }
  112. @symbol: ">";
  113. h1:before {
  114. content: "{@symbol}: ";
  115. }
  116. h2:before {
  117. content: "{@symbol}{@symbol}: ";
  118. }
  119. <a name="nested"></a>
  120. <a name="ablocks"></a>
  121. ### Nested Blocks
  122. By nesting blocks we can build up a chain of CSS selectors through scope
  123. instead of repeating them. In addition to reducing repetition, this also helps
  124. logically organize the structure of our CSS.
  125. ol.list {
  126. li.special {
  127. border: 1px solid red;
  128. }
  129. li.plain {
  130. font-weight: bold;
  131. }
  132. }
  133. This will produce two blocks, a `ol.list li.special` and `ol.list li.plain`.
  134. Blocks can be nested as deep as required in order to build a hierarchy of
  135. relationships.
  136. Pseudo classes are automatically joined without spaces:
  137. .navigation a {
  138. :link { color: green; }
  139. :visited { color: red; }
  140. :hover { text-decoration: none; }
  141. }
  142. This creates blocks `.navigation a:link`, `.navigation a:visited`, `.navigation
  143. a:hover`.
  144. We can control how the child blocks are joined:
  145. div {
  146. .child-class {
  147. color: purple;
  148. }
  149. &.isa-class {
  150. color: green;
  151. }
  152. // it also works with id identifiers
  153. #child-id {
  154. height: 200px;
  155. }
  156. &#div-id {
  157. height: 400px;
  158. }
  159. }
  160. The `&` prefix operator can be used to join the two selectors together without
  161. a space. This snippet would create blocks `div .child-class` and
  162. `div.isa-class` in addition to `div #child-id` and `div#div-id`.
  163. <a name="mixins"></a>
  164. <a name="args"></a>
  165. ### Mixins
  166. Any block can be mixed in just by naming it:
  167. .mymixin {
  168. color: blue;
  169. border: 1px solid red;
  170. .special {
  171. font-weight: bold;
  172. }
  173. }
  174. h1 {
  175. font-size: 200px;
  176. .mixin;
  177. }
  178. All properties and child blocks are mixed in.
  179. Mixins can be made parametric, meaning they can take arguments, in order to
  180. enhance their utility. A parametric mixin all by itself is not outputted when
  181. compiled. It's properties will only appear when mixed into another block.
  182. The canonical example is to create a rounded corners mixin that works across
  183. browsers:
  184. .rounded-corners (@radius: 5px) {
  185. border-radius: @radius;
  186. -webkit-border-radius: @radius;
  187. -moz-border-radius: @radius;
  188. }
  189. .header {
  190. .rounded-corners();
  191. }
  192. .info {
  193. background: red;
  194. .rounded-corners(14px);
  195. }
  196. Take note of the default argument, which makes specifying that argument optional.
  197. Because CSS values can contain `,`, the argument delimiter is a `;`.
  198. .box-shadow(@props) {
  199. box-shadow: @props;
  200. -webkit-box-shadow: @props;
  201. -moz-box-shadow: @props;
  202. }
  203. .size(@width; @height; @padding: 8px) {
  204. width: @width - 2 * @padding;
  205. height: @height - 2 * @padding;
  206. padding: @padding;
  207. }
  208. .box {
  209. .box-shadow(5px 5px 8px red, -4px -4px 8px blue); // all one argument
  210. .size(400px;200px) // multiple argument:
  211. }
  212. If you have a mixin that doesn't have any arguments, but you don't want it to
  213. show up in the output, give it a blank argument list:
  214. .secret() {
  215. font-size: 6000px;
  216. }
  217. .div {
  218. .secret;
  219. }
  220. If the mixin doesn't need any arguments, you can leave off the parentheses when
  221. mixing it in, as seen above.
  222. <a name="import"></a>
  223. ### Import
  224. Multiple LESS files can be compiled into a single CSS file by using the
  225. `@import` statement. Be careful, the LESS import statement shares syntax with
  226. the CSS import statement. If the file being imported ends in a `.less`
  227. extension, or no extension, then it is treated as a LESS import. Otherwise it
  228. is left alone and outputted directly:
  229. // my_file.less
  230. .some-mixin(@height) {
  231. height: @height;
  232. }
  233. // main.less
  234. @import "main.less" // will import the file if it can be found
  235. @import "main.css" // will be left alone
  236. body {
  237. .some-mixin(400px);
  238. }
  239. All of the following lines are valid ways to import the same file:
  240. @import "file";
  241. @import 'file.less';
  242. @import url("file");
  243. @import url('file');
  244. @import url(file);
  245. When importing, the `importDir` is searched for files. This can be configured,
  246. see [PHP Interface](#php-interface).
  247. <a name="bifs"></a>
  248. ### Built In Functions
  249. **lessphp** has a collection of built in functions:
  250. * `e(str)` -- an alias for unquote
  251. * `unquote(str)` -- returns a string without the surrounding quotes.
  252. This is useful for outputting something that wouldn't normally be able to be
  253. parsed. Some IE specific filters are notorious for causing trouble.
  254. .something {
  255. @size: 10px;
  256. border: unquote("{@size} solid red");
  257. }
  258. * `floor(number)` -- returns the floor of a numerical input
  259. * `round(number)` -- returns the rounded value of numerical input
  260. * `lighten(color, percent)` -- lightens color by percent and returns it
  261. * `darken(color, percent)` -- darkens color by percent and returns it
  262. * `saturate(color, percent)` -- saturates color by percent and returns it
  263. * `desaturate(color, percent)` -- desaturates color by percent and returns it
  264. * `fadein(color, percent)` -- makes color less transparent by percent and returns it
  265. * `fadeout(color, percent)` -- makes color more transparent by percent and returns it
  266. * `spin(color, amount)` -- returns a color with amount degrees added to hue
  267. * `rgbahex(color)` -- returns a string containing 4 part hex color.
  268. This is used to convert a CSS color into the hex format that IE's filter
  269. method expects when working with an alpha component.
  270. .class {
  271. @start: rgbahex(rgba(25, 34, 23, .5));
  272. @end: rgbahex(rgba(85, 74, 103, .6));
  273. -ms-filter: unquote("progid:DXImageTransform.Microsoft.gradient(startColorStr={@start},EndColorStr={@end})");
  274. }
  275. * `quote(str)` -- returns a string that contains all the arguments concatenated.
  276. <a name="php"></a>
  277. ## PHP Interface
  278. The PHP interface lets you control the compiler from your PHP scripts. There is
  279. only one file to include to get access to everything:
  280. include "lessc.inc.php";
  281. To compile a file to a string (of CSS code):
  282. $less = new lessc("myfile.less");
  283. $css = $less->parse();
  284. To compile a string to a string:
  285. $less = new lessc(); // a blank lessc
  286. $css = $less->parse("body { a { color: red } }");
  287. Often, you want to write the compiled CSS to a file, and only recompile when
  288. the original LESS file has changed. The following function will check the
  289. modification date of the LESS file to see if a compile is required:
  290. lessc::ccompile('myfile.less', 'mystyle.css');
  291. All of the following methods will throw an `Exception` if the parsing fails:
  292. $less = new lessc();
  293. try {
  294. $less->parse("} invalid LESS }}}");
  295. } catch (Exception $ex) {
  296. echo "lessphp fatal error: ".$ex->getMessage();
  297. }
  298. <a name="php-vars"></a>
  299. ### Setting Variables From PHP
  300. The `parse` function takes a second optional argument. If you want to
  301. initialize variables from outside the LESS file then you can pass in an
  302. associative array of names and values. The values will parsed as CSS values:
  303. $less = new lessc();
  304. echo $less->parse(".magic { color: @color; width: @base - 200; }",
  305. array(
  306. 'color' => 'red';
  307. 'base' => '960px';
  308. ));
  309. You can also do this when loading from a file, but remember to set the first
  310. argument of the parse function to `null`, otherwise it will try to compile that
  311. instead of the file:
  312. $less = new lessc("myfile.less");
  313. echo $less->parse(null, array('color' => 'blue'));
  314. <a name="php-funcs"></a>
  315. ### Custom Functions
  316. **lessphp** has a simple extension interface where you can implement user
  317. functions that will be exposed in LESS code during the compile. They can be a
  318. little tricky though because you need to work with the **lessphp** type system.
  319. By sub-classing `lessc`, and creating specially named methods we can extend
  320. **lessphp**. In order for a function to be visible in LESS, it's name must
  321. start with `lib_`.
  322. Let's make a function that doubles any numeric argument.
  323. include "lessc.inc.php";
  324. class myless extends lessc {
  325. function lib_double($arg) {
  326. list($type, $value) = $arg;
  327. return array($type, $value*2);
  328. }
  329. }
  330. $myless = new myless();
  331. echo $myless->parse("div { width: double(400px); }");
  332. Although a little verbose, the implementation of `lib_double` gives us some
  333. insight on the type system. All values are stored in an array where the 0th
  334. element is a string representing the type, and the other elements make up the
  335. associated data for that value.
  336. The best way to get an understanding of the system is to make a dummy `lib_`
  337. function which does a `vardump` on the argument. Try passing the function
  338. different values from LESS and see what the results are.
  339. The return value of the `lib_` function must also be a LESS type, but if it is
  340. a string or numeric value, it will automatically be coerced into an appropriate
  341. typed value. In our example, we reconstruct the value with our modifications
  342. while making sure that we preserve the type.
  343. All of the built in functions are implemented in this manner within the `lessc`
  344. class.
  345. <a name="cli"></a>
  346. ## Command Line Interface
  347. **lessphp** comes with a command line script written in PHP that can be used to
  348. invoke the compiler from the terminal. On Linux an OSX, all you need to do is
  349. place `plessc` and `lessc.inc.php` somewhere in your PATH (or you can run it in
  350. the current directory as well). On windows you'll need a copy of `php.exe` to
  351. run the file. To compile a file, `input.less` to CSS, run:
  352. $ plessc input.les
  353. To write to a file, redirect standard out:
  354. $ plessc input.les > output.css
  355. To compile code directly on the command line:
  356. $ plessc -r "@color: red; body { color: @color; }"
  357. To watch a file for changes, and compile it as needed, use the `-w` flag:
  358. $ plessc -w input-file output-file
  359. Errors from watch mode are written to standard out.