这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

目前平台前端使用的是原生CSS+BEM命名,在多人协作的模式下,容易出现样式冲突。为了减少这一类的问题,提升研效,我调研了业界上主流的7种CSS解决方案,并将最终升级方案落地到了工程中。

样式冲突的原因

目前遇到的样式冲突的原因,其实根本原因还是css样式混乱使用导致的:

  1. 多人协作,样式互相污染,这是项目中的主要问题。用开发规范来限定、用CR流程来保障,并不可靠
  2. 引用大量第三方组件库,组件库对CSS的使用不规范。比如bee.css中使用了大量!important,破坏了项目中的样式优先级;rsuit是前端非常强大的表格组件库,他的css文件中也有直接覆盖底层样式的写法label{ marign:2px }
  3. 直接使用组件库引入的css文件,比如import material-icons.css,如果引用顺序靠后,这些文件可能会覆盖开发人员手写的样式。
  4. ...

调研方案

CSS作为前端三剑客之一,几乎是所有前端同学最先学习的样式表语言。在生产环境的项目工程中,很少见到直接原生使用CSS的。但目前业界还没有通用的CSS工程化方案。这篇文章先简单介绍下7种在React/Next.js中较为流行使用CSS的方式,并说说他们的优缺点。

原生 CSS

这是一种用选择器来划分css作用域的方式。

  • 缺点:
  1. 作用域问题 CSS样式之间会层叠覆盖,需要用大量的classname来指定选择器,来限定CSS的作用域范围。频繁的命名给开发人员增加不少心智负担,而且容易搞错搞重复。
// pure css example
.card {
/* styles */
}
.card__header {
/* styles */
}
.card--focus {
/* styles */
}

采用BEM规则来进行命名或许会简单些。 但在需要维护特别多样式的时候,BEM还是不够用。尤其是当代码中开始大量出现!important这种破坏优先级的东西的时候。

// css with !important
.card {
color: blue !important;
}
.card {
color: red;
}
  1. 打包体积大 使用大量冗长的原生CSS,可能会导致 打出来的包变大。包越大,项目自然跑的就越慢。

CSS MODULES

这是一种在原生CSS的基础上,通过modules(也可以理解为文件)来划分CSS的作用域。

首先先建一些以.module.css结尾的文件,这些文件里的样式可以只针对某个组件(某个module)生效。这种做法在Next.js尤为常见,因为CSS modules在Next.js是可以开箱即用的。

下面是一个例子,在Home.module.cssother.module.css同样的类名书写样式,也不会产生冲突。

@file Home.module.css
.page {
color: bule;
}
@file other.module.css
.page {
color: yellow;
}
// 只会生效这里import的样式
import styles from '../styles/Home.module.css';
export default function Home(){
return (
// 蓝色
<div className={styles.page}>
<h1> Home Page </h1>
<div>
)
}
  • 优势:
  1. 当需要复用样式的时候,不同的组件可以import同一份样式文件,减少很多重复样式代码,减轻打包体积~
  2. 说到样式复用,CSS modules还有个特殊的composes属性,能引入别的module的css样式,也能重写(override)。
.page {
composes: className from "./shared.css"
}
  • 缺点:
  1. 不够“程序化” CSS modules在原生CSS的基础上增加了以modules(文件)划分的作用域,解决了作用域问题,但仍逃不过在单个module内以原生的方式书写CSS。原生的CSS只能纯纯的枚举出每一条样式,如果能在书写CSS的时候也支持一些程序特性岂不是更好?比如最常用的循环、遍历、函数、继承...

CSS PREPROCESSOR 预处理器

Sass、Less、Stylus... 这些预处理器就是为了解决CSS不够“程序化”而诞生的。他们允许你用一种不一样的语法来写CSS,之后再经过编译转化成原生CSS。

这里是一个例子:

// 只需一键安装sass
$ npm install sass
// 然后把原本的css后缀文件改成scss

// 就可以直接使用sass的方式来编写css啦,比如变量名、循环、...
@ file Home.module.scss $ primary-color: red;
$ font-stack:Helvetica body {
font: 100% $font-stack;
color: $primary-color;
}
  • 优势:
  1. 可以用变量、继承、循环、函数、...等程序特性
  • 缺点:
  1. 学习成本 每种预处理器都有各自特定的语法,虽然是用一种类CSS的语言来编写,但总有有些差异。这意味着开发人员必须配合工具掌握新的语法。
  2. 样式和项目代码微微割裂 在解决完作用域、程序化问题后,样式在前端项目中完完全全的独立出来了,似乎少了一些联动能力。既然我们有JSX这样整合JS和HTML的合体语言,为什么不能把CSS也合体进来呢?

CSS IN JS

这是一种把CSS写进JS的解决方案,就像把HTML写进JS后就有了JSX。这一类的库有styled components、emotion、jss、style tron、...

举个使用styled jsx的例子:

import styles from '../styles/Home.module.css';

export default function Home(){
const [color, serColor] = useState('orange');
return (
<div className={styles.page}>
<style jsx>{`
h1 {
// 取的是组件state,可以随state变化!
color: ${color};
}
`}</style>
<h1> Home Page </h1>
<div>
)
}
  • 优势:
  1. 轻松能实现的程序化能力 在sass里的程序化能力,CSS in JS都能做到,甚至更强,这种方式可以直接使用JS书写这种程序化语言,也不需要额外学习成本。
  2. 创建动态样式 在sass里,程序代码或许和样式文件是完全独立开来的。而使用CSS in JS,样式和JS强绑定,我们的样式能够跟着代码、跟着组件的state等特性实现动态样式,特别灵活!
  3. 不会有作用域问题 类似module,CSS in JS的样式只会绑定在样式定义的组件内,不会污染全局样式~
  • 缺点:
  1. CSS和JS混写,代码管理困难。

UTILITY CLASSES 原子类

时下最火的新概念就是tailwindcss、windi css这些原子类CSS库,能够提供大量的原子类样式,帮助我们快速构建样式。

// 配置好tailwind之后
export default function Home(){
return (
// 在这里写上tailwind的原子类classname,而不需要写样式
<div className="text-5xl font-bold">
<h1> Home Page </h1>
<div>
)
}
  • 缺点
  1. 需要比较麻烦的额外配置
  2. 打包后,生成的HTML文件可读性非常非常低
  3. 没有任何的内置组件
  • 优势
  1. 打包时,能自动优化,去除没有使用的css样式,减轻打包产物体积。

CSS FRAMEWORK

bootstrap、bulma、这一类库既能提供特定的样式主题,又有内置的组件,比如bottom、cards、...等等。我个人在自己倒腾东西的时候非常喜欢用这一类框架,因为实在是太方便啦!这种方式在生产上几乎很少采用,因为开发人员往往需要根据产品原型来绘制前端界面,而不是这些框架固定的样式。另外采用这种方式,也容易对线上性能造成比较大影响。

// 想使用这一类框架,只用一键安装上
$ npm install bootstrap // 引入框架的样式文件
import 'bootstrap/dist/css/bootstrap.css' export default function Home(){
return (
// 想要使用的样式都在bootstrap中用各种classname封装好啦,直接调用boostrap的预留classname,搞定
<div className="alert alert-primary">
<h1> Home Page </h1>
<div>
)
}
  • 缺点:
  1. 在只使用bootstrap来搭建组件和修改样式的话,会不太方便 由于这类框架已经自带了许多预留组件,而bootstrap的样式又是用classname来获取的。假设我需要频繁使用<Bottom />组件,却又不想在每次使用的时候,都重复的写相同的classname,那么就会将他们封装成<CustomButtom />。这么做的话,项目代码中就可能会有大量的仅仅是为了封装classname而存在的组件。
  2. 打包文件过大 整个bootstrap文件是直接import进来的。因此在打包时,会把大量没使用到的classname也打包进来,会造成打包产物较大~

组件库

这是大家最熟悉的方式啦,ant design、material design、t design、rebase、....

最终落地的升级方案

不同的CSS处理方式各有优劣,在实际开发中,可以自行选择和搭配合适的CSS处理手段。

在我目前工作中,是将项目的原生CSS,升级成css module + less 的组合,这样既能解决当前项目的核心矛盾:作用域和样式污染问题,又能让CSS的编写过程变得更“程序”,比如使用变量、继承等特性。

没有使用css in js 是因为当前项目没有主题切换和动态样式这样场景,此外css in js 会让一个组件文件变得非常冗长,尤其是目前我的工作特别多复杂图表的封装,仅jsx部分代码行数已经非常长,再引入CSS代码容易变得更混乱。我个人也更加偏向能用独立文件区分出CSS代码的方式,这样展示出更好的项目分层。

没有使用原子类的理由就更简单了,配置麻烦,可读性低,而且对团队内每个人都有较高的学习成本,不方便团队管理,直接pass了。

在前端工程开发的过程中,面对多人协作的场景,建立标准和团队内的规范是非常重要的一个环节。尤其当前业界的前端,就是没有通用标准的情况下,影响项目工程稳健性的往往是缺乏规范和标准,而不是开发人员的水平。在我工作的项目中,最初就是因为大量人员流动,大家在项目中各按各自的方式写CSS,导致在一个项目中存在3种以上CSS写法,非常难维护,也出现了样式互相污染、互相冲突的情况,所以才有了这次对CSS的调研,以及对项目进行升级和改造的工作。

本文转载于:

https://juejin.cn/post/7171413795938500639

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

记录--记一次前端CSS升级的更多相关文章

  1. 记一次前端css样式的三角形的应用

    1)面试题是这样的要求用css实现 <section> <div></div> <div></div> </section> & ...

  2. 扯一扯前端css的整体架构设计:(2)base基础类的那些事儿

    周一下午在实验室写了第一篇博文,有几个人捧场,那咱就得接着下去啊.然后我觉得现在写的内容更多的偏向于谈一下我对于前端css架构的理解和前端经验的一个小总结,所以就把标题里原来的[项目总结]给删掉了.但 ...

  3. {前端CSS} 语法 Css的几种引入方式 css选择器 选择器的优先级 CSS属性相关 背景属性 边框 CSS盒子模型 清除浮动 overflow溢出属性  定位(position)z-index

    前端CSS CSS介绍 CSS(Cascading Style Sheet,层叠样式表)定义如何显示HTML元素,给HTML设置样式,让它更加美观. 当浏览器读到一个样式表,它就会按照这个样式表来对文 ...

  4. 前端CSS - 相对定位,绝对定位,固定定位

    前端CSS - 相对定位,绝对定位,固定定位 1.1 相对定位 position:relative 相对定位,就是微调元素位置的.让元素相对自己原来的位置,进行位置的微调. 也就是说,如果一个盒子想进 ...

  5. 记一起和前端没什么卵关系的OPTION 405问题

    记一起和前端没什么卵关系的后端405问题 问题的关键点在于本来是POST请求,会变成OPTION请求,并且提示405报错,会类似跨域.并且只有某些手机机型才会(如Oppo系列). 其实跨域的问题,如果 ...

  6. day 45 前端CSS

      前端CSS   CSS介绍 CSS(Cascading Style Sheet,层叠样式表)定义如何显示HTML元素,给HTML设置样式,让它更加美观. 当浏览器读到一个样式表,它就会按照这个样式 ...

  7. 前端CSS编程之道-LESS

    由于前端css编写繁琐,最近开始学习LESS,用LESS编写文件.less文件可以直接编译成我们要的.css文件 学习Less 我下面是我练习时的截图,希望小伙伴也能动手自己写一下,而不是复制粘贴模式 ...

  8. Web前端-CSS必备知识点

    Web前端-CSS必备知识点 css基本内容,类选择符,id选择符,伪类,伪元素,结构,继承,特殊性,层叠,元素分类,颜色,长度,url,文本,字体,边框,块级元素,浮动元素,内联元素,定位. 链接: ...

  9. WEB前端 CSS(非布局)

    目录 WEB前端 CSS CSS引入方式 CSS结构 CSS选择器 直接选择器 组合选择器 分组选择器 也叫并集选择器 属性选择器 伪类选择器 伪元素选择器 CSS选择器是一个查找的过程,高效的查找影 ...

  10. 前端 CSS 目录

    前端 CSS 介绍 前端 CSS语法 前端 CSS 注释

随机推荐

  1. 好书推荐之《码出高效》、《阿里巴巴JAVA开发手册》

    好评如潮 <阿里巴巴Java开发手册> 简介 <阿里巴巴Java开发手册>的愿景是码出高效,码出质量.它结合作者的开发经验和架构历程,提炼阿里巴巴集团技术团队的集体编程经验和软 ...

  2. C++ 线程的学习---线程同步

    因为是学习篇,写下是为了个人的学习与理解.故参考其他文章为多. 为什么需要线程同步? 在程序中使用多线程时,一般很少有多个线程能在其生命期内进行完全独立的操作.更多的情况是一些线程进行某些处理操作,而 ...

  3. OpenCV开发笔记(五十七):红胖子8分钟带你深入了解直方图反向投影(图文并茂+浅显易懂+程序源码)

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

  4. 内建函数iter(),第三个参数哨兵用法

    循环读取文件常见写法 CHUNKSIZE=8192 def reader(s): while True: data = s.recv(CHUNKSIZE) if data == b'': break ...

  5. iterables/generators/yield

    iterables # 当你创建了一个列表,你可以一个一个的读取它的每一项,这叫做iteration: >>> mylist = [1,2,3] >>> for i ...

  6. React 中 Ref 引用

    不要因为别人的评价而改变自己的想法,因为你的生活是你自己的. 1. React 中 Ref 的应用 1.1 给标签设置 ref 给标签设置 ref,ref="username", ...

  7. 【ACM专项练习#01】基本输入输出,如何加减

    关于ACM,牛客其实也有专门的模拟练习:https://ac.nowcoder.com/acm/contest/5657#question 做这个也可以 关于while(cin>>n) 在 ...

  8. 矩池云|GPU 分布式使用教程之 TensorFlow

    GPU 分布式使用教程之 TensorFlow TensorFlow 提供了6种策略实现分布式计算,各个策略详情请参考官方文档.本文档使用 MirroredStrategy 实现单机多卡分布式,Mul ...

  9. SpringBoot面试题的零碎整理

    面试题1:简述一下Springboot相对SSM做了哪些提升? 首先,SpringBoot是采用"约定大于配置"(Convention over Configuration)的理念 ...

  10. Mysql基础目录

    尚硅谷Mysql课程笔记 课程链接: https://www.bilibili.com/video/BV1iq4y1u7vj?p=1 第01章_数据库概述 第02章_MySQL环境搭建 第03章_基本 ...