Tag: lessphp

Custom Functions With LESSPHP: Cheat sheet

My favorite feature of the fantastic lessphp library is the ability to easily add in your own custom functions. This makes working with LESS truly flexible as you can add a bunch of features that less doesn’t already have. Imagine having a css preprocessor that will do anything at your whim, well with lessphp you do. I’ve built some custom color scheme functions, a gradient image generator, a rem to px converter and more. The possibilities are endless.

The documentation¬†on custom functions is fairly brief (make sure to read it!) so I started writing down a cheat sheet for reference purposes. For starters, it’s important to know how LESSPHP passes arguments to functions. You need to know what format the data will be in so you can process it inside your function.

Data Structure

The data structure your php function gets to work with depends on whether your custom less function received one argument or multiple arguments. If it’s a single argument, you’ll get an array like this:

/*
css example:
.test {
     padding: my_custom_function( 10px );
}
this array is sent on to your custom function
*/
array(3) {
  [0]=>
  string(6) "number"
  [1]=>
  string(2) "10"
  [2]=>
  string(2) "px"
}

This is pretty straightforward. The first value of the array contains the type of the value.

Arguments that are passed to your custom function are first processed and parsed by lessphp and then passed on as one of the following types:

  • keyword (a string that is a single word)
  • number (any numeric value, with or without a unit appended)
  • string
  • color

Each of these types also has its own data structure, which we will get to in a moment.

If you have multiple arguments, you’ll get a multidimensional array like the following:

/* .test{
    padding: my_custom_function( 20px, 62.5% );
}
the following is a vardump of what is passed on to the custom function
*/
array(3) {
  [0]=>
  string(4) "list"
  [1]=>
  string(1) ","
  [2]=>
  array(2) {
    [0]=>
    array(3) {
      [0]=>
      string(6) "number"
      [1]=>
      string(2) "10"
      [2]=>
      string(2) "px"
    }
    [1]=>
    array(3) {
      [0]=>
      string(6) "number"
      [1]=>
      string(4) "62.5"
      [2]=>
      string(1) "%"
    }
  }
}

Note that in case of multiple arguments the first value of the array is ‘list‘. You can use that value to check if your custom function should anticipate one or more arguments. If it’s a single argument the first value will be the value type, otherwise it will be equal to list. It’s important that you do a check like that if your function is designed to take a varying amount of arguments.

The second value in the array in case multiple arguments were passed is the delimiter used between the variables in the function call. When using custom functions it’s fine to separate arguments with spaces or with commas.

.test{
    color: my_color_function( @color1, @color2 );
    background-color: my_color_function( @color1 @color2 );
}

Data Structures Per Type

Color:

No matter what color notation (hex, color name, hsl(a) or rgb(a)) is used as an argument inside the less input, it will be parsed and sent on as an array in RGB format. If there is an alpha value, it will specify a fourth value containing the alpha value.

Keyword:

The keyword is the simplest value to deal with, as the array for this will contain ‘keyword’ as the first value in the array and the actual word as the second value in the array.

String:

Strings are returned with a nested array. The first value in the array contains the type ‘string’, the second value contains the delimiter (which could be double, single or no quotes for example) and the third value is an array containing the raw string.

Number:

For numeric values, the first value will as usual denote the type of the data (which will be number). The second value in the array will be the raw numeric value. The third value is the unit, which will be blank if the unit was passed without any unit.

Returning A Value

Your custom function has to send back a value and you have to follow the same data structure that the lessphp script likes to use.

To return a color, send back an array like this:

return array( 'color', $red, $green, $blue, $alpha );

You can also send a raw color value back, which basically means any kind of color notation you could enter in to css.

$rawcolor = 'hsla( 200, 10%, 60%, 0.4)';
return array( 'raw_color', $rawcolor );

To return a string, send it like this:

return array( 'string', $delimiter, array ( $string ) );

To return a keyword:

return array( 'keyword', $keyword );

To return a number:

return array( 'number', $number, $unit );

To call another less function:

$function = 'darken';
$arguments = array( '#FF330F', '10%' );
return array( 'function', $function, $arguments );

That covers the basics. As a final helper, here is what the array looks like when passing multiple arguments of various types. It should give you an easy reference to know how to deal with different types of arguments.

/*
in our less we are calling a custom function with tons of different variables to give you an idea of the array that gets passed to your custom function.
.test {
    my_custom_function( "Amatic SC", url(www.w3.org), 'http://html5.com', 800, regular, 100px, 40%, green, #FF44E3, rgba(30,40,254,0.1), hsl(100, 33%, 50%) );
}
And here's the vardump it produces:
*/
array(3) {
  [0]=>
  string(4) "list"
  [1]=>
  string(1) ","
  [2]=>
  array(11) {
    [0]=>
    array(3) {
      [0]=>
      string(6) "string"
      [1]=>
      string(1) """
      [2]=>
      array(1) {
        [0]=>
        string(9) "Amatic SC"
      }
    }
    [1]=>
    array(3) {
      [0]=>
      string(8) "function"
      [1]=>
      string(3) "url"
      [2]=>
      array(3) {
        [0]=>
        string(6) "string"
        [1]=>
        string(0) ""
        [2]=>
        array(1) {
          [0]=>
          string(10) "www.w3.org"
        }
      }
    }
    [2]=>
    array(3) {
      [0]=>
      string(6) "string"
      [1]=>
      string(1) "'"
      [2]=>
      array(1) {
        [0]=>
        string(16) "http://html5.com"
      }
    }
    [3]=>
    array(3) {
      [0]=>
      string(6) "number"
      [1]=>
      string(3) "800"
      [2]=>
      string(0) ""
    }
    [4]=>
    array(2) {
      [0]=>
      string(7) "keyword"
      [1]=>
      string(7) "regular"
    }
    [5]=>
    array(3) {
      [0]=>
      string(6) "number"
      [1]=>
      string(3) "100"
      [2]=>
      string(2) "px"
    }
    [6]=>
    array(3) {
      [0]=>
      string(6) "number"
      [1]=>
      string(2) "40"
      [2]=>
      string(1) "%"
    }
    [7]=>
    array(4) {
      [0]=>
      string(5) "color"
      [1]=>
      string(1) "0"
      [2]=>
      string(3) "128"
      [3]=>
      string(1) "0"
    }
    [8]=>
    array(4) {
      [0]=>
      string(5) "color"
      [1]=>
      float(255)
      [2]=>
      float(68)
      [3]=>
      float(227)
    }
    [9]=>
    array(5) {
      [0]=>
      string(5) "color"
      [1]=>
      float(30)
      [2]=>
      float(40)
      [3]=>
      float(254)
      [4]=>
      float(0.1)
    }
    [10]=>
    array(4) {
      [0]=>
      string(5) "color"
      [1]=>
      float(113.475)
      [2]=>
      float(169.575)
      [3]=>
      float(85.425)
    }
  }
}