- 1.水平垂直居中
- 2.清除浮动
- 3.css预编译器
- 4.margin:auto 为什么可以实现垂直居中?
- 5.说说CSS选择器以及这些选择器的优先级
- 6.你知道什么是BFC么
- 7.了解盒模型么
- 9.如何实现左侧宽度固定,右侧宽度自适应的布局
- 10.用过Flex么,能简单介绍一下
- 11.伪类和伪元素的区别
- 12.绝对定位
- 13.说说z-index有什么需要注意的地方
- 14.熟悉CSS3动画么
- 15.Flex实现两列布局
- 16.绝对定位、固定定位和z-index
- 17.css预编译语言是什么
- 18.pc端和移动端像素不同,如何兼容?
- 19.box-sizing
- 20.height:100%和height:100vh的区别
- 21.box-sizing
- 22.1px边框问题
- 23.分析比较 opacity: 0、visibility: hidden、display: none 优劣和适用场景
- 如何实现样式隔离
1.水平垂直居中
1.margin: 0 auto;水平2.text-align: center;水平3.行高,垂直4.表格,center,middle;水平垂直5.display:table-cell;模拟表格,all6.绝对定位,50%减自身宽高7.绝对定位,上下左右全0,margin:auto8.绝对定位加相对定位。不需要知道宽高9.IE6,IE7:给父元素设一个font-size:高度/1.14,vertical-align:middle
/ 1.flex布局 /
.parent {
width: 500px;
height: 500px;
background: red;
display: flex;
justify-content: center;
align-items: center;
}
.children {
width: 200px;
height: 200px;
background: orange;
}
/ 2.绝对定位,上下左右全0,margin:auto /
.parent {
width: 500px;
height: 500px;
background: red;
position: relative;
}
.children {
width: 200px;
height: 200px;
background: orange;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
}
/ 3.绝对定位,上左50%,再用transform:translate偏移自身宽高的50% /
.parent {
width: 500px;
height: 500px;
background: red;
position: relative;
}
.children {
width: 200px;
height: 200px;
background: orange;
position: absolute;
top: 50%;
left: 50%;
transform:translate(-50%,-50%);
}
/ 4.子元素position: relative;横向利用margin auto,垂直还是利用定位和平移translate /
.parent {
width: 500px;
height: 500px;
background: red;
}
.children {
width: 200px;
height: 200px;
background: orange;
position: relative;
top: 50%;
margin-left: auto;
margin-right: auto;
transform:translateY(-50%);
}
/ 5.table布局 /
.parent {
width: 500px;
height: 500px;
background: red;
display: table;
text-align: center;
}
.children {
width: 200px;
height: 200px;
background: orange;
display: table-cell;
vertical-align: middle;
}
这只是一部分还有很多,可以自己尝试着做一下
2.清除浮动
.fahter{
width: 400px;
border: 1px solid deeppink;
}
.children1{
width: 200px;
height: 200px;
background: darkorange;
}
.children2{
width: 120px;
height: 120px;
background: darkmagenta;
}
.footer{
width: 900px;
height: 100px;
background: darkslateblue;
}
如上我们想让children1 和children2 浮动,但是设置了之后发现footer也上去了,而且父元素的宽度变成了一条线,这是因为没有给父元素设置高度,当没有浮动的时候就会子元素就会撑开父元的高度,当有浮动的时候就不会撑开了,这个时候就需要清除浮动了。
方法一:额外标签法,在div中添加一个标签clear
.clear{
clear:both;
}
方法二:after伪元素
.clearfix:after{/伪元素是行内元素 正常浏览器清除浮动方法/
content: “”;
display: block;
height: 0;
clear:both;
visibility: hidden;
}
.clearfix{
zoom: 1;/ie6清除浮动的方式 号只有IE6-IE7执行,其他浏览器不执行/
}
方法三:使用after 和before两个伪元素
.clearfix:after,.clearfix:before{
content: “”;
display: table;
}
.clearfix:after{
clear: both;
}
.clearfix{
*zoom: 1;
方法四:父元素overflow
.fahter{
width: 400px;
border: 1px solid blue;
overflow: hidden;
}
原理:
- 因为该属性进行超出隐藏时需要计算盒子内所有元素的高度, 所以会隐式清除浮动
-
3.css预编译器
https://blog.csdn.net/joehonv/article/details/81699572
https://segmentfault.com/a/1190000018337119?utm_source=tag-newest
https://zhuanlan.zhihu.com/p/38715068
css预处理是基于css的一些缺陷,扩展了一套属于自己的语法,使编写的css可以复用、减少冗余代码,提高样式代码的可维护性。
目前最主流的三个预处理器 Less、Sass 和 Stylus。Less 的基本语法属于「CSS 风格」,而 Sass、Stylus 相比之下激进一些,利用缩进、空格和换行来减少需要输入的字符。不过区别在于 Sass、Stylus 同时也兼容「CSS 风格」代码。三者的嵌套语法都是一致的,甚至连引用父级选择器的标记&
也相同。区别只是 Sass 和 Stylus 可以用没有大括号的方式书写。4.margin:auto 为什么可以实现垂直居中?
想要实现垂直方向的居中可以用绝对定位:
div {
width: 20px;
height: 20px;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
}
块状水平元素,如div元素(下同),在默认情况下(非浮动、绝对定位等),水平方向会自动填满外部的容器;如果有margin-left/margin-right,padding-left/padding-right,border-left-width/border-right-width等,实际内容区域会响应变窄。
但是,当一个绝对定位元素,其对立定位方向属性同时有具体定位数值的时候,流体特性就发生了。具有流体特性绝对定位元素的margin:auto的填充规则和普通流体元素一模一样,含有以下特性: 如果一侧定值,一侧auto,auto为剩余空间大小;
-
5.说说CSS选择器以及这些选择器的优先级
!important
- 内联样式(1000)
- ID选择器(0100)
- 类选择器/属性选择器/伪类选择器(0010)
- 元素选择器/关系选择器/伪元素选择器(0001)
-
6.你知道什么是BFC么
https://juejin.im/post/59b73d5bf265da064618731d
https://juejin.im/entry/59c3713a518825396f4f6969
https://juejin.im/post/5cee1b38e51d4556be5b39e1
https://zhuanlan.zhihu.com/p/184905483
BFC 全称为块级格式化上下文 (Block Formatting Context) 。一个环境中的元素不会影响到其它环境中的布局。比如浮动元素会形成BFC,浮动元素内部子元素的主要受该浮动元素影响,两个浮动元素之间是互不影响的。这里有点类似一个BFC就是一个独立的行政单位的意思。可以说BFC就是一个作用范围,把它理解成是一个独立的容器,并且这个容器里box的布局与这个容器外的box毫不相干。
特性: 使 BFC 内部浮动元素不会到处乱跑;
-
触发BFC的条件
float的值不为none;
- overflow的值不为visible;
- position的值为fixed / absolute;
display的值为table-cell / table-caption / inline-block / flex / inline-flex。
BFC的约束规则
内部的盒会在垂直方向一个接一个排列(可以看作BFC中有一个的常规流)
- 处于同一个BFC中的元素相互影响,可能会发生外边距重叠
- 每个元素的margin box的左边,与容器块border box的左边相接触(对于从左往右的格式化,否则相反),即使存在浮动也是如此
- BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之亦然
- 计算BFC的高度时,考虑BFC所包含的所有元素,连浮动元素也参与计算 ———-》利用这个特性可以清除浮动
- 浮动盒区域不叠加到BFC上
BFC可以解决的问题
- 解决浮动元素令父元素高度塌陷的问题如,父元素div包含几个子div,这几个子元素都为浮动时,父元素高度坍塌,这是因为浮动的子元素脱离了文档流,漂浮于父元素之上,父元素检测不到子元素的存在,获取不到子元素高度,所以看起来父元素没有高度了。父元素后面的布局也就乱了,这时,可以给父元素添加属性overflow:hidden,当然,这只是一种BFC的做法,还可以display: table-cell;或position: fixed;或position: absolute;
触发了BFC的容器就是页面上的一个完全隔离开的容器,容器里的子元素绝对不会影响到外面的元素,为了保证这个规则,触发了BFC的父元素在计算高度时,不得不让浮动的子元素也参与进来,变相的实现了清楚内部浮动的目的。
但有的时候出于布局需要也可能无法给父元素设置这些属性,解决高度坍塌还有让父元素也浮动起来,或添加一个高度,但这种适用于已知道子元素高度
- 解决自适应布局的问题PC端的网页,左右两栏布局很常见,一般左侧定宽,右侧主体页面宽度自适应变化,通常是用浮动来实现的;它利用了块级元素占满一行的特性,使得右边的元素可以随着页面宽度的变化而变化,又利用了浮动的特性,让左侧元素覆盖在右侧元素上方,同时还能挤开下方元素的内容,让页面看起来是两栏的效果,但随着右边元素的增加,超出了左边元素的高度后,文字就会环绕左侧元素,这显然不是我们想要的效果,因为右侧元素触发了BFC,触发BFC的容器就是页面上的一个完全隔离开的容器,容器中的子元素绝对不会影响到外面的元素,为了保证这个规则,触发了BFC的右侧元素为了将内部元素和左侧浮动元素隔离开,不得不形成这样左右完全隔离的两栏,同时,如果右侧元素依旧是块级元素,那么他尽可能占满一行的特性还在,这样就保证了右侧元素依旧是自适应的
- 解决外边距垂直方向重合问题
垂直方向上两个兄弟元素外边距会取最大值,而不是取和,那么我们可以通过触发BFC来防止他们之间相互影响。为其中一个元素的外边包裹一层父元素,并且触发父元素BFC,比如:overflow:hidden,这样打破原有格局,就不再会重叠啦!另外我们可以用padding来代替marging,有点是简单易懂,缺点是如果根据设计本来就需要设置padding样式,那就没办法用了
总结:
- 垂直外边距重叠问题
- 去除浮动 ——》 父元素添加overflow:hidden; (触发BFC) :原理: 因为该属性进行超出隐藏时需要计算盒子内所有元素的高度, 所以会隐式清除浮动 。
-
7.了解盒模型么
W3C盒子模型):元素的宽高大小表现为内容的大小
(IE盒子模型):元素的宽高表现为内容 + 内边距 + 边框的大小。背景会延伸到边框的外沿。9.如何实现左侧宽度固定,右侧宽度自适应的布局
利用
float + margin
实现:原理是创建bfc
.box {
height: 200px;
}
.box > div {
height: 100%;
}
.box-left {
width: 200px;
float: left;
background-color: blue;
}
.box-right {
margin-left: 200px;
background-color: red;
}
利用calc
计算宽度
.box {
height: 200px;
}
.box > div {
height: 100%;
}
.box-left {
width: 200px;
float: left;
background-color: blue;
}
.box-right {
width: calc(100% - 200px);
float: right;
background-color: red;
}
利用float + overflow
实现
.box {
height: 200px;
}
.box > div {
height: 100%;
}
.box-left {
width: 200px;
float: left;
background-color: blue;
}
.box-right {
overflow: hidden;
background-color: red;
}
利用flex
实现
.box {
height: 200px;
display: flex;
}
.box > div {
height: 100%;
}
.box-left {
width: 200px;
background-color: blue;
}
.box-right {
flex: 1; // 设置flex-grow属性为1,默认为0
overflow: hidden;
background-color: red;
}
10.用过Flex么,能简单介绍一下
https://juejin.im/post/58e3a5a0a0bb9f0069fc16bb
https://juejin.im/post/5e72eca86fb9a07cd80f410f
小提示:如果在项目中使用过,可简单介绍一下自己使用Flex解决过什么问题,这里我在项目中印象比较深刻的是使用Flex解决上面内容高度不固定,下面内容高度自动撑满父容器剩余高度的问题。
如果不是很清楚Flex,可以查看阮一峰的文章Flex 布局教程:语法篇。面试官追问,那么除了Flex,你还知道Grid么?这个由于兼容性问题,我一直没有好好研究过,这里可查看阮一峰的文章CSS Grid网格布局教程。
flex: 1; === flex: 1 1 0%;
- 第一个参数表示: flex-grow 定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大
- 第二个参数表示: flex-shrink 定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小
第三个参数表示: flex-basis**给上面两个属性分配多余空间之前, 计算项目是否有多余空间, 默认值为 auto, 即项目本身的大小**
11.伪类和伪元素的区别
1)伪类(pseudo-classes)
其核⼼就是⽤来选择DOM树之外的信息,不能够被普通选择器选择的⽂档之外的元素,⽤来添加⼀些选择器的特殊效果。
- ⽐如:hover :active :visited :link :visited :first-child :focus :lang等
- 由于状态的变化是⾮静态的,所以元素达到⼀个特定状态时,它可能得到⼀个伪类的样式;当状态改变时,它⼜会失去这个样式。
- 由此可以看出,它的功能和class有些类似,但它是基于⽂档之外的抽象,所以叫 伪类。
2)伪元素(Pseudo-elements)
- DOM树没有定义的虚拟元素
- 核⼼就是需要创建通常不存在于⽂档中的元素,
- ⽐如::before ::after 它选择的是元素指定内容,表示选择元素内容的之前内容或之后内容。
- 伪元素控制的内容和元素是没有差别的,但是它本身只是基于元素的抽象,并不存在于⽂档中,所以称为伪元素。⽤于将特殊的效果添加到某些选择器
2)伪类与伪元素的区别
- 表示⽅法
- CSS2 中伪类、伪元素都是以单冒号:表示,
- CSS2.1 后规定伪类⽤单冒号表示,伪元素⽤双冒号::表示,
- 浏览器同样接受 CSS2 时代已经存在的伪元素(:before, :after, :first�line, :first-letter 等)的单冒号写法。
- CSS2 之后所有新增的伪元素(如::selection),应该采⽤双冒号的写法。
- CSS3中,伪类与伪元素在语法上也有所区别,伪元素修改为以::开头。浏览器对以:开头的伪元素也继续⽀持,但建议规范书写为::开头
- 定义不同
- 伪类即假的类,可以添加类来达到效果
- 伪元素即假元素,需要通过添加元素才能达到效果
- 总结:
- 伪类和伪元素都是⽤来表示⽂档树以外的”元素”。
- 伪类和伪元素分别⽤单冒号:和双冒号::来表示。
- 伪类和伪元素的区别,关键点在于如果没有伪元素(或伪类),
- 是否需要添加元素才能达到效果,如果是则是伪元素,反之则是伪类。
4)相同之处:
- 伪类和伪元素都不出现在源⽂件和DOM树中。也就是说在html源⽂件中是看不到伪类和伪元素的。不同之处:
- 伪类其实就是基于普通DOM元素⽽产⽣的不同状态,他是DOM元素的某⼀特征。
- 伪元素能够创建在DOM树中不存在的抽象对象,⽽且这些抽象对象是能够访问到的。
12.绝对定位
小提示:这个建议大家好好回忆一下,例如子元素是相对父元素的padding、border还是content进行定位之类的,当时面试官问的就这么细。13.说说z-index有什么需要注意的地方
14.熟悉CSS3动画么
15.Flex实现两列布局
.box {
height: 200px;
display: flex;
}
.box > div {
height: 100%;
}
.box-left {
width: 200px;
background-color: blue;
}
.box-right {
flex: 1; // 设置flex-grow属性为1,默认为0
overflow: hidden;
background-color: red;
}
16.绝对定位、固定定位和z-index
小提示:感谢CBU技术部的面试官。
绝对定位
- 一旦给元素加上
absolute
或float
就相当于给元素加上了display:block
absolute
元素覆盖正常文档流内元素(不用设z-index,自然覆盖)可以减少重绘和回流的开销(如
absolute+ top:-9999em
,或absolute + visibility:hidden
,将动画效果放到absolute
元素中)属性介绍
static
,默认值。位置设置为static的元素,它始终会处于文档流给予的位置。inherit
,规定应该从父元素继承 position 属性的值。但是任何的版本的 Internet Explorer (包括 IE8)都不支持属性值 “inherit”。fixed
,生成绝对定位的元素。默认情况下,可定位于相对于浏览器窗口的指定坐标。元素的位置通过 “left”, “top”, “right” 以及 “bottom” 属性进行规定。不论窗口滚动与否,元素都会留在那个位置。但当祖先元素具有transform
属性且不为none时,就会相对于祖先元素指定坐标,而不是浏览器窗口。absolute
,生成绝对定位的元素,相对于距该元素最近的已定位的祖先元素进行定位。此元素的位置可通过 “left”、”top”、”right” 以及 “bottom” 属性来规定。relative
,生成相对定位的元素,相对于该元素在文档中的初始位置进行定位。通过 “left”、”top”、”right” 以及 “bottom” 属性来设置此元素相对于自身位置的偏移。
浮动、绝对定位和固定定位会脱离文档流,相对定位不会脱离文档流,绝对定位相对于该元素最近的已定位的祖先元素,如果没有一个祖先元素设置定位,那么参照物是body层。
绝对定位相对于包含块的起始位置:
- 如果祖先元素是块级元素,包含块则设置为该元素的内边距边界。
- 如果祖先元素是行内元素,包含块则设置为该祖先元素的内容边界。
问答题:
- 定位的元素的起始位置为父包含块的内边距(不会在border里,除非使用负值,会在padding里)
- 定位的元素的margin还是能起作用的
- background属性是会显示在border里的
- z-index是有层叠层级的,需要考虑同一个层叠上下文的层叠优先级
- z-index是负值不会覆盖包含块的背景色(但是如果有内容,会被包含块的内容覆盖)
- z-index的值影响的元素是定位元素以及flex盒子
- 上面一个定位元素,下面一个正常流的元素,定位元素会覆盖在正常流元素之上,除非给z-index是负值
- 页面根元素html天生具有层叠上下文,称之为“根层叠上下文”
17.css预编译语言是什么
18.pc端和移动端像素不同,如何兼容?
第一种是通过响应式或页面终端判断去实现一套资源适配所有终端;
优势:只需维护一套资源,维护成本较低。
劣势:需加载适配各个终端的各个资源,在不同终端通过响应式布局实现不同展现,部分交互效果需要在页面中做终端判断,代价较大,若图片资源为一套,部分图片在超高分辨率设备(例如iphone系列)下会失真,且在非wifi情况下即使加了延时加载也易出现加载慢的情况。
技术选型:jquery(或原生js等)+ 响应式 + 前端模块加载器(seajs或RequireJS等)+ css预处理器(sass 或less等)。jquery较好的兼容性配合响应式可相对代价较小地实现跨终端。前端模块加载器主要负责按需加载,以提高页面加载速度,css预处理器 的变量、运算、嵌套等特性可大大提高手动计算响应式的效率,妈妈再也不用担心我把比例算错了。当然后两者可参考需求及成本决定是否采用。
第二种是通过终端判断分别调取两套资源以适配所有终端。
优势:可根据不同端做个性设计及个性化信息推送且可按需加载,如移动端可配合重力感应、不同手势做各种炫酷拽效果,pc页面可不受流量限制做适合pc端的效果。
劣势:需维护两套资源,维护成本增加。
技术选型:zepto(或xui等移动端轻量级框架)+ 响应式 + 前端模块加载器 + css预处理器 + 终端适配。zepto作为jquery的移动端版本,依然延续其自身优势,大幅优化了移动端API且摒弃了兼容”非现代浏览器”的冗余代码,成为移动端轻 便可用的js框架代表,对于习惯了jquery的同学来说简直是不二之选!
终端适配目前一般通过ua判断来实现。ua判断可放在服务端也可放在页面中,在代理服务器中做跳转更快、更准确且不走应用程序层,即使浏览器禁用了js依然可以跳转到相应的地址,同时秉承着公共服务放在服务端这样的云端服务理念,我们选择了通过代理服务器做终端适配。
User-Agent嗅探,即Web浏览器发送一个Web页面或资源请求时,会发送一个User-Agent首部作为HTTP请求的一部分,那么我们就可以在服务器端获取想要的信息,进而判断并引导用户到达相应的页面地址。
二、pc上的网站在移动端上怎么办?
如果把移动端的可视区域(320-768)的话,大部分网站都会因为太窄而显示错乱;所以浏览器默认把viewport设置为一个较宽的值 980px或1024px,至少保证PC网站在移动端上可以显示,只不过出现了横向滚动条而已。
19.box-sizing
**box-sizing**
属性定义了应该如何计算一个元素的总宽度和总高度。
属性值
content-box
标准盒子模型
默认值,标准盒子模型。[width](https://developer.mozilla.org/zh-CN/docs/Web/CSS/width)
与[height](https://developer.mozilla.org/zh-CN/docs/Web/CSS/height)
只包括内容的宽和高, 不包括边框(border),内边距(padding),外边距(margin)。注意: 内边距、边框和外边距都在这个盒子的外部。 比如说,.box {width: 350px; border: 10px solid black;}
在浏览器中的渲染的实际宽度将是 370px。 尺寸计算公式:width
= 内容的宽度height
= 内容的高度
宽度和高度的计算值都不包含内容的边框(border)和内边距(padding)。border-box
ie盒模型[width](https://developer.mozilla.org/zh-CN/docs/Web/CSS/width)
和[height](https://developer.mozilla.org/zh-CN/docs/Web/CSS/height)
属性包括内容,内边距和边框,但不包括外边距。这是当文档处于 Quirks模式 时Internet Explorer使用的盒模型。注意,填充和边框将在盒子内 , 例如,.box {width: 350px; border: 10px solid black;}
导致在浏览器中呈现的宽度为350px的盒子。内容框不能为负,并且被分配到0,使得不可能使用border-box使元素消失。 尺寸计算公式:_width_
= border + padding + 内容的宽度_height_
= border + padding + 内容的高度20.height:100%和height:100vh的区别
vw:viewpoint width,视窗宽度,1vw等于视窗宽度的1%。vh:viewpoint height,视窗高度,1vh等于视窗高度的1%。vmin:vw和vh中较小的那个。vmax:vw和vh中较大的那个。
vh就是当前屏幕可见高度的1%,也就是说
height:100vh == height:100%;
但是当元素没有内容时候,设置height:100%,该元素不会被撑开,此时高度为0,
但是设置height:100vh,该元素会被撑开屏幕高度一致。
- 居中对齐的方式
- bfc
块级格式化上下文, scope中改变 element css
1.样式穿透 >>> .el-input { width: 178px; }
::deep Sass 之类的预处理器无法正确解析 >>> 需要用::deep
2.3.命名空间。
flex兼容性 ie都不兼容
- 解决css3的兼容性问题 postcss
https://www.cnblogs.com/mmykdbc/p/6921608.html21.box-sizing
**box-sizing**
属性定义了应该如何计算一个元素的总宽度和总高度。属性值
content-box
默认值,标准盒子模型。[width](https://developer.mozilla.org/zh-CN/docs/Web/CSS/width)
与[height](https://developer.mozilla.org/zh-CN/docs/Web/CSS/height)
只包括内容的宽和高, 不包括边框(border),内边距(padding),外边距(margin)。注意: 内边距、边框和外边距都在这个盒子的外部。 比如说,.box {width: 350px; border: 10px solid black;}
在浏览器中的渲染的实际宽度将是 370px。 尺寸计算公式:width
= 内容的宽度height
= 内容的高度
宽度和高度的计算值都不包含内容的边框(border)和内边距(padding)。border-box
[width](https://developer.mozilla.org/zh-CN/docs/Web/CSS/width)
和[height](https://developer.mozilla.org/zh-CN/docs/Web/CSS/height)
属性包括内容,内边距和边框,但不包括外边距。这是当文档处于 Quirks模式 时Internet Explorer使用的盒模型。注意,填充和边框将在盒子内 , 例如,.box {width: 350px; border: 10px solid black;}
导致在浏览器中呈现的宽度为350px的盒子。内容框不能为负,并且被分配到0,使得不可能使用border-box使元素消失。 尺寸计算公式:_width_
= border + padding + 内容的宽度_height_
= border + padding + 内容的高度22.1px边框问题
https://www.cnblogs.com/lyt0207/p/12350741.html23.分析比较 opacity: 0、visibility: hidden、display: none 优劣和适用场景
display: none (不占空间,不能点击)(场景,显示出原来这里不存在的结
构)
visibility: hidden(占据空间,不能点击)(场景:显示不会导致页面结
构发生变动,不会撑开)
opacity: 0(占据空间,可以点击)(场景:可以跟 transition 搭配)
如何实现样式隔离
解题:
- 初阶:
- 是什么:
- 为什么:
- 全局污染:原生CSS不支持局部作用域,容易出现全局冲突,特别在当前 spa、微前端 盛行的情况下,多人同时开发一个应用时,如果没有规则限制,很容易出现样式冲突
- 层叠混乱:并且css支持层叠,即使冲突了也没法很快知道
- 依赖管理混乱:并且,你很难知道某个样式规则被哪些地方用到,随着项目的发展你可能会积累一堆实际已经没用,但不敢删除的样式规则(append-only stylesheets)
- 性能差、维护成本高
- 引入顺序、组件嵌套,都可能导致样式冲突
- 怎么做:BEM、CSS modules、CSS Layer、css-in-js(styled-component)、web component、iframe、vue-scoped
- 中阶:
- BEM命名规则:使用简单,可读性强(Block)、元素(Element)、修饰符(Modifier),
- 缺点是依赖开发者遵循命名规则,容易出问题;依然有命名成本,需要小心规避不出现冲突,可能导致命名会特别长
- 包括 antd 之类的组件库,至今依然使用类似 bem 的命名规则
- CSS Modules:模块化的 css 文件,这是一种在构建时添加 scope 信息的工程化手段,例如使用 css-loader 并设置
modules=true
- 简单易用,能够用工具替代规范约束;能够复用一堆 css 预处理器
- 缺点:依赖构建工具,可能影响构建速度;最终代码可读性差,debug 成本高;css-modules 能力比较弱,不支持变量等,通常需要配合 less 等预处理器使用 ```javascript .title { color: red; }
- BEM命名规则:使用简单,可读性强(Block)、元素(Element)、修饰符(Modifier),
._3zyde4l1yATCOkgn-DBWEL { color: red; }
- CSS-IN-JS:把样式代码直接写在组件中,并最终生成为 style 代码 + 唯一选择器,插入页面;或生成行内样式,插入组件标签中
- 优点:可选择工具非常多 styled-componets、vanilla-extract 等;样式与组件强相关,不太会造成历史遗留代码问题;
- 缺点:大多数都是运行时生成样式代码,运行时开销大(运行时代码 + 动态生成);代码可读性差,不容易 debug;不能复用成熟的预处理工具
![image.png](https://cdn.nlark.com/yuque/0/2022/png/26698409/1661669838390-eff70638-fb52-4455-95b7-0889381fb289.png#clientId=u641cf19f-60ab-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=634&id=u72c23f97&margin=%5Bobject%20Object%5D&name=image.png&originHeight=860&originWidth=1080&originalType=binary&ratio=1&rotation=0&showTitle=false&size=323755&status=done&style=none&taskId=ue3cc53f3-55fb-46da-92e1-f96f6a2ceec&title=&width=796)
- iframe:嵌套子页面
- 优点:严格意义的样式与内容隔离
- 缺点:iframe 太重,成本略高,除微应用场景外不建议使用;严格隔离,所以无法影响全局样式
- web component:用于封装html结构、js逻辑、样式结构的浏览器原生 api,能够有效隔离 web component 与页面代码
- 优点:浏览器原生支持;严格意义上的样式隔离,与 iframe 效果差不多;
- 缺点:学习成本略高;浏览器兼容问题;无法影响全局样式
- Vue Scoped:vue sfc 提供的样式隔离手段
- 优点:简单,且支持 deep 等指令后,能够实现子组件的样式效果;配合 sfc 规则,样式结构更清晰
- 缺点:只适用于 vue 框架;只适用于组件级别的样式定义
```javascript
<style scoped>
.example {
color: red;
}
</style>
<template>
<div class="example">hi</div>
</template>
<style>
.example[data-v-f3f3eg9] {
color: red;
}
</style>
<template>
<div class="example" data-v-f3f3eg9>hi</div>
</template>
- css 新 layer 规范:在 css 基础上加多一个 layer 概念,明确定义部分样式集的层叠优先级:对于处在不同层中的样式,无视样式本身的权重,后声明的层中的样式优先级更高,不在层中的样式优先级最高
- 优点:未来可期;算是解决问题的一种新尝试;
- 缺点:本质上,只是一个组织 CSS、避免选择器权重导致问题的方式,不是样式隔离手段;还未成为正式规范,但算的上一个创新特性,未来必然会影响 css 写法
- 高阶:
- 可能顺带复习一下你所熟悉的 css-in-js 工具的实现原理,按需介绍
- 可以重点提一提 vanilla-extract,这是一个 0 运行时的高效 css-in-js 框架