初探原子css
简介: 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;
}