初探原子css

前端 0 857 0
发表于: 2022-10-31 18:26:17

简介: windicss、tailwindcss、unocss

前言

在讨论原子css的时候,首先我们先看看以前的css方案,看完之后再对比原子css的好处~

看之前可以看看css优先级:https://developer.mozilla.org/zh-CN/docs/Web/CSS/Specificity,对下文其实也挺重要的

sass

@import

Sass 扩展了 CSS 的@import规则,能够导入 Sass 和 CSS 样式表,提供对mixins函数变量的访问,并将多个样式表的 CSS 组合在一起。与普通的 CSS 导入不同,后者要求浏览器在呈现页面时发出多个 HTTP 请求,Sass 导入完全在编译期间处理。

common.scss:

// flex的水平垂直居中
.flexCenter {
  display: flex;
  align-items: center;
  justify-content: center;
}

// 解决图片缩小模糊问题
.imgBlur {
  -ms-interpolation-mode: nearest-neighbor;

  image-rendering: -moz-crisp-edges;
  image-rendering: -o-crisp-edges;
  image-rendering: -webkit-optimize-contrast;
  image-rendering: crisp-edges;
}

// 单行省略号
.singleEllipsis {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

// ltr
.ltr {
  direction: ltr;
}

// rtl
.rtl {
  direction: rtl;
}

// 置灰
.grayscale {
  filter: grayscale(100%);
}

// float清除浮动
.clearfix {
  &:after {
    display: block;
    clear: both;
    content: '';
  }
}

index.scss:

@import './common.scss';
.header {
  width: 100px;
  @extend .singleEllipsis;
}

编译index.scss结果:

.flexCenter {
  display: flex;
  align-items: center;
  justify-content: center;
}

.imgBlur {
  -ms-interpolation-mode: nearest-neighbor;
  image-rendering: -moz-crisp-edges;
  image-rendering: -o-crisp-edges;
  image-rendering: -webkit-optimize-contrast;
  image-rendering: crisp-edges;
}

.singleEllipsis, .header {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ltr {
  direction: ltr;
}

.rtl {
  direction: rtl;
}

.grayscale {
  filter: grayscale(100%);
}

.clearfix:after {
  display: block;
  clear: both;
  content: "";
}

.header {
  width: 100px;
}

extend

sass源码1(先定义要extend类,再使用):

.singleEllipsis {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.flexCenter {
  display: flex;
  align-items: center;
  justify-content: center;
}

.clearfix {
  &:after {
    display: block;
    clear: both;
    content: '';
  }
}

.header {
  width: 100px;
  @extend .singleEllipsis;
  @extend .flexCenter;
  @extend .clearfix;
}
.logo {
  width: 50px;
  @extend .singleEllipsis;
  @extend .flexCenter;
  @extend .clearfix;
}
.footer {
  width: 100vw;
  @extend .singleEllipsis;
  @extend .flexCenter;
  @extend .clearfix;
}

sass源码1编译结果:

.singleEllipsis, .footer, .logo, .header {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.flexCenter, .footer, .logo, .header {
  display: flex;
  align-items: center;
  justify-content: center;
}

.clearfix:after, .footer:after, .logo:after, .header:after {
  display: block;
  clear: both;
  content: '';
}

.header {
  width: 100px;
}

.logo {
  width: 50px;
}

.footer {
  width: 100vw;
}

编译结果跟顺序有关,有css优先级问题

先定义要extend的类,再使用header,logo,footer的话,其实后面header,logo,footer的规则优先级比extend的高(不考虑!important)

sass源码2(先使用,再定义extend类):

.header {
  width: 100px;
  @extend .singleEllipsis;
  @extend .flexCenter;
  @extend .clearfix;
}
.logo {
  width: 50px;
  @extend .singleEllipsis;
  @extend .flexCenter;
  @extend .clearfix;
}
.footer {
  width: 100vw;
  @extend .singleEllipsis;
  @extend .flexCenter;
  @extend .clearfix;
}

.singleEllipsis {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.flexCenter {
  display: flex;
  align-items: center;
  justify-content: center;
}

.clearfix {
  &:after {
    display: block;
    clear: both;
    content: '';
  }
}

sass源码2编译结果:

.header {
  width: 100px;
}

.logo {
  width: 50px;
}

.footer {
  width: 100vw;
}

.singleEllipsis, .header, .logo, .footer {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.flexCenter, .header, .logo, .footer {
  display: flex;
  align-items: center;
  justify-content: center;
}

.clearfix:after, .header:after, .logo:after, .footer:after {
  display: block;
  clear: both;
  content: '';
}

编译结果跟顺序有关,有css优先级问题

header,logo,footer先试用了extend类,再定义extend类的话,其实后面的extend的类的优先级比header,logo,footer的高(不考虑!important)

mixin

mixin不允许先使用再定义,必须得先定义mixin,再使用。

sass源码:

@mixin singleEllipsis {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@mixin flexCenter {
  display: flex;
  align-items: center;
  justify-content: center;
}

@mixin clearfix {
  &:after {
    display: block;
    clear: both;
    content: '';
  }
}

.header {
  width: 100px;
  @include singleEllipsis;
  @include flexCenter;
  @include clearfix;
}
.logo {
  width: 50px;
  @include singleEllipsis;
  @include flexCenter;
  @include clearfix;
}
.footer {
  width: 100vw;
  @include singleEllipsis;
  @include flexCenter;
  @include clearfix;
}

编译结果:

.header {
  width: 100px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  display: flex;
  align-items: center;
  justify-content: center;
}

.header:after {
  display: block;
  clear: both;
  content: '';
}

.logo {
  width: 50px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  display: flex;
  align-items: center;
  justify-content: center;
}

.logo:after {
  display: block;
  clear: both;
  content: '';
}

.footer {
  width: 100vw;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  display: flex;
  align-items: center;
  justify-content: center;
}

.footer:after {
  display: block;
  clear: both;
  content: '';
}

header,logo,footer的优先级比mixin的优先级高(不考虑!important)

extend和mixin区别

从上面的结果来看很容易得出结论,mixin不会单独输出,它只是将一份样式复制到所有用到的地方里,而extend会单独输出,它是将单独输出的那一份样式共享给所有用到的地方。

  • extend不能接收参数,mixin可以接收参数
  • mixin的造成的心智负担比extend的低很多(因为extend会根据书写的顺序不同会导致编译结果顺序也不同,有css优先级优先级问题)
  • 合理使用extend可以有效的复用样式,减少最终生成的css资源的大小。

sass做不到很好的复用

在使用sass的过程中,我们有沉淀了一些常用的css类,如:

common.scss:

// flex的水平垂直居中
.flexCenter {
  display: flex;
  align-items: center;
  justify-content: center;
}

// 解决图片缩小模糊问题
.imgBlur {
  -ms-interpolation-mode: nearest-neighbor;

  image-rendering: -moz-crisp-edges;
  image-rendering: -o-crisp-edges;
  image-rendering: -webkit-optimize-contrast;
  image-rendering: crisp-edges;
}

// 单行省略号
.singleEllipsis {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

// ltr
.ltr {
  direction: ltr;
}

// rtl
.rtl {
  direction: rtl;
}

// 置灰
.grayscale {
  filter: grayscale(100%);
}

// float清除浮动
.clearfix {
  &:after {
    display: block;
    clear: both;
    content: '';
  }
}

我们可以通过extend来继承我们之前封装的类样式(至于为什么要用extend,而不是mixin,看上面的extend和mixin区别):

.header {
  width: 100px;
  @extend .singleEllipsis;
}

这样咋眼一看,好像很正常,但是上面只是很泛的例子,实际的应用场景可能是这样的:

login.scss:

@import 'common.scss';

.header {
  width: 100px;
  @extend .singleEllipsis;
}

.fullname {
  width: 50px;
  @extend .singleEllipsis;
}

home.scss

@import 'common.scss';

.logo {
  width: 100px;
  @extend .imgBlur;
}

.avatar {
  width: 50px;
  @extend .imgBlur;
}

编译login.scss结果:

.flexCenter {
  display: flex;
  align-items: center;
  justify-content: center;
}

.imgBlur {
  -ms-interpolation-mode: nearest-neighbor;
  image-rendering: -moz-crisp-edges;
  image-rendering: -o-crisp-edges;
  image-rendering: -webkit-optimize-contrast;
  image-rendering: crisp-edges;
}

.singleEllipsis, .fullname, .header {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ltr {
  direction: ltr;
}

.rtl {
  direction: rtl;
}

.grayscale {
  filter: grayscale(100%);
}

.clearfix:after {
  display: block;
  clear: both;
  content: "";
}

.header {
  width: 100px;
}

.fullname {
  width: 50px;
}

编译home.scss结果:

.flexCenter {
  display: flex;
  align-items: center;
  justify-content: center;
}

.imgBlur, .avatar, .logo {
  -ms-interpolation-mode: nearest-neighbor;
  image-rendering: -moz-crisp-edges;
  image-rendering: -o-crisp-edges;
  image-rendering: -webkit-optimize-contrast;
  image-rendering: crisp-edges;
}

.singleEllipsis {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ltr {
  direction: ltr;
}

.rtl {
  direction: rtl;
}

.grayscale {
  filter: grayscale(100%);
}

.clearfix:after {
  display: block;
  clear: both;
  content: "";
}

.logo {
  width: 100px;
}

.avatar {
  width: 50px;
}

因为我们需要使用extend,所以我们就得引入common.scss,上面有两个文件引用到了common.scss,但是如果在一个项目里面,有五个十个甚至所有文件都引用了common.scss,那么我们编译这十几个文件的时候,每份文件都会引入所有的common.scss里面的样式,可能这个文件只用到了common.scss里面的一个样式,但是最终编译却会把common.scss的所有样式都会编译进每个样式文件里,很明显这造成了不必要的资源浪费(但是对这个文件或者sass来说,其实是正常的,因为你import了这个文件,他就会把这个文件的所有能引用的样式都引入进来)。那么有没有办法只编译用到的类呢,其实是有的,使用占位符选择器能实现。

占位符选择器

具体解释:https://sass-lang.com/documentation/style-rules/placeholder-selectors,总的来说就是没被extend使用的占位选择器不会被输出。

使用占位符选择器修改common.scss:

// flex的水平垂直居中
%flexCenter {
  display: flex;
  align-items: center;
  justify-content: center;
}

// 解决图片缩小模糊问题
%imgBlur {
  -ms-interpolation-mode: nearest-neighbor;

  image-rendering: -moz-crisp-edges;
  image-rendering: -o-crisp-edges;
  image-rendering: -webkit-optimize-contrast;
  image-rendering: crisp-edges;
}

// 单行省略号
%singleEllipsis {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

// ltr
%ltr {
  direction: ltr;
}

// rtl
%rtl {
  direction: rtl;
}

// 置灰
%grayscale {
  filter: grayscale(100%);
}

// float清除浮动
%clearfix {
  &:after {
    display: block;
    clear: both;
    content: '';
  }
}

使用extend时也得用占位符选择器,login.scss:

@import 'common.scss';

.header {
  width: 100px;
  @extend %singleEllipsis;
}

.fullname {
  width: 50px;
  @extend %singleEllipsis;
}

编译login.scss结果:

.fullname, .header {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.header {
  width: 100px;
}

.fullname {
  width: 50px;
}