The modularization practice of CSS preprocessing language

Source: Internet
Author: User
Writing CSS is the front-end work, a common and frequent labor, because CSS is not a language, so in the program design is somewhat humble. For small projects, the amount of CSS is not too large, the problem is not obvious, and if you want to develop and maintain a larger project, it will need to manage and standardize the CSS, otherwise there will be irreversible consequences (scare who?? )。

Background

In the previous section, "Modular from CSS" We have optimized and improved the way CSS is written by standardizing constraints, forming a sustainable route. But there are still some problems left: redundancy. Although we can gently share the volume of the common by defining public modules and private modules, the volume of the common is still too large, and in design, we should try to refine the public modules as much as possible in order to achieve better reuse. Ideally, all modules are sent to a common library where they need to be transferred directly from the library. This wonderful wish is not achievable, and we can do it easily with pre-processing language.

Preprocessing language is a kind of CSS language, we know that CSS itself is not a language, and the birth of preprocessing language is to fill this part of the language function. It implements variables, functions, hybrid definitions, as well as file references, merging, and compression, so that CSS can also be object-oriented to cope with the complexity of a large business.

There are two main types of preprocessing languages: less and sass. As a study, both can get started, and as a job, try to be familiar with one. I used to sass, so the following are sass as the basic language to introduce, the two have a lot of similarities in characteristics, so you do not have to worry about the implementation of what is different.

Sass

Basic grammar can go to the official website (English) or W3cplus Sass Guide (Chinese) to see the study, we simply go through it here, to tell some of the content we need to use, not exhaustive.

Sass has two suffix files: a suffix named sass, no curly braces and semicolons, and the Scss file we use here, similar to the CSS file format we normally write, using curly braces and semicolons. All of the Sass files described in this tutorial refer to files with the suffix named Scss. It is also recommended to use a file with the suffix named Scss to avoid the strict formatting requirements for sass suffix names. --Excerpt from W3cplus Sass Guide

1. Nesting (very important features)

The nesting of sass consists of two kinds: one is the nesting of selectors, the other is the nesting of attributes. What we generally talk about or use is the nesting of selectors. --Excerpt from W3cplus Sass Guide

selectors nesting the so-called selector nesting refers to nesting another selector in one selector to implement inheritance, which enhances the structure and readability of the sass file. In a selector nesting, you can use & to represent the parent element selector. --Excerpt from W3cplus Sass Guide

Index.scss.g-index {  ...  . G-HD {    ...    . M-nav {...}  }  . G-BD {    ...    . m-news {...}  }  . g-ft {    ...    . M-copy_right {...}  }  . M-dialog {    display:none;    &.z-active {  //Notice the usage display:block here &}}}  

After compiling:

/* Index.css */.g-index {...}. G-index. G-hd {...}. G-index. G-hd. M-nav {...}. G-index. g-bd {...}. G-index. g-bd. m-news {...}. G-index. g-ft {...}. G-index. g-ft. m-copy_right {...}. G-index. m-dialog {  display:none;}. G-index. m-dialog.z-active {  //Note The compiled result of & here  Display:block;}

Is it cool or crooked? You don't have to copy and modify a bunch of selectors over and over again, and you don't need to sort out the relationships between them, just nest them, and all the relationships are as straightforward as looking at the DOM! Liberate your hands, liberate your eyes, and increase your efficiency. It is worth noting that when we write sass, we should try to keep the nesting order of sass consistent with the DOM, noting that the nesting sequence is consistent rather than hierarchical, because not all elements in the DOM require a write style.

Let us mention a scene, that sass nested wording for maintenance, assuming G-BD under the original module M-article_box, now we want to transfer m-article_box from G-BD to G-HD (of course, this demand is somewhat unreasonable ~), we look at the original code:

<!--index.html--><! DOCTYPE html>
. g-bd {...}. G-bd. M-article_box {...}. G-BD. M-article_box. HD {...}. G-BD. M-article_box. bd {...}. G-BD. M-article_box. bd. List {...}. G-BD. M-article_box. Bd. list. Item {...}. G-BD. M-article_box. Bd. List. Item. cover {...}. G-BD. M-article_box. Bd. list. Item. info {...}. G-BD. M-article_box. Bd. list item. info. title {...}. G-BD. M-article_box. Bd. list. Item. info. desc {...}. G-bd. M-article_box. ft {...}. G-bd. M-article_box. ft. page {...}. G-bd. M-article_box. Ft. page. PG {...}

In the way of CSS, we are going to copy all the parts related to M-article_box from G-BD to G-HD. This is still in the module's writing conforms to the specification, if this module writing does not conform to the specification, does not have the entire structure to hang under the M-article_box class, that really is the disaster ~ and now uses sass words, we only need to put M-article_ Box block entire from G-BD cut to G-hd on the finished (here in order to highlight the workload of the change, I specifically put the entire module structure is written all-not to make up the word number ... ):

Modified before. G-hd {...}. G-BD {  . m-article_box {.    HD {...}.    BD {      . list {        . item {.          cover {...          }          . Info {            . title {              ...            }.            desc {              ...}}}}    . FT {.      page {        . pg {...}    }}}  Modified. G-HD {.  m-article_box {    . hd {...}.    BD {      . list {        . item {.          cover {...          }          . Info {            . title {              ...            }.            desc {              ...}}}}    . FT {.      page {        . pg {...}}}      }  . G-BD {...}

Very convenient, and not easy to make mistakes.

2. Variables (variable)

Let's go directly to the code:

index.scss$fontsize:16px; $grey: #ccc;. M-nav {  font-size: $fontSize;  Color: $grey;}

Compilation Result:

/* Index.css */.m-nav {  font-size:16px;  Color: #ccc;}

People who have written code are familiar with the use of parameters , too simple too straightforward to say too much, I feel it.

3. Functions (function)

Pixels to rems@function REM ($px) {    @return $px/640 * 16REM;}

It's too simple to say too much.

4. Mixing (mixin)

Mixing, as the name implies, is the meaning of mixing ... That is, we can define a block of code in advance, where we need to use the direct reference (include), and before the reference, this code will not appear in the compilation file, that is, no content generated.

This is also a very important feature! We know that the size of the common is very large, and the fundamental reason for its large size is that it stores many modules. We imagine, if each module is packaged into a mixin, then common not lose weight success?! Many years of stubborn disease finally see hope, no more surprising than this! Let's get in the car:

/* Common.css */.m-nav {...}. M-news {...}. M-copy_right {...}

After the transformation

Common.scss@mixin M-nav {  . M-nav {...}} @mixin m-news {  . m-news {...}} @mixin m-copy_right {  . m-copy_right {...}} Index.scss.g-index {  @include m-nav;  @include m-news;  @include M-copy_right;}

5. Import

This property looks familiar? Yes, in fact, the CSS itself has this property implementation, we can use import directly in the CSS file to introduce other files. So what is the difference between the import of CSS and the import of sass? There is no difference between meaning and usage, and the difference is in how it works. The import of CSS is blocked, and the import of sass after compiling, is actually merging files, finally only a CSS file, and CSS is not merged, the number of files is still how many files.

Attention:

    1. Only import a. sass/.scss file, you can omit the suffix name, if it is directly import a. css file, to complement the full file name;


    2. The semicolon after import, do not miss write, will error;


    3. Sass If the import is a. css file, then it functions as a CSS native import function, only import a sass file, is the merge file.

As follows:

Index.scss@import ' common '; @import ' a.css ';

Compilation Result:

/* Index.scss */.m-nav {...}. M-news {...}. M-copy_right {...} @import url (' a.css ');

There is a reason why the import of CSS is not universally used. We can probably guess how it works: A.CSS Import B.css later, when the browser loaded into the page a.css, is ready to follow the A.CSS content to render the page, just resolved to the first line, found A.css incredibly also import a b.css, so it had to put down a.css (both blocking a.css), to load b.css, until B.C SS loaded, and first resolved it, and then began to parse a.css--ghost know b.css will not again import C.css ... This directly results in rendering work lagging and causing performance problems.

To tell the truth, I might as well use two link tags to load a.css and b.css synchronously, which is more efficient.

Therefore, the import of CSS is basically discarded properties.

The main benefit of Sass's import is that it merges the files and reduces the requests. Originally need to link several CSS file page, now only need one.

Modular

At last, let's take a look at some of the problems we've left behind in our modular project, which we built on a normative basis.

    1. A large common of redundant volume;


    2. Using cm-module to distinguish M-module, so that in the late development process, M-Module to cm-module transformation process is more cumbersome;

......

It seems that the problem is not particularly much, we solve it one by one.

For convenience, here we refer to each page of the corresponding scss file is called page scss, the variables, functions, mixes, etc. (without being referenced or executed) after compiling code that does not produce the actual content is called the definition class code, then the corresponding other content is the actual content code.

1, Mixin.scss

We know that, on the one hand, the excessive addition of modules in common will eventually lead to common volume is too large, so that resources are redundant, on the other hand, in order to facilitate maintenance, we also hope that the module as much as possible to public.

This is a pair of contradictions, only by the CSS itself is impossible to solve, but sass can! If we use mixin to replace the direct writing module, because Mixin does not generate the code directly, but through the active reference, in order to generate the corresponding content, then theoretically, common can store the module infinitely more without occupying a little space!

(Note that the theory is that in practice, the file is too large to be subject to a naming conflict, but this is not a problem.) )

To do it, we pack all the modules in the common into mixin:

/* Common.css */.m-nav {...}. M-news {...}. M-copy_right {...}

After the transformation

Common.scss@mixin M-nav {  . M-nav {...}} @mixin m-news {  . m-news {...}} @mixin m-copy_right {  . m-copy_right {...}}

The method is called as follows:

Index.scss@import ' common '; Remember to first introduce Common.g-index {  @include m-nav;  @include m-news;  @include M-copy_right;}

Originally we will in each need to use the Public module page, the first reference common, and then refer to the page CSS, and now, we just need to scss directly in the page @import common;

Using common:

<!--index.html--><! DOCTYPE html>

After transformation:

Index.scss@import ' common ';
<!--index.html--><! DOCTYPE html>

Perfect, at least so far.

Let's think of a question, common, is there anything else besides the storage module? The answer is yes, you must know that there is a thing called CSS reset (or NORMALIZE.CSS), this is definitely the overall, and if you are doing a background management system, there may be bootstrap. Of course, there are some custom global styles, such as common. Clearfix, and so on.

These things are now piled up in common, and it makes sense, because they are all global in style. But compared to mixin, these actual content code appears to be very small, a kind of submerged feeling, make the whole common look like only mixin. But the role of these actual content code is very important. In order to make the composition of the common more intuitive, we mixin all out, separate a file called Mixin.scss, and then refer to it in common, so that the mixin management more normative, and common structure is more clear.

There is another important reason for pulling away from Mixin, which we want to mixin as a purely defined class code file that can be referenced everywhere without generating extra code.

Originally we will in each need to use the Public module page, the first reference common, and then refer to the page CSS, and now, we just need to scss directly in the page @import mixin;

Using mixin:

Index.scss@import ' common ';  The introduction of common, if necessary, common in the same can be introduced mixin@import ' mixin ';  Introduce Mixin.g-index {  ...}
<!--index.html--><! DOCTYPE html>

2, Common.scss

Well, after pulling away from Mixin, let's now look back at what the Common,common should be like. We mentioned a little bit of the above, let's start.

2.1. CSS Reset (normalize)

We know the browser is very different, the default style of the browser is not the same, the most common, such as the body's default padding, the P tag's default padding, and Ul/ol, and so on. These non-uniform default styles often make us feel headache, so it is suggested that the idea of first writing a style to eliminate them, thus creating a very popular reset.css later.

The initial reset.css was simple, presumably:

HTML, body, H1, H2, H3, H4, H5, H6, p, DL, DT, DD, UL, OL, Li, p {  margin:0;  padding:0;}

Yes, almost all of the tags used are given the inner margin and margin, simple and rough, so all the labels are unified, and in different browsers are unified.

Each of the others has their own additions, for example, someone would define all the font sizes of H1~H6 to ensure they have a uniform size in different browsers, and someone will set a uniform font color and hover effect for the a tag, and so on.

Good, no problem. We refer to these as CSS reset and then uniformly encapsulate them in a file called Reset.css, and then each page is referenced.

This approach has always been very practical, and everyone is so used, there is no problem. But later someone raised, this way is too rough (incredibly also distressed browser) ... And it will degrade the performance of page rendering, and most importantly, this makes us the original design of the expression of various meanings of the label, has become no feature ...

It makes sense to say that if all the people in your family have different names but they all look alike, what do you mean?

As a result, the purpose of the normalize.css,normalize is to unify the different default styles under each browser, but it is not simply and brutally completely flat, but according to the specification, to artificially put those non-conforming default style "righting", In order to achieve unified browser default style, while preserving the original characteristics of each label.

We can not say that the two ideas of reset and normalize are good or bad, can only say that each has its own characteristics and role, their existence is to solve the same problem.

2.2. Plugins

In general, a UI plug-in will include at least one CSS file, such as Bootstrap, DatePicker, and so on. Assuming that we need a bootstrap-based framework for rapid development in our project, we need to introduce BOOTSTRAP.MIN.CSS globally in the project, and, of course, bootstrap.min.js. When it comes to global exposure, the first thing we think about is common, yes, we can introduce it in common.

Someone asked, how to import the plugin's. css file? Well, change the extension to. scss, Scss is compatible with native CSS syntax ~

So in the end, our common is probably like this:

Common.scss@import './reset '; @import './bootstrap.min '; @import './mixin ';

In fact, if we don't need to use variables and mixin in Mixin.scss, we can not reference it.

So our page scss should look like this:

Index.scss@import './common '; @import './mixin ';. G-index {  ...}

Clean.

3, Mixin writing specifications

Every time we add a new role, we need to set it up in a timely fashion so that it doesn't get any worse from what we expect. Let's summarize the mixin writing standard.

Scenario One: The project has MIXIN.SCSS, A.SCSS (assuming this is a function file), index.scss three files, mixin defined a variable $fontsize:16px;,a defined in a variable $color: #ccc; We refer to these two files at the same time in index, so we can use both the $fontsize and the $color variables in index--I mean, although we don't see the declarations and definitions of the two variables in index, they exist.

Is this a good thing or a bad thing? Intuition tells me that this may be a problem. Yes, is this like the pollution we discussed before? It's just that after we quoted the common, Index has already occupied a lot of module names without writing anything, and now it is because other files are referenced, which takes up many of the variable names of index. In addition, on the maintenance point of view, this is also problematic, if I do not tell you beforehand, or you do not read mixin and a in advance, you know the index of $color is where? Suppose we need font size, do you know which file to change? In addition, how do you guarantee to refer to mixin and a at the same time, there is no possibility that there is a variable of the same name? Who's covering who? These problems may seem small, but when your project is large, it can be an irreparable catastrophe. )。

Scenario Two: Suppose our project has a theme color, border, tab background, navigation bar background, as well as font color and so on, are the theme color, in order to facilitate the use, do not want to always use the color picker to take the value, so we define a global variable in mixin $color: #ff9900, Then you can use it happily everywhere!

The entire Web site development finished, one months later, the designer suddenly came to say to you: "The boss said, this theme color to change, a bit of Earth, we change a red." ", so you face reluctantly but secretly happy to open mixin, the value of $color to the red, and then to the designers said:" Fortunately I have prepared, done, you look at it. " ", Save, open the page a look, the designer and your face are green, the page how so ugly, some words originally is the theme color, but the background is red, and now a change, the whole block has become red, the contents are not clear, some border is originally red, but the font is the original theme color, but now a change, The border and the font all turn red.

Designer: "No, no, no, I just want to change the background color." ”
You: "You don't mean to change the theme color?" That's all the place. ”
Designer: "No, it's better to change the background." ”
You: "No ah ... ”
Designer: "Why not, just change a background color?" How to set how to change back AH. ”
You: "Not as simple as you think ... ”

......

All right, I'm scaring you, and if you can do this, then it's not a good thing.

So we need to manage (global) variables, just as we did when we managed mixin, where we couldn't define where we defined them, or modify a global variable at will:

    1. Global variables are defined only in mixin, and other SCSS file-defined variables (whether exposed to global or local) are treated as local variables and are not used outside of the current file (that is, in cases where they can be referenced, they are also avoided);


    2. Need to use global variables where the direct import mixin;


    3. In general, the definition of global variables should be prudent, the number of global variables should be as small as possible;


    4. Do not change as far as possible, if the demand changes, unless the use is very certain circumstances, otherwise, please add a global variable to gradually replace the need to modify the place;


    5. Do not use too general nouns as global variables, such as color, the suggestion is directly using the color value of the description, such as $orange: #ff9900, which makes us more convenient maintenance on the extension, if the color value needs to be modified, but not all the places need to be modified, Then we can define a new variable to extend it, such as $red:red.

These points are a bit erratic, in fact, it is difficult to understand why to do so, after all, is the experience, so we might as well first familiar with the use of sass a period of time, then to ponder these problems.

Note that these are not death rules, and at some point the specification needs to be adjusted according to the actual project, such as the spa we are going to talk about later. Perfect projects do not exist, and there is no development model that can be applied to all projects, so that the problem can be solved better with local conditions. And the problems we're talking about are not deadly, and the deadly problem has been averted in the last section when we set the rules.

Calling module

Question, where is the module called?

Answer, Page scss.

It is a good habit to call the module in page Scss, which makes the modules we use in each page are both consistent and isolated, unlike referring to modules directly in common, so that a page scss has been polluted by many module names when there is no content.

Ask another question, where is the module called on the page scss?

Example one, outside the root class:

Index.scss@import './common '; @import './mixin '; @include m-nav; @include m-news; @include m-copy_right;. G-index {  ...}

Example two, within the root class:

Index.scss@import './common '; @import './mixin ';. G-index {  @include m-nav;  @include m-news;  @include M-copy_right;  ...}

So far, both of these methods are possible, and as for why I use the word "so far", that's because the spa we're going to talk about later, if the use case one is problematic. So I encourage the use of example two ways. Of course, I said, so far the example is no problem.

Performance optimization

So far, our modular work has been completed, in fact, can be finished. But we can still do a little bit of optimization.

1. Cache

We need to consider a problem: caching.

Caching is one of the most common scenarios in our web development, and many times we need to deal with caching, especially when it comes to performance optimizations.

In general, when a static resource is loaded into a browser, the browser caches it locally so that it can respond quickly the next time the resource is requested, without having to go to the remote server to load it.

As far as CSS is concerned, if we use multiple link to load reset, bootstrap, common, index files in the original way, these files will be cached so that the next time we visit this page, the page will load much faster.

If you are jumping from the index page to the About page? You will find it also very quickly, because the global CSS (reset, bootstrap, common) and index pages of the About page are the same, and they are already loaded when you visit index, thanks to the caching effect, then the page opens quickly.

The way we do it now is that all the CSS files that a page uses are merged into one, and there is no such thing as the same file that can take advantage of caching.

Do we have a way to improve it? Some! We just need to separate the common, so common can be cached as a public file. Finally we refer to a single file from a page to a page referencing two files, namely common and page CSS:

Common.scss@import './reset '; @import './bootstrap.min '; @import './mixin ';
Index.scss@import './mixin ';. G-index {  ...}

Note that unlike before, our index.scss here no longer introduces COMMON.SCSS, so we finally get two CSS files, and common.css is introduced through the link tag on all pages.

As a result, we can combine files, reduce requests, and use caching to increase loading speed.

2. Compression

Code compression is the most basic step in the optimization work, CSS compression space is very large, especially our vertical writing method , compression is quite efficient.

In sass This is very simple, sass in the compilation of the time to provide several modes, wherein the compressed mode is the most efficient compression mode, remember to compile the package when the choice of compressed mode on the line.

Summarize

In general, the preprocessing language makes our programming more beautiful at the same time, also make the specification more perfect. In the case where the CSS itself cannot be implemented, we have done the modular development with the tools.

I'm not going to talk about how to install and configure the Sass environment, because these w3cplus sass Guide has a detailed introduction, the recommended way to use Nodejs, not to tinker with NODEJS/NPM front end is not good.

Finally, let's go back to the first question-why modularity? Now we can answer from the work of CSS, in a sense, modularity has improved our ability to program and solve problems, making it possible to build a large and scalable maintainable project, enabling us to build an entire project with architectural thinking and vision.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.