Sass and Compass Designer's Cookbook
上QQ阅读APP看书,第一时间看更新

Creating pure Sass functions

Since Sass version 3.3.1., you can not only use the @mixin directive, but also the @function directive. Pure Sass functions created with the @function directive do not generate output in the compiled CSS code, but return a single value. In this recipe, you will create a Sass function that converts value in px (pixel) units to values in em units.

Getting ready

Read the Installing Sass for command line usage recipe of Chapter 1, Getting Started with Sass, and install Ruby Sass on your system. In the Using Sass interactive mode and SassScript recipe of Chapter 1, Getting Started with Sass, you can read how to use the interactive Sass mode. Operations with units, as used in this recipe, can easily be tested in the interactive Sass mode.

How to do it...

Perform the steps below to build a pure Sass function yourself:

  1. Create a Sass template that contains an em function, which looks as follows:
     $browser-context: 16; 
    
    @function px_to_em($pixels, $context: $browser-context) { 
      @return ($pixels / $context) * 1em; 
    } 
  2. Now you can compile the SCSS like that shown here:
    h1 { 
    font-size: px_to_em(20); 
    }
  3. The SCSS code from the previous step should compile into CSS code like that shown here:
    h1 { 
      font-size: 1.25em; } 

How it works...

As already mentioned, Sass functions created with @function directive return a single value based on their input parameters. You must call the @return directive to set the return value of the function. You can use the @function directive instead of the @mixin directive if you have to assign the same kind of value to different properties. The @function directive will help you make your code more DRY. You can replace mixins, which set the same kind of value for different properties with a single @function directive to get the same output.

Functions can access any globally defined variables as well as accept arguments just like mixins. Also, keyword and variable arguments are supported for functions. Read more about using mixins with arguments in the Writing mixins with arguments recipe of this chapter.

You can calculate the em equivalent for any pixel value using this formula:

em = desired pixel value / font-size of the parent element in pixels

In this recipe, the px_to_em function has been used to calculate the corresponding em value of a pixel value. An em value is equal to the size of the font that applies to the parent of the element in question. Using em values for your designs will make your applications easier to scale and resize.

There's more...

In the Applying operations in Sass recipe of this chapter, the standard arithmetic operations (adding, subtracting, multiplying, dividing, and modulo) for the data types supported by SassScript, including the data types supported by vanilla CSS already, are discussed. When applying operations in Sass, the rules for units are the same as used for normal mathematical operations.

In the normal mathematical/physical context, you cannot add or subtract numbers with different units; 1 kilometer + 2 hours makes no sense. The same will be true for SassScript values when compiling 1px + 1em results in an Incompatible units SyntaxError.

For the same reason, the unit will get lost when dividing two values with the same unit. Multiplying a unitless value with 1 x unit will result in a value with the unit used for multiplying. In this recipe, the preceding had been used to get a value in em units. First divide two unitless values and then multiply the result with 1 x 1em.

You can easily test the outcome of an operation by using the interactive mode of Sass, as described in the Using Sass interactive mode and SassScript recipe of Chapter 1, Getting Started with Sass.

When using the @if directive, as describe in the Using the @if directive recipe of Chapter 8, Advanced Sass Coding, you can also change your function so that it always uses two pixel values, even when you call it with some unitless values. A more robust function for the pixels to em conversion will look like that shown here:

@function px_to_em($pixels, $context: $browser-context) {
  
  @if (unitless($pixels)) {
    $pixels: $pixels * 1px;
  }

  @if (unitless($context)) {
    $context: $context * 1px;
  }
  
  @return ($pixels / $context) * 1em;
}

Besides the @if directive, the built-in unitless function is also used in the preceding SCSS code. You can read more about the built-in function in Chapter 5, Built-in Functions.

Instead of using math, you can also use string interpolation to get the correct em values. You can read more about string interpolation in the Interpolation of variables recipe of this chapter. The following Sass code compiles in the same CSS code as you have seen in the recipe before:

$browser-context: 16;
@function px_to_em($pixels, $context: $browser-context) {
  @return #{$pixels/$context}em;
}

In the preceding code, #{$ pixels/$context}em compiles into a single string value.

See also