Learning Less.js
上QQ阅读APP看书,第一时间看更新

Exploring the syntax used by Less

Enough theory about installing! Let's move on and take a look at the syntax that makes up Less. Over the next few chapters, we will explore each part of the library in depth; before doing so, we will start with a whistle-stop tour through some of the more important parts of the library, beginning with variables.

Working with variables

If we need to write CSS styles, it's likely that we will include one or more styles that appear in multiple places. A great example is a number of shapes, where we might need to use the same value for borders or foreground colors:

.shape1 {
  color: #5cb100;
  border: 1px solid #5cb100;
}

.shape2 {
  background: #fff;
  color: #5cb100;
}
.shape3 {
  border: 1px solid #5cb100;
}

We could, as web designers, simply use the same color values throughout our code, and where appropriate, this is a perfectly valid option. However, what happens if we've set up a specific set of colors, only to find they all need to be changed?

Each style can be changed individually, although this assumes we manage to change every instance—on a style-heavy site, and with the best will in the world, there will always be one that we miss!

We can solve this easily by using variables to store a constant value for each color, and use it throughout the style sheet:

@my-color: #5cb100;

.shape1 { color: @my-color; border: 1px solid @my-color; }
.shape2 { background: #fff; color: @my-color; }
.shape3 { border: 1px solid @my-color; }

This means that if we choose to change the original color for something else, then all we need to do is change the color value assigned to the relevant variable, and Less will automatically update each instance of the variable throughout the rest of the code.

In our example, we set up a variable to store the color value of #5cb100—if we wanted to change this, then we will only need to change the assigned variable at the start. Less will then handle the updating of every instance where the variable has been used, so we can be confident that the change has taken effect throughout our code.

We will explore more of variables in Chapter 4, Working with Variables, Mixins, and Functions.

Changing variables programmatically

Although we can set variables as static values, we might come across instances where it will be beneficial to programmatically change a value assigned to a Less variable, from within our code.

Hopefully, this is not something you will have to do too often, but it is useful to at least know how it works. Let's take a quick look at how this works, using an example form that has a couple of input fields and a simple Submit button.

In a new file, open a copy of the project.html file we created earlier, then alter the code as shown:

<link rel="stylesheet/less" href="css/object.less">
<script src="js/less.min.js"></script>
<script type="text/javascript">
  less.modifyVars({
    '@ button-color': '#61783F'
  });
</script>

Next, add the following code in between the <body> tags:

  <form action="demo_form.aspx">
    First name: <input type="text" name="fname"><br>
    Last name: <input type="text" name="lname"><br>
    <input type="submit" value="Submit" id="submitbtn">
  </form>

Finally, add the following Less styles to a new file, saving it as object.less:

@button-color: #4D926F;

input { margin-top: 10px; }

#submitbtn {
  background-color: @button-color;
  margin-top: 10px;
  padding: 3px;    
  color: #fff;
}

In our example, we've added a reference to the Less object, then used the modifyVars method to change the color of the @button-color variable, which we specified in object.less, to #61783F. We will cover variables in more detail in Chapter 4, Working with Variables, Mixins, and Functions.

Creating mixins

The next key element of Less is the creation of mixins, or predefined blocks of Less code that we can reuse from one ruleset, as part of another ruleset. So, we take the following block of CSS as an example:

.green-gradient {
  background: #5cb100;  
  background: linear-gradient(to top, #5cb100, #305d00);
  background: -o-linear-gradient(top, #5cb100, #305d00);
  background: -webkit-linear-gradient(top, #5cb100, #305d00);
}

Here, we've added a gradient color of dark green to a preset style rule called .green-gradient. So far so good; this will produce a perfectly usable gradient that fades from green to very dark green.

We could repeat this block of code for each instance where an object needs a similar style, but that would quickly lead to a lot of unnecessary code bloat. Instead, we can include the block of code as a mixin, within another style:

.shape1 {
  .green-gradient;
  border: 1px solid #ccc;
  border-radius: 5px;
}

This produces the following valid CSS—the mixin code is highlighted:

.shape1 {
  background: #5cb100;background: linear-gradient(to top, #5cb100, #305d00);
  background: -o-linear-gradient(top, #5cb100, #305d00);
  background: -webkit-linear-gradient(top, #5cb100, #305d00);
  border: 1px solid #ccc;
  border-radius: 5px;
}

Using this method means that we can cut down on the code we need to write and still produce the same results. As you will see in Chapter 4, Working with Variables, Mixins, and Functions, we will take this a step further—with some careful planning, we can begin to build up a library of mixins that we can reuse in future projects. The key to this is creating mixins that are sufficiently generic, which can then be reused as needed. Others have already created such libraries and made them available online—we will use some of the more well-known ones, such as 3L, More or Less and LESSHat, in our code examples.

The great thing about Less is that when we include these mixin libraries, Less will only include those mixins from the libraries where they are being referenced in our code. While it might initially seem like we're including a lot of extra code, the reality is that only a fraction of the code is used—it all comes down to careful planning as to how much we need to use!

Nesting styles in Less

Moving on, let's turn our focus to another key part of the Less library: the ability to nest styles. No, I'm not talking about bird habits (if you excuse the pun!), but a way to reduce repetition when creating your styles. Let me explain more.

Imagine you have a block of code similar to the following code, where a number of CSS styles have been created for child elements against their parent element:

#header { color: black; }
#header .navigation { font-size: 12px; }
#header .logo { width: 300px; }

On the face of it, this would appear normal code, right? Absolutely, there's nothing wrong with it. However, we can do better than this—as part of defining the class styles for each child element, there is a necessary degree of repetition in each style rule.

Using Less, we can embed or nest our styles more effectively. Our code will appear as this:

#header {
  color: black;
  .navigation {
    font-size: 12px;
  }
  .logo { width: 300px; }
}

Granted that it might not always reduce the number of lines required when writing code in your editor. However, this is not necessarily the aim of the exercise—the key here is to make the code more readable, as styles that relate to a specific element are grouped together, so it is clearer what role they play. You will find, particularly on larger sites, that this can sometimes mean a reduction in the number of lines we need to write—it all comes down to careful planning! We will cover nesting in more detail in Chapter 5, Inheritance, Overriding, and Nesting in Less.

Calculating values using operations

So far, our whistle-stop preview has taken us through creating variables, basic mixins, and reordering our code through the use of nesting. We're now going to step things up a little and have a look at the use of operators in our code.

Operators? Suprised? I am sure you are. Let's see what happens when we use them in our code. Imagine we have a number of shapes on screen, which are perfectly sized and positioned. We could use individual style rules for each element, but it would require careful calculations to ensure we had everything in the right place, particularly if any element needed repositioning.

Instead, we can use simple maths to work out the size and position of each element automatically, based on one or more given values:

@basic-width: 100px;

.shape1 { width: @basic-width; }
.shape2 { width: @basic-width * 2; }

It will, of course, require that each calculation be worked out, but once this is done, then all we need to do is change the initial value set, and it will automatically update every other value.

Note

It's worth noting that a strict math option is available in Less, which only calculates math that is encapsulated in parentheses, such as this code:

.class {
  height: calc(100% - 10px);
}

You can read more about this option at http://lesscss.org/usage/#command-line-usage-strict-math.

In our example, we've set an initial variable, @basic-width, of 100 px, then used it to double the width of shape2. Once the code is compiled, it will produce the following CSS:

.shape1 { width: 100px; }
.shape2 { width: 200px; }

If we were to change the value for .shape1 to 75px for example, then the width of .shape2 will be recalculated as 2 x 75px, or 150px. We'll be exploring more on the use of operators later in this book.

Extending existing styles in Less

This is a relatively new feature in Less and works almost as a direct opposite to a normal mixin. It takes a little time to get used to it, so let's examine a simple example—imagine you have a div tag that uses the following style rule:

div { background-color: #e0e0e0; }

The div tag produces a very light gray color as its background color. We can use this to extend another element:

p:extend(div) { color: #101010; }

This compiles to the following code:

div, p { background-color: #e0e0e0; }
p { color: #101010; }

Instead of adding a whole bunch of properties of a mixin class to an existing class, it adds the extending selector to the existing selector so that the output of the extended class includes both sets of styles.

The beauty of this is that it results in a similar effect to using mixins, but without the associated bloat that you sometimes get when using mixins. It works by taking the contents of the existing selector, in this instance background-color: #e0e0e0, and assigning it to the new selector, p. This way, we can be more selective about reusing styles from existing elements, without the need to introduce new mixins.

Tip

Note that extend will not check for duplicates. If you extend the same selector twice, it will add the selector twice. For more details, see http://lesscss.org/features/#extend-featureduplication-detection.