preface
After working for several years, I found that the following problems often exist in the project:
- 1. The module is improperly split
- 2. The naming of variables and functions is confusing
- 3. Missing comments or writing a lot of vague descriptions
- 4. Duplicate code everywhere, etc
Because of these bad programming habits, the project is more and more difficult to maintain, and the program performance is lower and lower, which greatly reduces the daily work efficiency and increases the development cost of the company.
The following takes the ARCHITECTURE of CSS in Vue3 project as a starting point to improve our programming ability and project architecture ability by reducing the redundancy of CSS code and enhancing the maintainability and expansibility of CSS code.
Technical reserves:
- Sass
- Vue3
The CSS design pattern
Before learning about CSS architecture, let’s take a quick look at five common CSS design patterns that provide some ideas for developing CSS architectures.
1. OOCSS mode
Object-oriented CSS(OOCSS) literally means object-oriented CSS, which has the following conventions in development
- Reduce reliance on HTML structure
# bad
#1. The matching efficiency is low, which affects the CSS performance
#2. High coupling degree with HTML, low maintenance and expansibility.container-list ul li a {} <div class="container-list"> <ul> <li> <a>... </a> </li> </ul> </div>
# good.container-list .list-item {} <div class="container-list"> <ul> <li> <a class="list-item">... </a> </li> </ul> </div>Copy the code
- Increase the reusability of styles
.label {
#Common code
}
.label-danger {
#Specific code
}
.label-info {
#Specific code
}
<div>
<p class="label label-danger"></p>
<p class="label label-info"></p>
</div>
Copy the code
2. The BEM model
BEM is the advanced version of OOCSS, is a hierarchical system, it divides our website into three layers, the three layers just correspond to BEM three English word shorthand block, element, modifier, divided into block layer, element layer, modifier layer.
To implement BEM into code, we need to follow three principles:
- Separate the block name from the element name with the __ double underscore
- Use — two dashes to separate element names and their modifiers
- All styles are a class and cannot be nested.
<div class="menu">
<div class="menu__tab menu__tab--style1">tab1</div>
<div class="menu__tab menu__tab--style1">tab2</div>
</div>
Copy the code
However, because of the two underscores __ and two dashes — in real development, it is not so convenient, affecting the efficiency of development, but if you want to strictly control CSS naming conventions, it is a good choice. And when writing CSS, we can use Sass hybrid instructions to encapsulate a BEm. SCSS file to reduce the input of class names and enhance the CSS structure
3. SMACSS mode
BEM’s simple three-layer classification method has no problem in dealing with small and medium-sized websites, but it may be more difficult to deal with the style of complex websites. We need to find a better way.
Scalable and Modular Architecture for CSS(SMACSS) is to write Modular, structured, and extensible CSS. It breaks down the CSS in your project into five categories
- Base: Resets the default property style, known as normalize.css
- Layout: The Layout style
- Modules: Styles of reusable Modules, such as list presentations
- State: State style, such as graying or highlighting of buttons
- Some websites, for example, have a skin-changing feature
4. ITCSS mode
ITCSS(Inverted Triangle Cascading Style Sheets) can be translated as “Inverted Triangle CSS” and is based on the concept of layering to divide styles in our project into seven layers
- Settings: Project style variables, such as theme color, font, etc
- Tools: Tools class style, such as defining a function to indicate that too many words appear as ellipses, etc
- Generic: Resets and/or standardizes styles, box size definitions, etc., as in normalize.css
- Base: resets the default values of browser element attributes
- Objects: Maintain OOCSS styles
- Components: Common component styles
- Trumps: Make the style weight the highest, utility and helper classes, able to override anything in front of the triangle, only important! The place where
5. ACSS mode
ACSS(Atomic CSS), translated as “Atomic CSS”, is an architectural style of CSS that tends to be small and single-purpose classes, and is named after visual effects. Is a WYSIWYG language that does not emphasize logic, but focuses more on performance. The background of its emergence is the arrival of front-end componentization era, and the CSS of each component can be independent of each other. So there’s code like this
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">button</button>
Copy the code
At present, mature ACSS libraries in the market include Tailwind CSS and Windi CSS
The advantages of ACSS
- CSS files stop growing: Using traditional methods, your CSS files get bigger every time you add a new feature. With utilities, everything is reusable, so you rarely need to write new CSS, and one set of styles is universal.
- No more wasted effort naming, no more silly class names: sidebar-inner-wrapper, for example, just to be able to style, and no more agonizing over the perfectly abstract name of something that is really just a Flex container.
- Flexible, easy to read: CSS is global, and when you make changes, you never know what you’re breaking. Classes in HTML are native, so you can plug and change styles without having to worry about other issues, and CSS styles have many abbreviations that are more memorable to the brain.
- Never worry about naming conflicts, never worry about style overwriting.
The disadvantage of ACSS
- Increases the size of the HTML
- Breaks the semantics of CSS naming
- Familiar with naming ACSS naming has a cost
To sum up, we can see that the disadvantages of ACSS are very small, while the benefits are very large, and there is no reason not to apply in the project. Let’s create ACSS architecture solution by using BEM, ITCSS, and ACSS patterns.
Project structures,
Create vuE3 projects and install dependencies
- 1. Create a VUe3 project
- 2. Installation:
NPM I [email protected] [email protected] --save
The CSS directory structure is displayed
# SRC style acSS # SRC style acSS # SRC style ACSS # SRC style ACSS # SRC style ACSS # SRC style ACSS # Tools # Store wrapped mixin and function styles global.scss # CSS that needs to be referenced globally by the projectCopy the code
1. The difference between mixin and function
- The function has calculation logic, returns the result of the calculation, does not output CSS blocks
- Mixins mainly output CSS blocks based on computed results
/* mixin */
@mixin center-translate($direction: both) {
position: absolute;
@if $direction == both {
top: 50%;
left: 50%;
transform: translate3d(-50%, -50%.0);
} @else if $direction == horizontal {
left: 50%;
transform: translate3d(-50%.0.0);
} @else if $direction == vertical {
top: 50%;
transform: translate3d(0, -50%.0); }}/* function */
@function am($module, $trait: false) {
@if $trait==false {
@return '[am-' + $module + '] ';
} @else {
@return '[am-' + $module + '~ =" + $trait + '"]; }}Copy the code
2. About style/global.scss and style/index.scss
- Global.scss imported code is not only used in the Vue file, but also referenced in the STYLE SCSS definition file
# style/global.scss
@import "./settings/var.scss";
# style/settings/var.scss
$background-color-primary: #F1F1F1;
$background-color-secondary: $color-white;
# style/acss/color.scss
@each $style in (primary $background-color-primary, secondary $background-color-secondary) {
[bg-#{nth($style, 1)}] {
background-color: # {nth($style, 2)}; }}Copy the code
- Global introduction of style/global.scss
// Root directory: vue.config.js
module.exports = {
css: {
loaderOptions: {
scss: {
// @/ is an alias for SRC /
// Note: in Sass-Loader V8, the option name is "prependData".
prependData: `@import "@/style/global.scss"; `}}}},Copy the code
- The code defined by style/index.scss is not referenced by other CSS files in style, otherwise it is the same as global.scss
- Introduction of style/index. SCSS
// src/main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import './style/index.scss'
createApp(App).use(router).mount('#app')
Copy the code
Below is a brief analysis and demonstration of the code in each style directory.
1.acss
This directory mainly defines some simple border, color, font-size, margin and padding code
/* style/acss/border.scss */
@for $i from 1 through 100 {
[radius#{$i}] {
border-radius: #{$i}Px;
overflow: hidden; }}[circle] {
border-radius: 50%;
}
/* style/acss/font-size.scss */
@for $i from 12 through 30 {
[fz#{$i}] {
font-size: #{$i}px; }}Copy the code
Use acSS code
<div class="container">
<div class="item" radius20>border-radius: 20px;</div>
</div>
<div class="container">
<div class="item" circle>border-radius: 50%;</div>
</div>
<div class="container">
<div class="item" fz30>font-size: 30px;</div>
</div>
Copy the code
2.base
This directory resets the default styles of elements in the project, such as input, hn, P, A, and so on
/* style/base/form.scss */
input {
padding: 0;
outline: none;
border: none;
}
/* style/base/link.scss */
a {
color: #ccc;
text-decoration: none;
}
Copy the code
3.settings
This directory defines global, project-specific variables such as text color, border color, and so on
/* style/settings/var.scss */
/* Theme color */
$color-primary: #FF5777;
$color-white: #FFFFFF;
/* Text tone */
$color-text-primary: green;
$color-text-secondary: #FF4533;
$color-text-tertiary: $color-white;
$color-text-quaternary: $color-primary;
/* Box frame color */
$border-color-base: #E5E5E5;
/* Box background color */
$background-color-primary: #F1F1F1;
$background-color-secondary: $color-white;
$background-color-tertiary: $color-primary;
/* Boxes default border */
$border-width-base: 1Px! default; $border-style-base: solid ! default; $border-base: $border-width-base $border-style-base $border-color-base ! default;Copy the code
4.theme
This directory defines the styles of related modules under each topic of the project
/* style/theme/default.scss */
[data-theme='default'] .header {
background: #FF5777;
}
[data-theme='default'] .footer {
color: #FF5777;
border: 2px solid #FF5777;;
}
/* style/theme/cool.scss */
[data-theme='cool'] .header {
background: #409EFF;
}
[data-theme='cool'] .footer {
color: #409EFF;
border: 2px solid #409EFF;;
}
Copy the code
We can transform the project theme by adding data-theme attributes and values on HTML elements
<! -- Theme.vue -->
<template>
<div class="theme">
<div class="header"></div>
<div class="theme__set">
<div class="set set--default" @click="changeTheme('default')"></div>
<div class="set set--cool" @click="changeTheme('cool')"></div>
</div>
<div class="footer"></div>
</div>
</template>
<script>
export default {
name: "Theme".setup() {
const changeTheme = (theme = 'default') = > {
window.document.documentElement.setAttribute("data-theme", theme);
}
return {
changeTheme
}
}
}
</script>
<! -- Other.vue -->
<template>
<div class="about">
<div class="header"></div>
<div class="about-title">This is an about page title</div>
<div class="about-content">This is an about page content</div>
<div class="footer"></div>
</div>
</template>
Copy the code
5.tools
This directory defines some global public mixins and functions. At present, this content is more complete, which is SassMagic. If you are interested, you can click here to have a look. The following is a brief look at the application of BEM mode
$elementSeparator: '__';
$modifierSeparator: The '-';
// Check whether '$selector' contains BEM Modify
@function containsModifier($selector) {
$selector: selectorToString($selector);
@if str-index($selector.$modifierSeparator) {
@return true;
} @else {
@returnfalse; }}// Convert '$selector' to String
@function selectorToString($selector) {
$selector: inspect($selector); //cast to string
$selector: str-slice($selector.2, -2); //remove brackets
@return $selector;
}
// @param {String} $selector
@function getBlock($selector) {
$selector: selectorToString($selector);
$modifierStart: str-index($selector.$modifierSeparator) - 1;
@return str-slice($selector.0.$modifierStart);
}
@mixin b($block) {. # {$block} {
@content; }}@mixin e($element) {
$selector: &;
@if containsModifier($selector) {
$block: getBlock($selector);
@at-root {
#{$selector#} {{$block + $elementSeparator + $element} {
@content; }}}}@else {
@at-root {
#{$selector + $elementSeparator + $element} {
@content; }}}}@mixin m($modifier) {
@at-root# # {{and} {$modifierSeparator + $modifier} {
@content; }}}// @param {string} $block - BEM block
// <div class="block">
//
//
//
// </div>
// @include b(block) {
// background: red;
// @include e(header){
// font-size: 14px;
// @include m(css) {
// font-size: 18px;
/ /}
/ /};
// }
/ / the compiled
// .block {
// background: red;
// }
// .block__header {
// font-size: 14px;
// }
// .block__header--css {
// font-size: 18px;
// }
Copy the code
The end of the
So much for now, more information can be paid attention to vue3-CSS-Architecture, which will be continuously updated to add more mixins, functions, and applications in the project.