In front end development, there has always been a principle called “separation of concerns”, which means that technologies are only in their own domain and don’t mix and couple. This principle is straightforward: don’t write inline style and inline script. Keep HTML, CSS, and JavaScript separate and avoid mixing (see introduction to CSS in JS here)
Now, due to the use of various front-end frameworks and packaging tools, our previous separation of concerns has changed into a strategy that is actually implemented in JS.
The framework doesn’t have any special treatment for CSS compared to HTML, and it doesn’t have a JSX-like solution, but there is one interesting solution: CSS-in-JS (although writing CSS in JS feels awkward anyway).
In addition CSS itself programming ability is weak, the community has formed a variety of programs to improve CSS programming ability. I find Postcss more elegant than the others, so I’m going to highlight it here
It is currently based on PostCSS 7.0.32
The basic concept
- Postcss is a tool for converting CSS using JS plug-ins
- Postcss is not a preprocessor
Preprocessor refers to the enhancement of CSS capabilities by adding some non-CSS functions (such as nesting and variables), which can be converted into ordinary CSS after processing.
- Postcss is not a post-processor
Improve existing CSS with rules such as adding browser prefixes
- Postcss exists as a platform. Plug-ins provided by Postcss can combine various modules to build more complex functions
Demo
- Any directory NPM init -y
In this way, the name of the project must not conflict with the name of the library, such as webpack, postCSS, which will cause ENOSELF errors when installing the related library
- Installation-dependent dependencies
- Css-loader is the ability to import CSS using import in a page
- Style-loader uses CSS code to generate style tags and place them in the head tag
- Mini-css-extract-plugin Plugin used to extract CSS
npm i –save-dev webpack webpack-cli webpack-dev-server html-webpack-plugin mini-css-extract-plugin css-loader style-loader @babel/cli @babel/core @babel/preset-env vue-loader vue-template-compiler
npm i –save vue
- Create two new folders
src
、dist
, as well asbabel.config.js
,webpack.config.js
And other relevant documents
/// babel.config.js const presets = [["@babel/env"]]; module.exports = { presets } ... /// webpack.config.js const HtmlWebpackPlugin = require('html-webpack-plugin'); const VueLoaderPlugin = require('vue-loader/lib/plugin'); module.exports = { entry: './src/index.js', resolve: { extensions: ['.js', '.vue'] }, output: { filename: '[name].js', publicPath: '/' }, mode: 'development', module: { rules: [ {test: /\.js$/, use: 'babel-loader', exclude: /node_modules/}, {test: /\.vue$/, use: 'vue-loader', exclude: /node_modules/}, {test: /\.css/, use: ['style-loader', 'css-loader']} ] }, devServer: { port: '8111' }, plugins: [ new HtmlWebpackPlugin({ template: './src/tpl/index.html' }), new VueLoaderPlugin() ] } ... /// suppose there is an app.vue set as above import '.. /style/app.css';Copy the code
At this point in the JS file, you can import the style file into the page through import. However, since style-loader is used, the style will be written to the
The mini-CSs-extract-plugin can be used, which splits related styles into separate files
/// webpack.config.js const MiniCssExtractPlugin = require("mini-css-extract-plugin"); . {test: / \. CSS /, use: [MiniCssExtractPlugin loader, 'CSS - loader]} / / replace style - loader... plugins: [ ... new MiniCssExtractPlugin({ filename: "[name].css", chunkFilename: "[id].css" }) ]Copy the code
If multiple style files are imported, they will be merged into a single style file and exported as currently set. The contents of these files, however, are simply merged together, and it is entirely up to the style writer to control the contents of each style file
/// app.css .info { font-size: 24px; }... /// color.css .info { color: red; }... /// app.vue import '.. /style/app.css'; import '.. /style/color.css'; . /// The merged style file is as follows. Info {font-size: 24px; } .info { color: red; }Copy the code
BianChengHua
Install related dependencies
npm i -D postcss postcss-loader
Introduce style files through.pcss
. PCSS is a special format file of Postcss
- The installationpostcss-importTo make the
.pcss
Files can be used@importImporting style files
npm i -D postcss-import
You need to add a running configuration file for Postcss, either.postcsrc. Js or postcss.config.js
Module. exports = {plugins: []}Copy the code
postcss.config.js
In addition toplugins
It also has the following parameters:- Syntax: Object that provides a parser and a stringalizer
- Parser: a special syntax parser (e.g., SCSS)
- 2. A specialized syntax output generator (such as Midas).
- Map: Sets the map file
- From: Enter the file name
- To: Indicates the output file name
However, plugins are commonly used.
{test: /\.pcss$/, use: [ MiniCssExtractPlugin.loader, "css-loader", "postcss-loader" ]}, ... /// mian.pcss @import './app.css'; @import './color.css'; . /// app.vue imports main. PCSS import './main. PCSS ';Copy the code
The PostCSS, for example, is different from the Lass Sass stylus in that it has a self-configuration process, so it has a higher degree of freedom. These gaps can be written yourself, or you can directly use existing community plug-ins that set usage parameters in the PostCSS configuration file
Related to the plug-in
autoprefixer
This is probably the most widely used plugin in PostCSS, automatically recognizing the browser compatibility range and adding the browser style prefix
npm i -D autoprefixer
/// postcss.config.js
let postcssConfig = {};
postcssConfig.autoprefixer = {
browsers: ['> 1%', 'ff 3']
}
module.exports = {
plugins: postcssConfig
}
Copy the code
- Modify main. PCSS as follows
b {
border-radius:5px;
}
Copy the code
The result after compiling and running is
b {
-moz-border-radius:5px;
border-radius:5px;
}
Copy the code
For autoprefixer parameters, use the default Settings. Only the browsers parameter Settings are spoken here because these relate to what is ultimately prefixed.
browsers
Browsers use the Browserslist function to decide whether certain browser prefixes need to be added. Browsers are built with the browserslist documentation. You can set Settings for browser, country, specific platform, and year
> 5% cover 99.5% in US node 10 and node 10.4 since 2015 IE 6-8 not IE <= 8Copy the code
Here’s a list of browsers you’re most likely to encounter on your project
- Android: Android WebView browser
- IOS: Safari on iOS
- Chrome: Google browser
- ChromeAndroid: Google chrome for android
- Edge: Microsoft’s Edge browser
- Internet Explorer: Indicates the Internet Explorer
- Safari: Safari desktop browser
- Ff: Firefox browser
- And_ff: Firefox Android browser
- And_qq: Android version of QQ browser
- And_uc: Android version of UC browser
Browsers accept an array, so can be set separately as in the example. The following means that browsers add prefixes to fit android 2.3, ios3.2, Safari3.1, and IE10
‘> 0%’, ‘the Android 2.3’, ‘iOS 3.2’, ‘Safari 3.1’, ‘Internet explorer 10’
-
> 0% : indicates that when you do not want to set up so tedious to specify the browser, you can directly specify a approximate, is I want to support the market what proportion of browsers, this number can be added before the ordinary operators >, >=, <, <=
-
The prefix modifier NOT: indicates that it is not in a range, and you can use cover extends or since for more detailed Settings, including the path specifying what version from what year.
The rounded corners function is only added to FF4. The preceding configuration has the prefix for a specific browser because it is specified for a specific browser version
/// With this set, the resulting styles are not prefixed with Firefox browsers: ['> 1%', 'ff > 4'].Copy the code
When setting a range, you need to specify the range. Do not set ff or not ff directly, because this will cause errors. You need to specify the version
Set browserslist in package.json
In the current version, this setup runs WebPack with a section warning that it is not recommended to set the browser scope in the configuration file. Either add it to package.json or set it to.browserslistrc
/// .browserslistrc > 1% ff > 4 ... Json "browserslist": ["> 1%", "ff > 4"] // This priority is lower than the plugin settingCopy the code
postcss-preset-env
This plugin allows developers to use new features that may be added to future versions of CSS in their current projects, much like writing ES6+ code, but using Babel to convert ES5 code.
Autoprefixer is included in this plugin, and a similar plugin, PostCSS-CssNext, is no longer maintained
npm i –save-dev postcss-preset-env
const PostCssEnv = require("postcss-preset-env");
const postCssEnvConfig = PostCssEnv({
stage: 2
});
module.exports = {
plugins: [postCssEnvConfig]
};
Copy the code
Plug-in Parameters
The following describes related parameters based on the official documents:
-
stage: According to the process of the current web standards (mainly is accredited by the w3c standard, so has the function of the in the plug-in are future is likely to be directly added to the contents of the CSS standard) to determine some CSS function need not to need to add, by means of shim can set any number of the 0 ~ 4, without setting this value, This value defaults to 2
- 0: At this stage
Unofficial draft or editorial draft stage
, will most likely be deleted - 1: This stage is in
The experimental stage
, may be set as standard - 2: This stage is in
Pending phase
This is also the default value of the plugin. Features at this stage can be expected to be added to the future standard - 3: This stage is in
Stable phase
, basically has been implemented by browser vendors, can be used directly - 4: This stage is in
The standard stage
- 0: At this stage
-
Features: Sets specific CSS functionality separately. For example, if stage is set to 3, you can use this parameter to specify functionality that is stage 2
PostcssPresetEnv ({/* Uses the standard of stage 3, while allowing nesting rules (nesting is standard for stage 1) */ stage: 3, features: {'nesting-rules': true}})Copy the code
-
Browsers: Do not set this parameter by referring to the introduction of Browserslist above
-
InsertBefore/insertAfter: Allows you to run one or more plug-ins before or after the plug-in runs
import postcssSimpleVars from 'postcss-simple-vars'; PostcssPresetEnv ({insertBefore: {'all-property': postcssSimpleVars}})Copy the code
- Autoprefixer: Set to false to disable autoprefixer. The Autoprefixer and Browsers included with the plug-in can be set here, but are usually built with the default
Const postCssEnvConfig = PostCssEnv({stage: 2, autoprefixer: {} // Blank is used by default. The default is autoprefixer, browsers are all turned on});Copy the code
- Preserve: Determines whether all plug-ins should receive the same Preserve option, which can preserve or remove CSS populated in other ways
Use custom selectors in the style file @custom selectors :--heading H1, H2, H3, h4, h5, h6; article :--heading + p { color: red; }... @custom-selector :--heading H1, H2, h3, h4, h5, h6; article h1 + p,article h2 + p,article h3 + p,article h4 + p,article h5 + p,article h6 + p { color: red; } article :--heading + p { color: red; }... /// When set to false, Article h1 + p,article h2 + p,article h3 + p,article h4 + p,article h5 + p,article h6 + p {color: red; }Copy the code
- ImportFrom: Import related variable information (such as custom media, custom properties, custom selectors, and environment variables) from an external source, which can be CSS, JS, or JSON (functions and direct object values are also supported). This feature is perfectly fine
/// style/theme.css @custom-media --small-viewport (max-width: 30em); @custom-selector :--heading h1, h2, h3, h4, h5, h6; :root { --color: red; }... PostCssEnv({ ... ImportFrom: "SRC /style/theme. CSS"Copy the code
If the postcss.config.js configuration is used, in the Node runtime environment, you can determine the most basic variable parameters according to the runtime ENV and some of the parameters you set, easily implement the function of skin
- ExportTo: Export related variables as opposed to importFrom (this should encourage us to keep variables in a common file for easy maintenance)
Stage 2 and above CSS syntax
Is to enable the default configuration of the CSS syntax can be used directly
all
Used to reset all properties [stage 3, numeric abbreviation below]
A {all: initial; }Copy the code
value | describe |
---|---|
initial | Modifies the values of all element attributes or parent elements to their initial values |
inherit | Modify all element attributes or parent element values to their parent element values |
unset | Modify all element attributes or parent element values to parent element values (if inherited) or their initial values |
:any-link
CSS pseudo-class selector will match:link
或:visited
[2]
Nav: any-link> span {background-color: yellow; }... // compile to nav :link > span,nav :visited > span {background-color: yellow; }Copy the code
- Break property: Property used to define interrupt behavior in a multi-column layout [3]
- Break-inside: describes how a content box breaks under a multi-column layout page
- Break-after: Describes the break behavior of a page, column, or region after the generated box
- Break-before: Describes how the column or region should handle interrupts before generating boxes
- Case-insensitive Attributes: Defining attribute selectors case-insensitive [2]
[title="hs" i] { border-style: solid none; }... /// convert to all possible combinations, use less. Conversion of too much [title = "hs"], [the title = "hs"], [the title = "hs"], [the title = "hs"] {border - style: solid none; }Copy the code
- Custom Properties: Used to define variable values accepted by CSS properties [3]
Img {--some-length: 32px; img {--some-length: 32px; height: var(--some-length); width: var(--some-length); }Copy the code
:dir(rtl|ltr)
Elements matching a specific writing direction are not of concern to Chinese language families [2]- Double-position-gradients: gradients [2]
.pie_chart {
background-image: conic-gradient(yellowgreen 40%, gold 0deg 75%, #f06 0deg);
}
Copy the code
Others include Linear Gradients, Radial Gradients
:focus-visible
Focus of elements triggered by keyboard access (selecting elements by tabbing) [2]
Outline: none; outline: none; outline: none; outline: none; outline: none; outline: none; outline: none; }. Name: focal-visible {// Outline: #00ff00 dotted thick; }... /// DOM <div class="name" tabindex="0">name</div>Copy the code
When you click on the element on the page with the mouse, you will have a different experience than when you switch with the TAB key. Mouse click because the outline is set to None, so you can see nothing. However, when tab-toggling elements, there is an obvious border around them, which is a great help in improving accessibility.
The postCSS-focus-visible plugin is used internally. The plugin author assumed that Polyfill was needed to solve the compatibility problem, so if you write the relevant style code in the.pcss file, .name:focus-visible becomes.name. Focus-visible. To avoid this conversion, put the relevant code in a.css file
:focus-within
The current element or children of the current element are in focus state [2]
.tab-content:focus-within { background: #f00; }... /// If you have a DOM element tag in the page, follow the style code above, as soon as the input gets focus, the whole area will turn red. <div class="tab-content"> <input placeholder=" Please input your name "type="text" /> </div>Copy the code
- Font-variant: A font with small uppercase letters that displays text. This means that all lowercase letters are converted to uppercase letters, but all letters with small uppercase fonts are smaller than the rest of the text. Another attribute that is not useful for The Chinese area [3]
- Gap properties [3]
This property is used to set gutters between Grid rows and columns, which is short for row-gap and column-gap, a concept in a Css Grid
.grid-1 { gap: 20px; } .grid-2 { column-gap: 40px; row-gap: 20px; }... Grid-1 {grid-gap: 20px; } .grid-2 { grid-column-gap: 40px; grid-row-gap: 20px; }Copy the code
gray()
: Function for specifying fully desaturated colors [2]
p { color: gray(50); }... /// convert to p {color: RGB (119,119,119); }Copy the code
- Alpha: Hexadecimal color notation is 1/2 more characters than the usual 3/6 notation, and transparency can be specified [2]
section { background-color: #f3f3f3f3; color: #0003; }... /// convert to section {background-color: rgba(243,243,243,0.95294); Color: rgba (0,0,0,0.2); }Copy the code
lab()
Use LAB for color [2]lch()
Use LCH for colors [2]hwb()
Use HWB for colors [2]
color: lch(53 105 40);
color: lab(240 50 20);
color: hwb(120 44% 50%);
Copy the code
Generally these colors are used more in the field of design or typography, and the front end is generally RGB RGBA
- Image-set () : reference different image sources according to user resolution [2]
.foo { background-image: image-set( "https://www.baidu.com/img/flexible/logo/pc/[email protected]" 1x, "https://www.baidu.com/img/flexible/logo/pc/[email protected]" 2x, "https://www.baidu.com/img/flexible/logo/pc/[email protected]" 600dpi ); }... // become .foo { background-image: https://www.baidu.com/img/flexible/logo/pc/[email protected]; } @media (-webkit-min-device-pixel-ratio: 2), (min--moz-device-pixel-ratio: 2), (min-resolution: 192dpi){ .foo { background-image: https://www.baidu.com/img/flexible/logo/pc/[email protected]; }} @media (-webkit-min-device-pixel-ratio: 6.25), (min--moz-device-pixel-ratio: 6.25), (min-resolution: 600dpi){ .foo { background-image: https://www.baidu.com/img/flexible/logo/pc/[email protected]; }}Copy the code
- Logical Properties of CSS [2]
*-start, *-end, *-inline-start, *-inline-end, *-block-start, *-block-end, *-inline-start, *-block-end, *-inline-start, *-block-end This is opposed to a property like padding-left that has a clear direction. This CSS logical property has a number of values, as described in the W3C standard
p:first-child { float: inline-start; margin-inline-start: 10px; Margin-left} margin-left} margin-left} margin-left}Copy the code
Margin-inline and margin-block are CSS logical properties. The former is short for margin-inline-start and margin-inline-end. The latter is short for margin-block-start and margin-block-end. Margin-inline refers to horizontal margin control, while margin-block refers to vertical margin control
:matches
Matching pseudo-classes, multiple property values can be set at once [2]
p:matches(:first-child, .special) { margin-top: 1em; }... p:first-child, p.special { margin-top: 1em; }Copy the code
:not
Reject pseudo classes, setting out of current range [2]
p:not(:first-child, .special) { margin-top: 1em; }... p:not(:first-child):not(.special) { margin-top: 1em; }Copy the code
- Define the scope of media queries in a more understandable way [3]
@media (width < 480px) {b {font-size: 14px}} @media (480px <= width < 768px) {// 18px} } @media (width >= 768px) { b { font-size: 20px} } ... @media (max-width: 479px) { b { font-size: 14px; } } @media (min-width: 480px) and (max-width: 767px) { b { font-size: 18px; } } @media (min-width: 768px) { b { font-size: 20px; }}Copy the code
overflow
foroverflow-x
和overflow-y
The shorthand [2]
html { overflow: hidden auto; }... html { overflow-x: hidden; overflow-y: auto; }Copy the code
overflow-wrap
Sets or retrieves line breaks when content exceeds the bounds of the specified container [2]- Normal: Allows content to overshoot or overflow specified container boundaries.
- Break-word: The content will be wrapped within the boundary. Line breaks are allowed inside words if necessary.
CSS3 renamed word-wrap to overflow-wrap; So this will monitor your browser’s compatibility range, and the lower version browsers will synchronize overflow-wrap values to word-wrap
- The CSS in the grid
place-
Short form of attribute [2]place-items
Attributes arealign-items
Properties andjustify-items
The merged short form of a propertyplace-content
Attributes arealign-content
Properties andjustify-content
The merged short form of a propertyplace-self
Attributes arealign-self
Properties andjustify-self
The merged short form of a property
.example { place-content: flex-end; place-items: center / space-between; place-self: flex-start / center; }... .example { -ms-flex-line-pack: end; align-content: flex-end; -webkit-box-pack: end; -ms-flex-pack: end; justify-content: flex-end; -webkit-box-align: center; -ms-flex-align: center; align-items: center; justify-items: /, space-between; -ms-flex-item-align: start; align-self: flex-start; justify-self: /, center; }Copy the code
- Rebeccapurple a special color value [2]
HTML {color: rebeccapurple; / / # 663399}Copy the code
- System-ui matches universal fonts [2]
body {
font-family: system-ui;
}
Copy the code
CSS syntax for Stage 1
Since stage is set to 2, if you want to enable syntax that requires stage 1, enable it in the Features configuration. You can click the relevant API to check the hash corresponding to the URL, such as https://preset-env.cssdb.org/features#custom-media-queries, The corresponding ID is custom-media-queries. If the ID is not the same as the GIthub JS file, you can query it in the github JS file
postcssPresetEnv({
stage: 2,
features: {
'nesting-rules': true,
'custom-media-queries': true,
'custom-selectors': true
}
})
Copy the code
- Custom-media-queries (Correlation ID)
- Custom media query
@custom-media --small-viewport (max-width: 30em); @media (--small-viewport) { h1 {font-size: 16px} } ... Max-width: 30em) {h1 {font-size: 16px}}Copy the code
The maximum and minimum width can be >= <= instead
@custom-media --small-viewport (width >= 500px) and (width <= 1200px); @media (--small-viewport) { h1 {font-size: 16px} } ... // Convert @media (min-width: 500px) and (max-width: 1200px) {h1 {font-size: 16px}}Copy the code
- custom-selectors
- Custom selectors
The CSS Extensions specification allows the creation of custom selectors, which can be defined using @custom-Selector
@custom-selector :--heading h1, h2, h3, h4, h5, h6;
:--heading {
font-weight: bold;
}
Copy the code
After running into
h1,h2,h3,h4,h5,h6 {
font-weight: bold;
}
Copy the code
- nesting-rules
- Nesting, to reduce duplicate selector declarations, is done in two ways: the first way requires nested style declarations to be used
&
As a prefix,&
Can only be used as the starting position of a declaration; The second style declaration is used@nest
As a prefix, and&
It can appear anywhere
- Nesting, to reduce duplicate selector declarations, is done in two ways: the first way requires nested style declarations to be used
// Nesting can only start with &, unless prefixed with @nest. message {font-weight: normal; & .header { font-weight: bold; } @nest .body & { color: black; }}... .message { font-weight: normal } .message .header { font-weight: bold; } .body .message { color: black }Copy the code
- prefers-color-scheme-query
- Query media in dark mode
- Light Theme
- Dark theme
- Query media in dark mode
body { background-color: white; color: black; } @media (prefern-color scheme: dark) {body {background-color: black; color: white; }}Copy the code
cssnano
The version of webpack4+, which already integrates cssnano, is automatically enabled when mode is set to production mode
npm install –save-dev cssnano
Module. exports = {plugins: [require('cssnano')({preset: 'default',}),],};Copy the code
Implement a SASS using PostCSS
Postcss can define the use of related plug-ins, combine functions suitable for their own use, with postCSS plug-ins to achieve a class SASS (general function)
Introduction to related plug-ins
- postcss
- Basic Feature Pack
- postcss-cli
- Provides terminal operation capability
- postcss-advanced-variables
- Provides nesting similar to sass
Variables, @if, @else, @for, @each, @mixin, @include, @content
- Provides nesting similar to sass
- postcss-scss
- Sass can be used normally
#{$var-name}
Variable form
- Sass can be used normally
- postcss-apply
- postcss-assets
- postcss-import
- Make it possible to import in a file using @import
.pcss
file
- Make it possible to import in a file using @import
- postcss-preset-env
@import
Use the postCSs-import plug-in
const atImport = require("postcss-import");
module.exports = {
plugins: [
atImport(),
Copy the code
Elements nested
Use nesting-rules in the postCSS-preset-env plug-in stage:1
const PostCssEnv = require("postcss-preset-env");
const postCssEnvConfig = PostCssEnv({
stage: 2,
features: {
"nesting-rules": true
}
});
Copy the code
It’s a little different than sASS nesting, but it’s the future CSS standard, and it’s the main one
Variables, @if, @else, @for, @each, @mixin, @include, @content
Use postcss – advanced – variables this plug-in, this plug-in can achieve the function of sass variable most, but a special syntax # {$var – name} need to use the plug-in postcss – SCSS, And set parser to postCSs-scss in postcss.config.js
const advanced = require("postcss-advanced-variables");
module.exports = {
parser: "postcss-scss",
plugins: [
advanced(),
...
Copy the code
variable
$the font - size: 1.25 em. $font-stack: "Helvetica Neue", sans-serif; $primary-color: #333; body { font: $font-size $(font-stack); color: #{$primary-color}; }... Font: 1.25em "Helvetica Neue", sans-serif; color: #333; }Copy the code
@ the if, @ the else
$type: monster; p { @if $type == ocean { color: blue; } @else { color: black; }}... P {color: black}Copy the code
@for
@for $i from 1 through 5 by 2 { .width-#{$i} { width: #{$i}0em; }}... // convert to.width-1 {width: 10em; } .width-3 { width: 30em; } .width-5 { width: 50em; }Copy the code
@each
@each $animal in (red, yellow, black, white) { .#{$animal}-icon { color: #{$animal}; }}... // convert to.red-icon {color: red; } .yellow-icon { color: yellow; } .black-icon { color: black; } .white-icon { color: white; }Copy the code
@mixin @include
@mixin heading-text { color: #242424; font-size: 4em; } h1, h2, h3 { @include heading-text; }... // turn to h1, h2, h3 {color: #242424; font-size: 4em; }Copy the code
Attributes are nested
postcss-nested-props
const nestedProps = require("postcss-nested-props");
module.exports = {
plugins: [
nestedProps(),
Copy the code
.funky { font: { family: fantasy; size: 30em; weight: bold; }}... // convert to.funky {font-family: arial; font-size: 30em; font-weight: bold }Copy the code
Extend/Inheritance(Extend/ inherit)
postcss-extend
const extend = require("postcss-extend");
module.exports = {
plugins: [
extend(),
Copy the code
@define-placeholder message-shared {border: 1px solid # CCC; padding: 10px; color: #333; } .message { @extend message-shared; } .error { border: 1px #f00; background-color: #fdd; } .seriousError { @extend .error; border-width: 3px; }... Message {border: 1px solid # CCC; // convert to.message {border: 1px solid # CCC; padding: 10px; color: #333; } .error, .seriousError { border: 1px #f00; background-color: #fdd; } .seriousError { border-width: 3px; }Copy the code
Add calc() calculation
postcss-calc
const calc = require("postcss-calc");
module.exports = {
plugins: [
calc(),
Copy the code
@mixin columns_calc($count) { width: calc(100% / $count); @if $count > 1 { float: left; } } .column_calculated { @include columns_calc(2); }... // Change to.column_calculated {width: 50%; float: left; }Copy the code
With these plug-ins, normal development needs are almost completely met
The complete configuration is as follows:
const PostCssEnv = require("postcss-preset-env");
const AtImport = require("postcss-import");
const advancedVariables = require("postcss-advanced-variables");
const nestedProps = require("postcss-nested-props");
const extend = require("postcss-extend");
const calc = require("postcss-calc");
const postCssEnvConfig = PostCssEnv({
stage: 2,
features: {
"nesting-rules": true
}
});
module.exports = {
parser: "postcss-scss",
plugins: [
AtImport(),
advancedVariables(),
nestedProps(),
extend(),
calc(),
postCssEnvConfig
]
};
Copy the code
Use PostCSS independently
You can build a standalone CSS processing platform using the postCSs-CLI plug-in by adding the following commands to package.json
"scripts": {
"build:pc": "npx postcss src/main.pc.css -o dist/main.pc.css",
"build:h5": "npx postcss src/main.h5.css -o dist/main.h5.css"
Copy the code
// src/main.pc.css
@import 'normalize.css';
@import 'reset.css';
@import 'variables.css';
@import 'common.css';
@import 'common.mixin.css';
@import 'layout.mixin.css';
@import 'layout.css';
@import 'layout-flex.css';
@import 'button.mixin.css';
@import 'button.css';
@import 'button-group.css';
@import 'skeleton.mixin.css';
@import 'skeleton.css';
@import 'breadcrumb.css';
@import 'dropdown.css';
@import 'menu.css';
@import 'pagination.mixin.css';
@import 'pagination.css';
@import 'step.css';
@import 'checkbox.css';
@import 'cascader.css';
@import 'form.css';
@import 'calendar.css';
@import 'input-number.css';
@import 'rate.css'
Copy the code
There is a unified entry file that controls the output of different style sheets for PC and H5. In the entry file, you can set different variables to be introduced (such as the variable.css in the example above). CSS (variables.pc. CSS or variables.orange. CSS) to make skin classes easier to implement
Avoid compiler errors on PCSS files
I use vscode, which refers to the style written after the plug-in, and the compiler basically does not know, will give you an error, so here is how to avoid PCSS error, other compilers should have a similar method
Add support for.pcss files to vscode
- Install the postCSs-Sugarss-language plug-in
- Go to Setting, search for files.associations, and open settings.json to add the following content
"Files. associations": {"*.css": "postcss"}, "postcss.validate": false // Avoid checker.pcSSCopy the code
css module
CSS Module and CSS in JS are both solutions proposed by the community for CSS scope. In the actual development process, we feel that CSS Module is more suitable for the requirements of division of labor and cooperation.
In development today, no matter what framework you use, the basic flow is probably the same: do static pages first, then dynamic data. Two lines of work can easily be formed here: one is dedicated to refactoring and interacting with designers to achieve visual implementation; The other is dedicated to connecting business needs with the product manager and the back end (large companies will split into two jobs, small companies will do it all, but the work scene is mostly the same).
CSS in JS is more in line with the encapsulation of independent components. Everything from style and logic to content presentation is implemented in a SINGLE JS, without the need to import other files, which is great if you are writing UI components.
However, if it is a normal development requirement, you use this way, it means that the changes and fixes of style problems and the implementation of business logic are all carried out in a file, which is not conducive to the division of labor.
Personally, CSS in JS makes JS files confusing and less readable. And there is no way to export style files separately, no way to drop style files under a CDN server. It also affects component reusability. To reuse a component (business component) means to accept the component’s own style. If you change the dot size or color, add a separate receive parameter, or create a new component (list-red, for example). It is perfectly possible to add an outer layer of this component like
, which is controlled directly in the outer style file, and can easily be extended to multiple different styles, skins, etc.).
CSS also not friendly to reconstruct personnel in js, before they check style problem, directly modify the style file can see after deployment problem can be solved, now need to modify the js files such as js files to see if changes can take effect after deployment (if refactoring branches and development branch is different, you release a different situation, This can get messy…)
To enable the
Refer to the CSS Modules tutorial
With CSS-Loader, set the following parameters in the WebPack configuration item:
{test: / \. PCSS /, use: [MiniCssExtractPlugin loader, 'CSS - loader? Modules',' postcss - loader]}.Copy the code
This opens up the CSS Module, whose use will change the corresponding style name into a regular, but unexpected, name, such as
{border-radius:5px;} /// main.pcss /// since the style file itself does not require.classname to be repeated, so make sure that you do not repeat it, otherwise there will be problems with the same classname for multiple variable names. } .info { color: red; font-size: 24px; }... /// app.vue <template> <div :class="$style.info">{{ msg }}</div> </template> import style from '.. /style/main.pcss'; . computed: { $style () { return style; }}Copy the code
$style is a reference to vue-Loader’s CSS Modules scheme. Vue loader uses the $style calculation property to inject CSS Modules local objects into components
Style will print (value is a dynamic value)
{box: "_2sI8WybUY_1NGPVWmXjdbV", info: "_hA0iOLbXZy9PpOuCjpkc"}
Copy the code
The name of the style that is directly used in the component is automatically replaced by these names, and the style file is automatically converted to these names. This can solve the problem of CSS style conflict (pollution), the problem of global pollution, and also can solve the problem of dependency. Components only need to introduce their own related styles. Define the styles you want to use in the related styles file, and then use the $style for the related components.
Vue is a bit more cumbersome to write (it’s easier if you use JSX), but you can use it directly if you use React
import style from '.. /style/main.css'; class App extends Component { render () { return <div className={style.info}>app info</div> } }Copy the code
Global scope
In the imported style file, all styles are converted by default. If your style is intended to be used in a generic way, there are two options:
- Only for
.pcss
opencss module
..css
Don’t open
/// webpack.config.js {test: /\.css/, use: [MiniCssExtractPlugin.loader, 'css-loader']}, {test: /\.pcss/, use: [MiniCssExtractPlugin.loader, 'css-loader?modules', 'postcss-loader']} ... /// global.css body { font-size: 18px; background: #cccccc; }... /// app.vue import '.. /style/global.css'; import style from '.. /style/main.pcss'; // This is a separate import, but will eventually merge with a style file... /// main. CSS export style file body {font-size: 18px; background: #cccccc; } ._2sI8WybUY_1NGPVWmXjdbV { border-radius:5px; } ._hA0iOLbXZy9PpOuCjpkc { color: red; font-size: 24px; }Copy the code
- Used in the style file to be compiled
:global(.className)
(Can also be omitted:global .className
), so that the corresponding style does not compile
:local allows you to set what needs to be converted, since the default is conversion, there is no need to add another layer to indicate that it needs to be converted
** For conversions, always use.classname instead of id **
/// main.pcss
...
:global(body) {
font-size: 18px;
background: #cccccc;
}
Copy the code
The two methods are relative, I feel the first one is better
Composing and Importing
- The point of composition is not to mix style code, but to use the name of the combined class, including its subclasses when referenced
.box { border-radius:5px; } .info { color: red; font-size: 24px; } .foo { composes: box; composes: info; padding: 10px; } /// The corresponding JSON information after conversion is as follows: box: "src-style-main__box--2sI8W", info: "src-style-main__info--_hA0i", foo: "Src-style-main__foo --LiN2X src-style-main__box--2sI8W src-style-main__info--_hA0i", /// if we used $style.foo would also include the contents of the other two subclassesCopy the code
composes
It is also possible to import styles from other style modules for composition, which is used in a way that does not include blended classes synchronously.
.foo {
composes: main-title header-title from './color.css';
padding: 10px;
}
Copy the code
@value
There are many solutions to CSS variables. This is the CSS-loader solution, and it can only be used when CSS modules are enabled
There are official naming suggestions: V-define value, S-selector m-define media rule
@value v-primary: #BF4040; @value s-black: black-selector; @value m-large: (min-width: 960px); .header { color: v-primary; padding: 0 10px; } :global .s-black { color: black; } @media m-large { .header { padding: 0 20px; }}... ._2Q-2IY8XIGQEwnpoQr8qIF { color: #BF4040; padding: 0 10px; } .black-selector { color: black; } @media (min-width: 960px) { ._2Q-2IY8XIGQEwnpoQr8qIF { padding: 0 20px; }}Copy the code
Custom compiled class name
The default csS-loader hash algorithm is [hash:base64], and the output is this _2sI8WybUY_1NGPVWmXjdbV. The converted name can be customized
Loader: 'css-loader', options: {modules: {localIdentName: '[path][name]__[local]--[hash:base64:5]'}Copy the code
On official advice
- Development environment Usage
[path][name]__[local]--[hash:base64:5]
- Use in production environment
[hash:base64]
The resulting class name is similar to src-style-main__box–2sI8W, which allows you to see the path and use modules to locate style problems
CSS loader parameters
The name of the | type | The default | describe |
---|---|---|---|
url | {Boolean|Function} | true | Enable/disable the URL () function |
import | {Boolean|Function} | true | Enable/disable @import processing |
modules | {Boolean|String|Object} | false | Enable/disable CSS Modules and related configurations |
sourceMap | {Boolean} | false | The map function was enabled or disabled |
importLoaders | {Number} | 0 | How many loaders to use before CSS-loader (default, do not touch this value, use loader in the order set in Webpack) |
localsConvention | {String} | ‘asIs’ | Key rule corresponding to the exported JSON |
onlyLocals | {Boolean} | false | It affects the loader sequence during packaging. You can set this value in some SSR scenarios, but do not use it in general cases |
esModule | {Boolean} | false | Whether to enable es Module |
url
/ / / install url - loader processing image first, and add the relevant configuration information {test: / \. (PNG | SVG | JPG jpeg | | GIF) $/, use: "url - loader"},... /// main.pcss .foo { color: red; font-size: 14px; background: url(".. /image/timg.jpeg"); // Set the background}Copy the code
If you do this, the converted CSS will process the image, but if you set this value to false
{loader: "CSS-loader ", options: {modules: true, url: false // This value defaults to true}},Copy the code
The converted CSS does not process the URL () and outputs it as is
/// background: url(".. /image/timg.jpeg"); Url: (url, resourcePath) => {// url.. /image/timg.jpeg // resourcePath - CSS absolute path // not processing 'img. PNG 'urls if (url.includes('img.png')) {return false; } return true; },Copy the code
import
This value is similar to the url function, except that it controls the import and export of files. This value can also be set to true or false. If this parameter is set directly, then there is a problem
/// @import "./color.css"; import: (parsedImport, resourcePath) => { // parsedImport { url: './color.css', media: Url - '@import' file path // paralport. media - '@import' Media query path // resourcePath - the absolute path of the CSS file / / contains ` style.css. CSS ` merging processing if not (parsedImport. Url. Includes (' style. The CSS ')) {return false. } return true; },Copy the code
@import is a widely supported CSS attribute that can be used in browsers larger than IE9
modules
True or false Enables/disables (you can also enable/disable CSS modules by setting the modules value to ‘local’ or ‘global’)
In my view, global :local, Composing Importing, @value, and localIdentName are all configuration information for modules, which can accept an object for other configurations
Modules: {mode: 'local', // Set local enable global Disable CSS module exportGlobals: true, localIdentName: '[path][name]__[local]--[hash:base64:5]', // Compiled class name Context: path.resolve(__dirname, 'SRC '), hashPrefix: 'my-custom-hash', },Copy the code
mode
In addition tolocal global
Plus, there’s another valuepure
To use this value requires that the style file must be a pure selector and cannot be usedglobal local
On the parcel
/// when mode is pure, a compilation error is prompted :local(.zoo)... /// mode can also take a function form that performs special processing on the style files in the specified path (which files are converted and which files are not). The return values can only be these three values: (resourcePath) => { if (/pure.css$/i.test(resourcePath)) { return 'pure'; } if (/global.css$/i.test(resourcePath)) { return 'global'; } return 'local'; },Copy the code
-
ExportGlobals = exportGlobals = exportGlobals
-
Context generates the same hash, which is the same as GitHub bug description. In some cases, the same hash is generated, and this parameter is used to solve the problem, but I have tried many cases, and I have not found the same hash
-
HashPrefix sets the group’s own hash rule
-
GetLocalIdent sets the compiled rule name, the same as localIdentName except that it’s a function that can be set in more detail, usually using localIdentName
-
What does localIdentRegExp do
localsConvention
This sets how the key value maps to the class name when exporting JSON. The default is ‘asIs’.
loader: 'css-loader', options: { modules: { mode: 'local', localIdentName: '[path][name]__[local]--[hash:base64:5]' }, localsConvention: 'asIs' } ... .infoNews { font-size: 35px; } .info-old { color: white; } .info_dashes { color: salmon; } .info { color: red; }... Info: "src-component-page1-index__info --10GK2" info-old: "src-components-page1-index__info-old--k163w" infoNews: "src-components-page1-index__infoNews--1uma1" info_dashes: "src-components-page1-index__info_dashes--FVVUn" ... /// camelCase camelCase will change the non-camelcase name to camelCase and keep the previous class name info: "src-component-page1-index__info --10GK2" info-old: "src-components-page1-index__info-old--k163w" infoDashes: "Src-components -page1-index__info_dashes--FVVUn" // same as info_dashes infoNews: "src-components-page1-index__infoNews--1uma1" infoOld: "Src-components -page1-index__info-old--k163w" // same as info-old info_dashes: "src-components-page1-index__info_dashes--FVVUn" ... /// camelCaseOnly is similar to hump except that it does not keep the non-hump conversion info: "src-component-page1-index__info --10GK2" infoDashes: "src-components-page1-index__info_dashes--FVVUn" infoNews: "src-components-page1-index__infoNews--1uma1" infoOld: "src-components-page1-index__info-old--k163w" ... Info: "src-components-page1-index__info--10GK2" info-old: "SRC -components-page1-index__info--10GK2" info-old: "src-components-page1-index__info-old--k163w" infoNews: "src-components-page1-index__infoNews--1uma1" infoOld: "Src-compones-page1-index__info-old --k163w" info_dashes:" src-compones-page1-index__info_dashes --FVVUn" /// dashesOnly Does not retain the pre-conversion info: "src-components-page1-index__info--10GK2" infoNews: "src-components-page1-index__infoNews--1uma1" infoOld: "src-components-page1-index__info-old--k163w" info_dashes: "src-components-page1-index__info_dashes--FVVUn"Copy the code
The reason for this argument is that when we use CSS modules, we may end up dynamically binding to a component for easy use in JS