When working on large-scale, long-term projects with many people, it is extremely important that all developers adhere to the following rules:
**Keep CSS accessible Maintainability**
**Keep the code clear and easy to understand**
**Keep the code scalable**
In order to achieve this To achieve this goal, we must adopt many methods.
The first part of this document will discuss syntax, format and CSS analysis; the second part will start with methodology, thinking framework and attitude towards writing and planning CSS.
## Directory
* CSS document analysis
* Overview
* Single file and multiple File
* Directory
* Chapter title
* Code sequence
* Rule analysis
* Naming convention
* JavaScript hooks
* I18n
* Comments
* Extended usage of comments
* Quasi-modified selector
* Code Tags
* Inherit tags
* Write CSS
* Add new section
* Object-oriented CSS
* Layout
* Interface size
* Font size adjustment
* Abbreviation
* IDs
* Selector
* Modified selection Selector
* Selector performance
* Selector inheritance
* `!important`
* Magic number and absolute ratio
* Conditional judgment
* Debugging
* Preprocessing
---
## CSS document analysis
No matter what document we write, we should try our best to maintain a unified style, including unified comments, unified grammar and unified naming convention.
### General
Try to keep the line width under 80 bytes. Gradient-related syntax and URLs in comments can be counted as exceptions. After all, there is nothing we can do about this part.
I prefer to use 4 spaces instead of tab indentation, and split declarations into multiple lines.
### Single file vs. multiple files
Some people like to write styles as one big file, which is not bad, and if you follow You will not encounter any problems if you write the following rules. After I moved to Sass, I started splitting my styles into many small files. That's not bad either. Whichever way you go, the rules below will apply. The two writing methods only differ in the directory and block titles.
### Table of contents
At the beginning of the CSS, I would write a table of contents, for example:
/*--------------------------------*
$ CONTENTS
*--------------------------------*/
/**
* CONTENTS............You’re reading it!
* RESET...............Set our reset defaults
* FONT-FACE...........Import brand font files
*/
This directory can tell other developers what content is contained in this file. Each item in this directory has the same block title as its corresponding block.
If you are maintaining a larger single-file CSS, the corresponding blocks will also be in the same file. If you are writing a set of small files, then each item in the directory should have a corresponding @include statement.
### Block title
The table of contents should correspond to the title of the block. Please see the following example:
/*---------------------------------- -----*
$RESET
*----------------------------- -------*/
The block title prefix `$` allows us to use the ([Cmd|Ctrl] F) command to find `$[SECTION-NAME]` , while limiting the search to block titles.
If you are maintaining a large file, then leave 5 empty lines between blocks, like this:
/*--- ----------------------------------*
$RESET
*- ----------------------------------*/
[Our
reset
styles]
/*-- ----------------------------------*
$FONT-FACE
*----------------------------------------*/
These large gaps help distinguish chunks when flipping quickly through large files.
If you are maintaining multiple copies of CSS connected with @include, just add a title to the header of each file without having to leave a blank line like this.
## Order
Try to write the rules in a specific order. This will ensure that you get the most out of the first C in the CSS abbreviation: cascade , cascading.
A well-planned CSS should be arranged as follows:
1. **Reset** The root of all things
2. **Element type** `h1`, `ul`, etc. without class setting
3. **Object and abstract content** The most general and basic design pattern
4. **Sub-elements** All expansions and sub-elements extended from the object
5. **Fix** For abnormal conditions
like this Now, when you write CSS sequentially, each block can automatically inherit the properties of the block before it. In this way, the parts of the code that offset each other can be reduced, some special problems can be reduced, and a more ideally designed CSS structure can be formed.
For more information on this, Jonathan Snook’s [SMACSS](http://smacss.com) is highly recommended.
## CSS rule set analysis
[selector]{
[property]:[value];
[<- Declaration ->]
}
[Selector]{
[Attribute]:[Value] ;
[<-Declaration->]
}
When writing CSS styles, I like to follow these rules:
* Class names are connected with hyphens (-), except for the BEM nomenclature mentioned below;
* Indent 4 spaces;
* Declaration split into multiple lines;
* declarations are arranged in relevance order, not alphabetical order;
* prefixed declarations are indented appropriately, aligning their values;
* indented Improve the style to reflect the DOM;
* Keep the semicolon at the end of the last declaration.
For example:
.widget{
padding:10px;
border:1px solid # BADA 55; radius:4px;
}
.widget-heading{
font-size:1.5rem;
line-height:1;
font - weight: bold; padding: 0.25em;
}
We can find that `.widget-heading` is a child element of `.widget`, because the former is more indented than the latter Level one. This allows developers to quickly access information when reading these styles.
We can also find that the declarations of `.widget-heading` are arranged according to their relevance: `.widget-heading` is a text element, so we add font-related styles first Statement, then comes the rest.
The following is an example without splitting into multiple lines:
.t10 { width:10% }
.t20 { width:20% }
.t25 { width:25% } /* 1/4 */
.t30 { width:30% }
. t33 { width:33.333% } /* 1/3 */
.t40 { width:40% }
.t50 { width:50% } /* 1/2 */
.t60 { width:60% }
.t66 { width:66.666% } /* 2/3 */
.t70 { width:70% }
.t75 { width:75% } /* 3/4*/
.t80
In this example (from [inuit.css's table grid system](https://github.com/csswizardry/inuit.css/blob/master/inuit.css/partials/base/_tables .scss#L88)), placing CSS on one line can make the code more compact.
## Naming convention
Generally, I connect class names with hyphens (-) (for example `.foo- bar` instead of `.foo_bar` or `.fooBar`), but in certain situations I will use the BEM (Block, Element, Modifier) nomenclature.
BEM The nomenclature can make the selector more standardized, clearer and more semantic.
The nomenclature follows the following format:
.block{}
.block__element{}
.block--modifier{}
Where:
* `.block` represents a basic abstract element;
* `.block__element` represents a sub-element of `.block` as a whole;
* `.block--modifier` represents a different state of `.block`.
For example:
.person{}
.person--woman{}
.person__hand{}
.person__hand--left{}
.person__hand--right{}
The best thing we describe in this example The basic element is a person, and then that person might be a woman. We also know that people have hands, which are part of the human body, and the hands also have different states, like the left hand and the right hand.
This way we can specify the namespace of the selector based on the parent element and convey the function of the selector, whether it is a child element (`__`) or a different state (`- -`)?
Thus, `.page-wrapper` is an independent selector. This is a standard name, because it is not a child element or other state of other elements; however `.widget-heading` is related to other objects, it should be a child element of `.widget`, so we should use it Renamed to `.widget__heading`.
Although the BEM nomenclature is not pretty and quite verbose, it allows us to quickly learn the functions of elements and the relationships between elements through names. At the same time, the repeated parts in the BEM syntax greatly benefit the gzip compression algorithm.
Whether you use BEM nomenclature or not, you should ensure that classes are named appropriately, with no more words and less words; abstract element naming to improve reusability (e.g. `.ui-list`, `.media`). The naming of elements extending from this should be as precise as possible (for example `.user-avatar-link`). Don't worry about the number or length of class names, as well-written code can be compressed effectively by gzip.
### class in HTML
To ensure readability, use two spaces to separate class names in HTML tags. For example:
The added spaces should make it possible to use multiple class is easier to read and locate.
### JS Hooks
** Never use CSS styles as JavaScript hooks. **Mixing JS behaviors and styles together will make it impossible to treat them separately.
If you want to bind JS to certain tags, write a JS-specific class. Simply put, it is to delineate a namespace with the prefix `.js-`, such as `.js-toggle`, `.js-drag-and-drop`. This means we can bind both JS and CSS via classes without causing trouble due to conflicts.
|
The above tag has two classes. You can use one to add styles to the sortable table column and the other to add the sorting function. < i>colour rather than color, but for the sake of uniformity I think it's better to use the American spelling in CSS. CSS and most other languages are written with American spelling, so there would be a lack of uniformity if you wrote `color:red` in `.colour-picker{}`. I used to advocate using two spellings at the same time, for example:
.color-picker,
.colour-picker{
}
But I recently participated in a large-scale Sass project. There are many color variables in this project (such as `$brand-color`, `$highlight-color`, etc.), each It is very hard to maintain two spellings of a variable, and it takes twice as much work to find and replace.
So for the sake of uniformity, just name all classes and variables with the usual spelling of the project you are involved in.
## Comments
I use block comments with a line width of no more than 80 bytes:
/**
* This is a docBlock style comment
* *
* This is a longer description of the comment, describing the code in more
* detail. We limit these lines to a maximum of 80 characters in length.
*
* We can have markup in the comments, and are encouraged to do so:
*
*
* We do not prefix lines of code with an asterisk as to do so would inhibit
* copy and paste.
*/
/**
* 这是一个文档块(DocBlock)风格的注释。
*
* 这里开始是描述更详细、篇幅更长的注释正文。当然,我们要把行宽控制在 80 字以内。
*
* 我们可以在注释中嵌入 HTML 标记,而且这也是个不错的办法:
*
*
* If it is an embedded markup, do not add an asterisk in front of it, otherwise it will be copied.
*/
You should describe the code in as much detail as possible in comments, because what is clear and understandable to you may not be so to others. Every time you write a part of code, you must write a special comment to explain it in detail.
### Extended usage of comments
Comments have many advanced uses, such as:
* Quasi-modified selector
* Code tags
* Inherited tags
#### Quasi-modified selector
You should avoid over-modifying selectors, for example if you can write `.nav{}` try not to write `ul.nav{}`. Excessive modification of selectors will affect performance, affect class reusability, and increase selector privacy. These are things you should try to avoid.
But sometimes you may want to tell other developers the scope of use of a class. Taking `.product-page` as an example, this class looks like a root container, which may be an `html` or `body` element, but it cannot be determined based on `.product-page` alone.
We can add quasi-modification before the selector (that is, comment out the previous type selector) to describe the scope of our planned class:
/*html*/.product-page{}
This way we can accurately know the scope of the class without affecting reusability.
Other examples are:
/*ol*/.breadcrumb{}
/*p*/.intro {}
/*ul*/.image-thumbs{}
This way we can know the class scope without affecting the privacy of the code.
#### Code tags
If you write a new rule, you can add tags to it, for example:
/**
* ^navigation ^lists
*/
.nav{}
/**
* ^grids ^lists ^tables
*/
.matrix{}
These tags allow other developers to quickly find related code. If a developer needs to find parts related to lists, he can quickly locate `.nav`, `.matrix` and other related parts by searching for `^lists`.
#### Inherited tags
If you apply object-oriented ideas to CSS writing, you can often find two parts of CSS that are closely related (One is the foundation, the other is the expansion) but it is divided into two places. We can use inheritance tags to establish a close connection between the original element and the inherited element. These are written as follows in comments:
In the element's base style:
/**
* Extend `.foo` in theme.css
*/
.foo{}
In the extended style of the element:
/**
* Extends `.foo` in base.css
*/
.bar{}
This way we can establish a close connection between two pieces of code that are far apart.
---
## Writing CSS
The previous chapters mainly discussed how to plan CSS, these are easy-to-quantify rules. This chapter will explore the more theoretical stuff, as well as our attitudes and methods.
## Writing new components
When writing a new component, write the HTML part before working on the CSS. This allows you to accurately determine which CSS properties can be inherited and avoid duplication and waste.
If you write the markup first, you can focus on the data, content and semantics, and then add the required classes and CSS styles.
## Object-oriented CSS
I write code in an object-oriented CSS way. I divide components into structure (objects) and appearance (extensions). Just like the following analysis (note that this is just a note and not an example):
.room{}
.room--kitchen{}
.room--bedroom{}
.room--bathroom{}
We have many rooms in the house and they all have common characteristics: they all contain floors, ceilings, walls and doors. We can put these shared parts into an abstract `.room{}` class. But we also have other rooms that are distinctive: a kitchen might have floor tiles, a bedroom might have carpet, the bathroom might not have a window but the bedroom would, and the walls might be a different color in each room. The idea of object-oriented CSS allows us to abstract the same parts into structural parts, and then use more specific classes to extend these features and add special processing methods.
So instead of writing a large number of special modules, you should try to find the repeated design patterns in these modules and abstract them, write them into a reusable class, and use it as Basic and then write special cases for other expansion modules.
When you are writing a new component, split it into its structure and appearance. When writing the structure part, use the most general class to ensure reusability, and when writing the appearance, use a more specific class to add design methods.
## Layout
Do not declare width for all components, it is determined by its parent element or grid system.
**Definitely don’t** make a statement. Height should only be used for things whose dimensions are already fixed, such as images and CSS sprites. Height should not be declared on `p`, `ul`, `div`, etc. elements. You can write `line-height` if necessary, which is more flexible.
Grid system should be understood as a bookshelf. They contain content, rather than containing themselves as content, just as you build a bookshelf first and then put things in it. Rather than declaring their sizes, treating the grid system separately from other properties of the elements helps with layout and makes our front-end work more efficient.
You should not add any styles to the grid system, they are just for layout. Add styling inside the grille system. Do not under any circumstances add box model related properties in a grid system.
## UI size
I use many methods to set the UI size, including percentage, `px`, `em`, `rem ` and simply use nothing at all.
Ideally, grid systems should be set using percentages. As mentioned above, because I use a grid system to fix column and page widths, I can ignore the size of elements.
I use rem to define the font size, and supplement it with px to be compatible with old browsers. This can combine the advantages of em and px. Below is a very beautiful Sass Mixin. Assuming you declare the base font size (base-font-size) elsewhere, you can use it to generate rem and px compatible with old browsers.
@mixin font-size($font-size){
font-size:$font-size px;
font-size: $font-size / $base-font-size rem;
}
I only use px on elements that have fixed sizes, including pictures and sizes that have been used px Fixed CSS Sprite.
### Font size
I will define some classes similar to the grid system principle to declare the font size. These classes can be used for dual title sizing, please read [Pragmatic, practical font-sizing in CSS](http://csswizardry.com/2012/02/pragmatic-practical-font-sizing-in-css) about this.
## Abbreviation
**CSS abbreviation should be used with caution. **
Writing attributes like `background:red;` is indeed very convenient, but what you mean by writing this is to declare `background-image:none; background-position: top left; background-repeat: repeat; `. Although most of the time this won't cause any problems, if it does happen even once, it's worth considering whether to give up abbreviations. This should be changed to `background-color:red;`.
Similarly, a statement like `margin:0;` is indeed concise and refreshing, but it should still be written as clearly as possible. If you just want to change the `margin` at the bottom, it's best to be more specific and write `margin-bottom:0;`.
In turn, the attributes you need to declare must also be written clearly, and do not affect other attributes because of abbreviations. For example, if you only want to change the bottom `margin`, don't use `margin:0` which will also clear the other margins.
Although abbreviations are a good thing, be careful not to abuse them.
## ID
Before we start working with selectors, keep this sentence in mind:
** Never use ID in CSS. **
In HTML, ID can be used for JS and anchor positioning, but in CSS, you only need to use class, not an ID at all.
The advantage of Class is its reusability, and its degree of privacy is not high. Privacy can easily lead to problems, so it's important to reduce it. The privacy of ID is **255** times that of class, so never use it in CSS.
## Selector
Always keep selectors short and efficient.
Selectors positioned by page element position are not ideal. For example, the positioning of a selector such as `.sidebar h3 span{}` relies too much on relative position, so it is difficult to move the span outside h3 and sidebar and maintain its style.
Selectors with complex structures will affect performance. The more complex the selector structure is (for example, `.sidebar h3 span` is three layers, `.content ul p a` is four layers), the greater the browser's consumption.
Try to make the style independent of its positioning, and try to keep the selector simple and clear.
As a whole, the selector should be as short as possible (for example, only one layer of structure), but the class name should not be too simple, for example `.user-avatar` is far better than `. usr-avt` OK.
**Remember:** Classes don’t matter whether they are semantic or not; focus on whether they are reasonable. Don’t stress about class names being semantic, but focus on using names that are sensible and not outdated.
### Over-modified selectors
As mentioned above, over-modified selectors are not ideal.
An over-modified selector is something like `div.promo`. It's possible that you can get the same effect by just using `.promo`. Of course, you may occasionally need to modify the class with the element type (for example, you wrote an `.error` and want it to display differently in different element types, such as `.error{ color:red; }` `div .error{ padding:14px;}`), but it should be avoided most of the time.
Give another example of an over-modified selector, `ul.nav li a{}`. As mentioned before, we can delete `ul` immediately because we know that `.nav` is a list, and then we can find that `a` must be in `li`, so we can rewrite this selector as` .nav a{}`.
### Selector performance
Although browser performance is improving day by day and rendering CSS is getting faster and faster, you should still pay attention to efficiency. This problem can be avoided by using discontinuous, non-nested selectors, not using global selectors (`*{}`) as core selectors, and avoiding the use of increasingly complex CSS3 new selectors.
Translation note, core selector: The browser parses selectors in order from right to left. The rightmost element is the element where the style takes effect and is the core selector.
## The purpose of using CSS selectors
Rather than trying to use selectors to locate an element, a better way is to directly Add a class directly to the element you want to style. Let’s take a selector like `.header ul{}` as an example.
Assume that this `ul` is the site-wide navigation of this website. It is located in the header and is the only `ul` element in the header so far. `.header ul{}` does work, but it's not a good idea, it's easily outdated, and it's very obscure. If we add another `ul` in the header, it will apply the style we wrote for this navigation part, even if this is not the effect we envisioned. This means that we either have to refactor a lot of code, or write a lot of new styles for the later `ul` to offset the previous impact.
Your selector must fit the reason why you want to style this element. Think about it, "Am I targeting this element because it's a ul under .header, or because it's my site navigation?" This will determine how you should use the selector.
Make sure your core selector is not a type selector, nor a high-level object or abstract selector. For example, you will definitely not find selectors such as `.sidebar ul{}` or `.footer .media{}` in our CSS.
Clear expression: directly find the element you want to style, not its parent elements. Don't assume that HTML won't change. **Use CSS to hit the elements you need directly, rather than opportunistically. **
For the complete content, please refer to my article [Shoot to kill; CSS selector intent](http://csswizardry.com/2012/07/shoot-to-kill-css -selector-intent/)
## `!important`
Only use `!important` on auxiliary classes. You can also use `!important` to increase the priority. For example, if you want a certain rule to be valid **always**, you can use `.error{ color:red!important; }`.
Avoid using `!important` actively. For example, don’t use it as a shortcut when writing complex CSS. Clean up and refactor the previous parts, keep selectors short and avoid using IDs to overwhelm others.
## Magic Number and Absolute Positioning
Magic Number refers to those numbers that "happen to have an effect". Very bad, because they only treat the symptoms but not the root cause and lack scalability.
For example `.dropdown-nav li:hover ul{ top:37px; }` It is far from a good idea to move the dropdown menu down, because 37px here is a magic number. The reason why 37px takes effect is because `.dropbox-nav` happens to be 37px high at this time.
At this time you should use `.dropdown-nav li:hover ul{ top:100%; }`, that is, no matter how high `.dropbox-down` is, this drop-down menu All will move down 100%.
Whenever you are about to put numbers in your code, think twice. If you can replace it with a keyword (e.g. `top:100%` which means "pull from top to bottom"), or if there is a better solution, try to avoid direct numbers.
Every number you leave in CSS is a promise you make but don’t want to keep.
## Conditional judgment
Styles written specifically for IE can basically be avoided. The only thing that needs to be specially processed for IE is In order to handle content that IE does not support (such as PNG).
In short, if you refactor CSS, all layouts and box models don’t need to be extra compatible with IE. In other words, you basically don’t need `` or similar IE-compatible writing methods.
## Debugging
If you want to solve CSS problems, **take out the old code first and then write new**. If there's a problem in old CSS, writing new code won't fix it.
Delete the CSS code and HTML until there are no bugs, and then you will know where the problem lies.
Sometimes writing an `overflow:hidden` or other code that can hide the problem has an immediate effect, but the overflow aspect may not be a problem at all. Therefore, it is necessary to treat the root cause rather than simply treating the symptoms.
## Preprocessor
I use Sass. You should use it **flexibly** when using it. Use Sass to make your CSS more powerful, but don’t make it too complex. In vanilla CSS, only use nesting where necessary, for example:
.header{}
.header .site-nav{}
.header .site-nav li{}
.header .site-nav li a{}
This writing method is completely used in ordinary CSS Less than. The following is **bad** Sass writing:
.header{
.site-nav{
li{
Write:
.header{}
.site-nav{
li{}
a{}
}
Statement:The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn