Writing CSS is front-end work, a common and frequent labor, because CSS is not a language, so in the program design is a little simple. For small projects, the amount of CSS is not huge and the problem is not obvious, but if you want to develop and maintain a larger project, you need to manage and regulate CSS, otherwise there will be irreversible consequences. .

background

In the last section [from CSS on modularity], we have optimized and improved the way CSS is written through the constraints of specifications, forming a sustainable development path. But some problems remain: redundancy. Although common’s volume is subtly shared by defining public and private modules, it is still too large, and by design we should refine as many public modules as possible for reuse. Ideally, all modules are stored in a common repository and can be pulled directly from the repository where they are needed. This wish is not impossible, and with the help of pre-processed languages, it can be easily accomplished.

Preprocessor language is a kind of CSS language, we know that CSS itself is not a language, and the birth of preprocessor language, is to fill this part of the language functionality. It implements variable, function, mixed definition, as well as file reference, merge, compression functions, so that CSS can also be object-oriented, complex and large business.

There are two popular preprocessing languages: less and sass. As a study, you can get an introduction to both, and as a job, try to familiarize yourself with one. I often use SASS, so the following content is introduced with SASS as the basic language. There are many similarities in features between the two, so you don’t have to worry about the differences in implementation.

sass

Basic grammar can be found on the official website (English) or W3CPLUS Sass Guide (Chinese). We will only briefly go over it here and talk about some of the content we need to use. We will not cover everything.

Sass files have two suffixes: one is called sass without braces and semicolons; The other is the SCSS file we use here, which is similar to the CSS file format we normally write, with braces and semicolons. All sass files in this tutorial refer to files with the suffix SCSS. It is also recommended to use a file with the suffix SCSS to avoid the strict formatting requirements of the sass suffix. — From W3CPLUS Sass Guide

1. Nesting (very important feature)

Sass nesting includes two kinds: one is the nesting of selectors; The other is nesting of attributes. We usually talk about or use nesting of selectors. — From W3CPLUS Sass Guide

Selector nesting Refers to the nesting of another selector in one selector to implement inheritance, thus enhancing the structure and readability of SASS files. In selector nesting, the parent element selector can be represented with &. — 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 of & here display: block; }}}Copy the code

The compiled:

/* 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 {// Notice the result of & display: block; }Copy the code

Is it great? Instead of copying and modifying a bunch of selectors over and over again, or rearranging the relationships between them, just nesting them is as straightforward as looking at the DOM! Free your hands, free your eyes, and increase your efficiency. It is important to note that when writing sass, we should try to keep the nesting order of Sass consistent with that of the DOM. Note that the nesting order is consistent, not the hierarchy, because not all elements in the DOM need to be styled.

If you want to migrate the m-article_box module from g-BD to G-HD, you can use the following code:






  index


  
      
The latest article
The article title
The article brief introduction
1 2 3 4
Copy the code
.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 { ... }Copy the code

In CSS fashion, we will copy all the m-article_box content from g-BD to G-HD. This is if the module’s writing is in compliance with the specification. If the module’s writing is not in compliance with the specification, it would be a disaster if the entire structure is not under the m-article_box class. We just need to cut the entire m-article_box block from G-BD to G-HD, and we’re done. :

.g-hd {... } .g-bd { .m-article_box { .hd { ... } .bd { .list { .item { .cover { ... } .info { .title { ... } .desc { ... } } } } } .ft { .page { .pg { ... }}}}} / / revised g - hd {. M - article_box {hd {... } .bd { .list { .item { .cover { ... } .info { .title { ... } .desc { ... } } } } } .ft { .page { .pg { ... } } } } } .g-bd { ... }Copy the code

It’s very convenient and error-free.

2. Variable

Let’s go straight to the code:

// index.scss

$fontSize: 16px;
$grey: #ccc;

.m-nav {
  font-size: $fontSize;
  color: $grey;
}Copy the code

Compile result:

/* index.css */

.m-nav {
  font-size: 16px;
  color: #ccc;
}Copy the code

If you’ve ever written code, you’re probably familiar with the use of parameters, but it’s so simple and so straightforward that you don’t want to say too much, but you can figure it out.

3. Function

// pixels to rems

@function rem($px) {
    @return $px / 640 * 16rem;
}Copy the code

It’s too simple and straightforward to say too much, but you know what to say.

4. Mixin

Mix, as the name suggests, means mix… That is, we can define a block of code in advance and include it wherever it is needed, and the code will not appear in the compile file until it is referenced, that is, nothing will be generated.

This is also a very important feature! We know that Common is very large, and the root cause of its large size is that it houses many, many modules. If every module was packaged as a mixin, wouldn’t common lose weight? ! There’s nothing like a glimmer of hope after years of suffering. We’ll get on:

/* common.css */

.m-nav { ... }
.m-news { ... }
.m-copy_right { ... }Copy the code

After transforming

// 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;
}Copy the code

5, the import

This property looks familiar, right? Yes, in fact, CSS already has this property implemented, and we can use import directly in CSS files to import other files. What is the difference between CSS import and Sass import? In terms of meaning and usage, there is no difference, the difference is how it works. CSS import blocks, whereas Sass import, when compiled, actually merges files and produces only one CSS file, whereas CSS does not merge files and has as many files as it needs.

Note:

  1. Only when you import a. Sass /. SCSS file, you can omit the suffix. If you import a. CSS file directly, complete the file name.
  2. Semicolon after import;Do not omit to write, will report errors;
  3. Sass If you import a. CSS file, it works just like CSS native import, only if you import a sass file.

As follows:

// index.scss
@import 'common';
@import 'a.css';Copy the code

Compile result:

/* index.scss */

.m-nav { ... }
.m-news { ... }
.m-copy_right { ... }

@import url('a.css');Copy the code

There is a reason why CSS imports are not commonly used. We can guess roughly how it works: A.css import b.css, when the browser loads a.css in the page, it is ready to render the page according to the contents of a.css. When it reaches the first line, it finds that a.css also imports a B.css, so it has to drop a.css. Load b.css until b.css is loaded, parse it first, and then start back to parse A.css — who knows if B.css will import c.css again… This directly leads to rendering delays and performance issues.

To be honest, I would rather use two link tags to load A.cs and B.cs synchronously. It would be more efficient.

So CSS imports are basically discarded attributes.

The main benefit of sass import is that it merges files and reduces requests. Pages that used to link several CSS files now only need one.

modular

Finally, to get down to business, let’s review some of the issues left over from the modularization project we built from the specification in the previous section.

  1. Redundant common of large volume;
  2. usecm-Module is the difference betweenm-Module, so that in the later development process,m-Module tocm-Module transformation process is tedious;

It doesn’t seem like there are too many problems. We’ll take them one at a time.

For convenience, here we call the SCSS file corresponding to each page page SCSS; Code that compiles variables, functions, blends, etc. (without reference or execution) without producing actual content is defined class code, and the corresponding other content is actual content code.

1, a mixin. SCSS

We know that, on the one hand, adding too many modules to common will eventually make common too large and redundant, and on the other hand, we want to make as many modules public as possible for easy maintenance.

This is a contradiction that CSS alone can’t solve, but Sass can! If we use mixins instead of writing directly to modules, since mixins don’t generate code directly, but rather actively reference it, then in theory common could store an infinite number of modules without taking up any space!

(Note that in theory, in practice, files that are too large will inevitably be limited by naming conflicts, but that’s not a problem.)

Without further ado, we packaged all the modules in Common as mixins:

/* common.css */

.m-nav { ... }
.m-news { ... }
.m-copy_right { ... }Copy the code

After transforming

// common.scss @mixin m-nav { .m-nav { ... } } @mixin m-news { .m-news { ... } } @mixin m-copy_right { .m-copy_right { ... }}Copy the code

Call as follows:

// index.scss @import 'common'; Common. g-index {@include m-nav; @include m-news; @include m-copy_right; }Copy the code

Instead of referring to common first and then to page CSS on every page that needs to use a common module, we simply need to @import common in the page SCSS; That’s it.

The use of common:






  index
  
  


  ...


Copy the code

After transforming:

// index.scss
@import 'common';Copy the code





  index
  


  ...


Copy the code

Perfect, at least so far.

We thought about the question, is there anything else in Common besides modules? The answer is yes, you must know that there is something called CSS reset (or normalize.css), which must be global; In addition, if you are doing a background management system, you may also have bootstrap. Of course, there are also custom global styles, such as the common.clearfix, and so on.

These are the things we currently stack in common, and they make sense because they are global styles. But compared to mixins, the actual content code is so small that it feels drowned out, making the entire Common look like mixins alone. But the actual content code is very important. In order to make the composition of common more intuitive, we extract all mixins, store them in a separate file named mixin. SCSS, and reference them in common. In this way, the management of mixins is more standardized, and the structure of Common is clearer.

Another important reason to steer clear of mixins, which we’ll cover later, is that we want mixins to be purely defined class code files that can be referenced everywhere without generating extra code.

Instead of referring to common first and then to page CSS on every page that needs to use a common module, we’ll simply use @import mixin in the page SCSS; That’s it.

With mixins:

// index.scss @import 'common'; // add mixin@import 'mixin' to common if necessary; // add mixin.g-index {... }Copy the code





  index
  


  ...


Copy the code

2, common SCSS

Ok, so now that we’ve removed the mixins, let’s go back to the common and see what the common should look like. We’ve touched on that a little bit, so let’s expand on that.

2.1, CSS reset (normalize)

We know that browsers differ from one another, and that the default styles vary from browser to browser. The most common ones are the default body margin, the default P tag margin, ul/ OL, and so on. These inconsistent default styles are often a pain in the butt, so the idea of getting rid of them in the first place was the result of the very popular reset.css.

The original reset.css was simple and looked something like this:

html, body, h1, h2, h3, h4, h5, h6, div, dl, dt, dd, ul, ol, li, p {
  margin: 0;
  padding: 0;
}Copy the code

That’s right, we’ve removed the inside and outside margins of almost all the tags that we use, so that all the tags are uniform, and they’re uniform across browsers.

For other parts, each person has their own supplement. For example, some people will define all the font sizes of H1 ~ H6 to ensure that they have the same size in different browsers. Someone will give the A tag a uniform font color and hover effect, and so on.

Fine, nothing wrong with it. We call them CSS Reset, and then encapsulate them in a file called reset.css that we refer to on every page.

This has always worked, and everyone has done it without any problems. It was only later that someone suggested that this approach was too rude… It also degrades page rendering performance, and most importantly, it makes the tags that we’ve designed to express meaning look feature-less…

That makes sense. What’s the point if everyone in your family has the same name but they all look the same?

So, normalize. CSS. The goal of normalize is to unify the different default styles in different browsers. At the same time retain the original characteristics of each label.

We can not say that the two ideas of reset and normalize which is better, can only say that each has its own characteristics and functions, they exist to solve the same problem.

2.2, the plug-in

Generally speaking, a UI plug-in will include at least one CSS file, such as Bootstrap, datepicker, and so on. Assuming that we need to use bootstrap as the basic framework for rapid development in our project, we need to introduce bootstrap.min. CSS and bootstrap.min.js globally in our project. When we think about global exposure, the first thing that comes to mind is Common, and yes, we can introduce that in Common.

How to import the plugin’s.css file? Well, change the extension to. SCSS, which is compatible with native CSS syntax

So in the end, our common looks something like this:

// common.scss

@import './reset';
@import './bootstrap.min';
@import './mixin';Copy the code

In fact, if we don’t need to use mixins and variables in mixin.scss, we don’t need to refer to mixins.

So our page SCSS should look like this:

// index.scss

@import './common';
@import './mixin';

.g-index {
  ...
}Copy the code

Clean and tidy.

3. Mixin writing specification

Every time we add a new character, we need to give it a specification in time so that it doesn’t mess up as much as we want it to. Let’s summarize the writing specifications for mixins.

Scenario 1: There are three files mixin. SCSS, A.css (assuming it is a function file), and index. SCSS. $color: # CCC; If we reference both files in the index, then we can use the variables $fontSize and $color directly in the index — I mean, even though we don’t see the declarations and definitions of these variables in the index, they just exist.

Is that a good thing or a bad thing? Something tells me there might be a problem. Yeah, isn’t that similar to the pollution we talked about earlier? It’s just that after we referenced common, index had taken up a lot of module names before we wrote anything, and now it’s taking up a lot of variable names because we referenced other files. Also, from a maintenance point of view, this is problematic. If I don’t tell you beforehand, or if you don’t look at mixin and a first, do you know where the $color in index comes from? Suppose we need font size, do you know which file to go to change it? In addition, how can you ensure that when you refer to mixin and A at the same time, there may be a variable with the same name between them? So who covers whom? These problems may seem small, but when your project is large, it can be an irreversible disaster (scare who??). .

Scenario 2: Suppose our project has a theme color, border, TAB background, navigation background, font color, etc., all of which are theme colors. For convenience, we don’t want to use color pickers all the time, so we define a global variable $color: #ff9900 in mixin, and then we can happily use it everywhere!

A month after the whole site is developed, the designer suddenly comes to you and says, “The boss says we need to change the theme color. It’s a little cheesy. Let’s change it to a bright red.” “, you reluctantly but secretly open mixin, change the value of $color to red, and say to the designer: “Fortunately, I have prepared for this, you can see.” , save, open the page, the designer and your face is green, what page so ugly, some words were originally theme color, but the background is red, and now the change, the whole piece into red, the content all could not see, some border was originally a red, but the colour theme of font is originally a change now, however, borders to become a red font.

Designer: “No, no, no, I just want to change the background color.” You: “Didn’t you say change the theme color? That’s all there is.” Designer: “No, just change the background.” You: “I can’t…” Designer: “Why not, just change a background color? How to set how to change back ah.” You: “It’s not as simple as you think…”

All right, I’m just bluffing, but none of this is a big deal if you’re really good at it.

So we need to manage (global) variables in the same way we managed mixins. We can’t just define them where we want them, and we can’t change a global variable at the drop of a switch:

  1. Global variables are defined only in mixins, and variables defined in other SCSS files (whether exposed globally or locally) are treated as local variables only and are not used outside the current file (even if they can be referenced, avoid using them);
  2. Import mixin directly where global variables are needed;
  3. In general, global variables should be defined carefully and the number of global variables should be as small as possible.
  4. Do not change as much as possible. If the requirements change, unless the purpose is very certain, please add a global variable to gradually replace the place that needs to be modified;
  5. Don’t use generic nouns as global variables, such ascolor, the suggestion is to use the color value of the description, such as$orange: #ff9900If the color value needs to be changed, but not everywhere, then we can define a new variable to extend it, for example$red: red.

All of these points are a little bit vague, and it’s actually hard to see why, since they’re all empirical, so you might want to think about them after you’ve been familiar with Sass for a while.

Note that none of this is a dead end. At some point, the specification will need to be adjusted to suit the actual project, as we will see later in spAs. There is no such thing as a perfect project, and there is no one-size-fits-all development model. And none of the problems we’ve mentioned so far are fatal. The fatal problems were avoided in the last section when we created the specification.

Call modules

Question, where is the module called? A, page SCSS.

It is a good practice to call modules in a page SCSS so that the modules we use on each page are consistent and isolated from each other, unlike in common where direct references to modules pollute a page SCSS with many module names before it has any content.

Another question, where does the page SCSS call the module?

Example 1, outside the root class:

// index.scss

@import './common';
@import './mixin';

@include m-nav;
@include m-news;
@include m-copy_right;

.g-index {
  ...
}Copy the code

Example 2, within the root class:

// index.scss @import './common'; @import './mixin'; .g-index { @include m-nav; @include m-news; @include m-copy_right; . }Copy the code

So far, both approaches work, and the reason WHY I use the word “so far” is because we’re going to get to SPA later, if the use case one approach is problematic. So I encourage the use of example two. Of course, as I said, example one is fine so far.

Performance optimization

So far, we’ve done our modularization work, and we’re ready to call it a day. But we can optimize it a little bit.

1, caching,

We need to consider one issue: caching.

Caching is one of the most common things we do in Web development, and we need to deal with caching a lot of times, especially when doing performance optimizations.

Typically, after a static resource is loaded into the browser, the browser caches it locally so that it can respond quickly to the next request for the same resource without having to load it from a remote server.

For CSS, if you load reset, bootstrap, common, and index files with multiple links, these files will be cached so that the next time you visit the page, the page will load much faster.

What if I jump from the Index page to the About page? You’ll notice that it’s also fast because the global CSS (reset, Bootstrap, common) for the About page and the Index page are the same, and they are already loaded when you access the index page. Thanks to caching, subsequent pages open faster.

The way we have it now, all the CSS files used on a page are merged into one, so there are no identical files that can take advantage of the cache.

Is there anything we can do to improve? Some! We just need to isolate common so that common can be used as a cached public file. We ended up going from one file per page to two files per page, common and page CSS:

// common.scss

@import './reset';
@import './bootstrap.min';
@import './mixin';Copy the code
// index.scss

@import './mixin';

.g-index {
  ...
}Copy the code

Note that unlike before, our index. SCSS no longer introduces common. SCSS, so we end up with two CSS files, while common. CSS is introduced in all pages with the link tag.

In this way, we can merge files to reduce the number of requests while taking advantage of caching to increase loading speed.

2, the compression

Code compression is the most basic step in optimization, CSS compression is a lot of room, especially our vertical writing style, compression is quite efficient.

Sass provides several compressed modes during compilation, among which compressed mode is the most efficient. Remember to select compressed mode when compiling package.

conclusion

In general, preprocessing languages make our programming more beautiful, but also make the specification more perfect. In cases where CSS itself is not possible, we use tools to achieve modular development.

I will not go into how to install and configure the SASS environment, because the W3CPlus SASS Guide has a detailed description of it. It is recommended to use nodeJS instead of messing with the nodeJS/NPM front end.

Finally, we come back to the original question — why modularity? For now, we can start with the work of CSS. In a sense, modularity improves our programming and problem solving abilities, making it possible to build large, scalable and maintainable projects, and to build entire projects with an architectural mind.

Under a cost-saving to with the content of this article directly said, SPA, but found that the content of the SPA is componentized, meaning that it is not just the content of the CSS, need more knowledge to plays, or with the first so, the next section, we come to know HTML and template engine modular practice 】 【 (soon, please note)