前言
CSS大家肯定都是会的但是每个人所撑握地情况都不一样,特别是已经工作几年的前辈(这里指的是我司)很多CSS玩法都不知道,可能他们已经习惯了用组件, 但是面试的时候又不可避免问,所以我整理了下CSS比较晦涩难懂的点总结写了这篇文章,在最后也会有些面试中常问的CSS相关面试题,看完全文面试就不用慌了 。
对了,在这里说一下,我目前是在职web前端开发,如果你现在正在学习前端,了解前端,渴望成为一名合格的web前端开发工程师,在入门学习前端的过程当中有遇见任何关于学习方法,学习路线,学习效率等方面的问题,都可以随时关注并私信我:前端,我都会根据大家的问题给出针对性的建议,缺乏基础入门的视频教程也可以直接来找我,我这边有最新的web前端基础精讲视频教程, 还有我做web前端技术这段时间整理的一些学习手册,面试题,开发工具,PDF文档书籍教程,都可以直接分享给大家。
目录
在线卑微,如果觉得这篇文章对你有帮助的话欢迎大家点个赞
css大三特性是css最重要的部分,可以说如果了解了这三大特性就对css撑握了一半,对于属性只不过是记不记得住的事,而这个是重在理解。
在讲这三个特性之前我们需要来全面了解下选择器。
下面我将选择进行划分为三大部分,对于基本选择器我就不说了,主要讲下伪类选择器,组合选择器及它们各自的使用场景。
基本选择器
算了还是讲下属性选择器吧 ,这个选择器我在项目开发中还是用到过的
直接看例子:
/* 匹配包含title属性的a标签 => <a title> */a[title] {color: purple;} /* 存在href属性并且属性值为"http://beige.world"的<a>标签*//* <a href="http://beige.world"> */ a[href="http://beige.world"] {color: green;}/* 存在href属性并且属性值包含"baidu"的<a>标签*/ /* <a href="https://baidu.com/we"> <a href="https://fanyi.baidu.com/we"> <a href="https://pan.baidu.com/we"> */ a[href*="baidu"] {font-size: 20px;}/* 存在id属性并且属性值结尾是"-wrapper"的<div>标签 */ /* <div id="btn-wrapper"> <div id="menu-wrapper"> <div id="pic-wrapper"> */ div[id$="-wrapper"] {display: flex;}/* 存在class属性并且属性值包含以空格分隔的"logo"的<div>元素 */ /* <div id="aaa logo"> <div id="bbb logo"> */ div[class~="logo"] { padding: 2px; }
结构伪类
先讲这两比较作用类似的:nth-child(n) | nth-of-type(n)
结构
<ul> <li>1</li> <li> <p>a1</p> <div>b1</div> <p>a2</p> <div>b2</div> </li> <li>3</li> <li>4</li> <li>5</li></ul>
CSS
// 第一个li => <li>1</li>ul li:first-child { background-color: lightseagreen;} // 最后一个li => <li>5</li>ul li:last-child { background-color: lightcoral;}// 第三个li => <li>3</li>ul li:nth-child(3) { background-color: aqua; } // 第二个li下的第一个div(不是div标签的都不算) => <div>b1</div>ul li:nth-child(2) > div:nth-of-type(1) {background-color: red}
它俩的区别
下面讲讲nth-child()括号中的公式,这个算是这个选择器的亮点了。
注意⚠:本质上就是选中第几个子元素
对于这里面的公式平常也用不到太复杂的,我说下我的技巧:nth-child(3n + 3); 这里的n可以看做几个为一组,3可以看做选这组的第几个。
例: nth-child(5n + 3) :5个为一组,选一组中的第三个。 对于"-"号就表示选择的是前面的。
组合选择器本质上就是通过连接符来对两个选择器进行组合
上面这两我就不说了,相信大家都用烂了。主要说说下面这两个。
结构
<div class="box1"> <div>One</div> <div>Two!</div> <div>Three</div> <p>pppp</p> </div> <div class="box2"> <div>One2</div> <p>pppp1</p> <div>Two2!</div> <p>pppp2</p> </div>
选择器解析
<style> /* (+标识)符介于两个选择器之间,当第二个选择器匹配的元素紧跟着第一个元素后面并且它们都是同一个父亲 .box1 div:first-of-type(A元素) div(B元素) 匹配紧跟着A的B */ .box1 div:first-of-type+div { color: red; } .box1 div:first-of-type+p { color: red;} 筛选不到的 /* (~标识)符介于两个选择器之间,匹配第一个选择器元素后面所有匹配第二个选择器的同层级元素 .box2 div(A元素) p(B元素) 匹配所有A后面的B */ .box2 div~p { color: seagreen; } </style>
好了,在讲完这些选择器之后我们来看看它们的使用场景。
组合选择器可以用于:hover伪类操纵自己包含的子元素及以外的元素。举个例子
<div id='a'>元素1 <div id='b'>元素2</div></div><div id='c'>元素3 <div id='b'>元素2</div></div><div>同级元素1</div><div>同级元素2</div><div>同级元素3</div></body>
#a:hover > #b{....} #a:hover ~ div{....} // 鼠标停留在a元素的时候让所有同层级元素有某某样式// 防止选择器层级替换了下面的样式#a:hover + #c{....} // 鼠标停留在a元素的时候让同层级中的c元素有某某样式#a:hover + #c > #b{....} // 鼠标停留在a元素的时候让同层级中的c元素下的b元素有某某样式
上面这两选择器在做一些特效页的时候应该是会用到的。
效果
结构
<body> <div class="img-box enter-box"> <!-- 悬浮在这个盒子的时候动态添加enter-box类名 --> <img src="http://resource.beige.world/imgs/beige.jpg" alt=""> <div class="cover"> <h3>标题名称</h3> <p class="con">Bei Ge</p> <p class="brier">这里放内容简介,内容简介,这里放内容简介,内容简介,这里放内容简介,内容简介</p> <div class="handle"><span>.</span><span>.</span><span>.</span></div> </div> </div> <!-- 其他盒子 --> <div class="img-box">2</div> <div class="img-box">3</div> <div class="img-box">4</div> <div class="img-box">5</div></body>
样式
布局样式
<style> .img-box { position: relative; top: 100px; left: 200px; z-index: 1; display: inline-block; overflow: hidden; background: #70adc4; cursor: pointer; transition: transform .5s, box-shadow .3s; } .img-box img { width: 200px; height: 200px; opacity: 1; float: left; } .img-box .cover { width: 200px; height: 200px; padding: 15px; position: absolute; box-sizing: border-box; color: hotpink; } .img-box .cover h3 { margin-top: 10%; font-size: 24px; font-weight: bold; text-shadow: 0 0 2px #ccc; opacity: 0; transition: opacity .5s; } .img-box .cover .con { margin: 20px 0; font-style: italic; font-weight: bold; transform: translateX(-150%); } .img-box .cover .brier { font-size: 12px; transform: translateX(150%); } .img-box .cover .handle { position: absolute; right: 10px; bottom: -50px; font-size: 25px; transition: bottom 1s; /* 对于position的过渡动画, 不能用position, 直接用位置属性: left right top bottom */ } </style>
定义了一个animation动画
@keyframes textAnimation { /* 0% { transform: translateX(150%); } */ 100% { transform: translateX(0); }}
悬浮在盒子设置样式
.img-box:hover { transform: scale(1.1); box-shadow: 2px 2px 13px 3px #ccc;}.img-box:hover img { opacity: .5;}.img-box:hover .cover h3 { opacity: 1;}.img-box:hover p { animation: textAnimation .6s ease-out forwards; /* forwards让动画停留在最后一帧 */}.img-box:hover .cover .handle { bottom: 5px;}.enter-box:hover ~ .img-box { background-color: transparent; color: wheat;}.enter-box:hover + .img-box { color: red;}
上面这个例子有些还没有讲,但是相信大家之前也都学过,后文中也会说。主要会说些细节方面的东西
这里需要注意在使用伪类Hover的注意点,在使用他影响子级元素的时候尽量将选择器写全。例:
先看下效果
上面的效果相信大家都能写出来,所以我要讲的肯定不是怎么去实现这个效果,我要说下使用Hover时的一些细节。
结构比较简单
flex类名用于布局实现重置和水平居中,box: 绿色盒子;center: 紫色盒子 inner: 橙黄色盒子
<div class="box flex"> <div class="center flex"> <div class="inner"></div> </div></div>
我们用了一个:hover让鼠标虚浮的时候让盒子变红
.box:hover div { background-color: red;}
这里有一个问题不知道大家想过没有,为什么我这段代码只让center盒子变红了,inner为什么没有变红呢???
展开查看
因为CSS选择器的优先级!
我们在实现的时候一般都会像下面这样写吧,这个时候使用伪类选择器改变元素样式的时候就要注意选择器优先级的问题了。
.box .center { width: 150px; height: 150px; background-color: blueviolet;}.box .center .inner { width: 100px; height: 100px; background-color: coral;}
这段代码的优先级比.box .center高,所以他也就只能覆盖它了。
.box:hover div { background-color: red;}
相信我们很多人如果在写鼠标悬浮大盒子让最里面的inner盒子变色的时候,都会这么写吧:
.box:hover .inner { background-color: red;}
有用吗?没用!
注意⚠: 优先级还是没有.box .center .inner高。
所谓层叠性是指多种CSS样式的叠加。是浏览器处理冲突的一个能力,如果一个属性通过两个相同选择器设置到同一个元素上,那么这个时候一个属性就会将另一个属性层叠掉
原则:
CSS层叠性最后的执行口诀: 长江后浪推前浪,前浪死在沙滩上。
继承性
子标签会继承父标签的某些样式,如文本颜色和字号。 想要设置一个可继承的属性,只需将它应用于父元素即可。简单的理解就是: 子承父业
CSS继承性口诀: 龙生龙,凤生凤,老鼠生的孩子会打洞
我们恰当地使用继承可以简化代码,降低CSS样式的复杂性。比如有很多后代元素都需要某个样式,可以给父级指定一个,这些孩子继承过来就好了。
注意点:在CSS的继承中不仅仅是儿子可以继承, 只要是后代都可以继承
可继承的属性
控制继承
注意点: 对于天生自带的继承属性我们可以控制它是否需要继承
四个属性
效果图
演示
<ul style="color: green;"> <li class="default">Default <a href="#">link</a> color</li> <li class="inherit">Inherit the <a style="color: inherit;" href="#">link</a> color</li> <li class="initial">Reset the <a style="color: initial;" href="#">link</a> color</li> <li class="unset">Unset the <a style="color: unset;" href="#">link</a> color</li></ul>
如果我们需要控制元素所有属性的继承使用all属性
.inherit a { all: initial; /* 将所有的属性都恢复成默认值(天生继承也不再继承) */ /* 行内设置过的除外:你的层级干不过人家 */}
这个不难,但是忽略很容易绕晕。其实,我们修改样式,一定要看该标签有没有被选中。
(1) 如果选中了,那么以上面的公式来计权重。谁大听谁的。 (2) 如果没有选中,那么权重是0,因为继承的权重为0.
控制继承在我们封装自己的组件的时候是会用到的,我们在封装组件需要沿用样式,有些默认情况下不可继承父元素的属性:box-sizing,这个其实用的就很多。
优先级
要想了解优先级,肯定得了解选择器;但是选择器非常多的,前面列举的是日常开发用的比较多,其他的你可能一辈子都用不到,这里贴出C1~C4的选择器,感兴趣的同学可以看看。
定义CSS样式时,经常出现两个或更多选择器应用在同一元素上,此时,
关于CSS权重,我们需要一套计算公式来去计算,这个就是 CSS Specificity(特殊性)
值从左到右,左面的最大,一级大于一级,数位之间没有进制,级别之间不可超越。
常用的选择器记法:
权重叠加
我们经常用组合选择器,是有多个基础选择器组合而成,那么此时,就会出现权重叠加。
就是一个简单的加法计算
注意⚠: 数位之间没有进制 比如说: 0,0,0,5 + 0,0,0,5 = 0,0,0,10 而不是 0,0, 1, 0, 所以不会存在10个div能赶上一个类选择器的情况。
important适用优先级
#id .box div { color: red !important;}#id div.box div { color: green !important; // 使用这个选择器中的颜色}
下面来几道题,全对才算通过了噢
<style type="text/css"> .c1 .c2 div{ color: blue; } div #box3 { color:green; } #box1 div { color:yellow; }</style></head><body><div id="box1" class="c1"> <div id="box2" class="c2"> <div id="box3" class="c3"> 文字 </div> </div></div></body>
什么颜色??
yellow 上面两选择器的层级都是一样的, 后者覆盖前者
<style type="text/css"> #father #son{ color:blue; } #father p.c2{ color:black; } div.c1 p.c2{ color:red; } #father{ color:green !important; }</style></head><body><div id="father" class="c1"> <p id="son" class="c2"> 试问这行字体是什么颜色的? </p></div></body>
blue
<body> <style> div.parent { width: 300px; height: 300px; border: 10px solid #000; font-size: 46px; text-shadow: 3px 13px 4px green; box-sizing: border-box } div.child { width: 200px; height: 200px; background-color: brown; border: 5px solid #000; width: inherit; box-sizing: inherit; font-size: 80px; } </style></head> <div class="parent"> <div id="child" class="child">123</div> </div> <!-- child: 字体多大? 有没有文字阴影? 真实内容的宽高是多少? --></body>
字体:80,有文字阴影,真实内容的宽:290px 高190px
讲下这最后一题
文字阴影有:因为从父元素中继承到了,字体: 80px;
真实内容宽290px, 高190px
flex布局相信大家也都用烂了,用来让盒子垂直和水平居中好用的一批
父项常用属性
flex-direction
在 flex 布局中,是分为主轴和侧轴两个方向,同样的叫法有 : 行和列、x 轴和y 轴
主轴和侧轴是会变化的,就看 flex-direction 设置谁为主轴,剩下的就是侧轴。而我们的子元素是跟着主轴来排列的
flex-wrap设置是否换行
justify-content 设置主轴上的子元素排列方式
效果图
这里讲下space-around和space-evenly
space-evenly:项目两侧之间的间距与项目与容器两侧的间距相等,相当于除去项目宽度和容器和项目的两侧间距,剩下的平均分配了剩余宽度作为项目左右margin。
**设置侧轴上的子元素排列方式:align-items(单行)/align-content(多行) **
上图写能设置多行只能用于子项出现 换行 的情况(多行),在单行下是没有效果的。
效果跟上面是一样的只不过是方向换了,上面是元素在主轴上排列,这个是在侧轴上,至于侧轴是不是Y轴就看你的flex-direciton怎么设置的了
子项常见属性
flex-grow
默认0,用于决定项目在有剩余空间的情况下是否放大,默认不放大;注意,即便设置了固定宽度,也会放大。
假设第一个项目默认为0,第二个项目为flex-grow:2,最后一个项目为1,则第二个项目在放大时所占空间是最后项目的两倍。
可以这么理解:
假设三个盒子分别都设置了上面的属性: 那就将剩余空间分成6份, 各占自己的份数假设前两个没有设置, 就最后一个设置了flex: 3 === flex: 1, 那就将剩余空间都给它
flex-shrink
默认1,用于决定项目在空间不足时是否缩小,默认项目都是1,即空间不足时大家一起等比缩小;注意,即便设置了固定宽度,也会缩小。但如果某个项目flex-shrink设置为0,则即便空间不够,自身也不缩小。
上图中第二个项目flex-shrink为0,所以自身不会缩小。
flex-basis
默认auto,用于设置项目宽度,默认auto时,项目会保持默认宽度,或者以width为自身的宽度,但如果设置了flex-basis,权重会width属性高,因此会覆盖widtn属性。
上图中先设置了flex-basis属性,后设置了width属性,但宽度依旧以flex-basis属性为准。
注意⚠: 如果当容器中有多个盒子并且还宽度100%, flex-basis会被影响, 如下图
解决办法就是在我们设置flex-basis宽度时, 最好给他设置flex-shrink为0不缩放
transform
2D的属性相信大家都会用了, 本文主要深究transform的3D属性
透视(perspective)
在讲3D之间先来了解一下透视(视距),只有了解了透视我们才能理解3D的物体投影在2D平面上
注意: 透视需要写在被视察元素的父盒子上面
拿图说话
来个例子
给实例的父元素设置: perspective: 200px;
上面我们在div的父盒子上设置了perspective,也就是说从3D成像的角度来讲我们人眼距离屏幕div是200的视距,translate3D设置Z轴让div往前挪了100,视距变小距离我们人眼距离也就越小,所以看到的div也就变大了。 (可以想像成在500米远看见的人, 和5米看见的人。)
translate3d(x, y, z)
3D的特点
三维坐标系
3D 呈现 transform-style
transform-style:控制子元素是否开启三维立体环境,代码写给父级,但是影响的是子盒子
效果图
body { perspective: 500px;}.box { position: relative; width: 200px; height: 200px; margin: 100px auto; transition: all 2s; /* 让子元素保持3d立体空间环境 */ transform-style: preserve-3d;}.box:hover { transform: rotateY(60deg);}.box div { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-color: pink;}.box div:last-child { background-color: purple; transform: rotateX(60deg);}
rotate3d(x, y, z)
3D 旋转指可以让元素在三维平面内沿着 x 轴、y 轴、z 轴 或者自定义轴进行旋转
例子:
<ul> <li> <div class="box"> <div class="front">公众号:</div> <div class="bottom">前端留学生</div> </div> </li></ul>
ul li { float: left; margin: 0 5px; width: 120px; height: 35px; list-style: none; /* 一会我们需要给box 旋转 也需要透视 干脆给li加 里面的子盒子都有透视效果 */ perspective: 500px;}.box { position: relative; width: 100%; height: 100%; transform-style: preserve-3d; transition: all .4s;}.box:hover { transform: rotateX(90deg);}.front,.bottom { position: absolute; left: 0; top: 0; width: 100%; height: 100%;}.front { background-color: pink; z-index: 1; transform: translateZ(17.5px);}.bottom { background-color: purple; /* 这个x轴一定是负值 */ /* 我们如果有移动 或者其他样式,必须先写我们的移动 */ transform: translateY(17.5px) rotateX(-90deg);}
动画(animation)是 CSS3 中最具颠覆性的特征之一,可通过设置多个节点来精确的控制一个或者一组动画,从而实现复杂的动画效果, 先定义动画再调用定义好的动画
动画序列
0% 是动画的开始,100 % 是动画的完成,这样的规则就是动画序列
@keyframes move{ 0% { transform: translate(0px) } form { transform: translate(0px) } 100% { transform: translate(500px, 0) } to { transform: translate(500px, 0) }}
动画常见属性
动画简写方式
/* animation: 动画名称 持续时间 运动曲线 何时开始 播放次数 是否反方向 起始与结束状态 */animation: name duration timing-function delay iteration-count direction fill-mode
除了名字,持续时间,何时开始有严格顺序要求其它随意
CSS实现扫描二维码
效果
BFC(Block formatting context)直译为"块级格式化上下文"。
在讲BFC之前得先说下display的属性值,只有它符合成为条件才资格触发BFC机制
那些属性值会具有BFC的条件
不是所有的元素模式都能产生BFC,w3c 规范: display 属性为 block, list-item, table 的元素,会产生BFC.
大家有没有发现这个三个都是用来布局最为合理的元素,因为他们就是用来可视化布局。注意其他的,display属性,比如 line 等等,他们创建的是 IFC ,我们下面研究。
这个BFC 有着具体的布局特性:
有宽度和高度,有 外边距margin 有内边距padding 有边框 border。就好比,你有了练习武术的体格了。 有潜力,有资质。
什么情况下可以让元素产生BFC
以上盒子具有BFC条件了,就是说有资质了,但是怎样触发才会产生BFC,从而创造这个封闭的环境呢?
就好比,你光有资质还不行,你需要一定额外效果才能触发的武学潜力,要么你掉到悬崖下面,捡到了一本九阴真经,要么你学习葵花宝典,欲练此功必先....
同样,要给这些元素添加如下属性就可以触发BFC。
它是一个独立的渲染区域,只有Block-level box参与, 它规定了内部的Block-level Box如何布局,并且与这个区域外部毫不相干。
白话文: 孩子在家里愿意怎么折腾都行,但是出了家门口,你就的乖乖的,不能影响外面的任何人。
(1) 清除元素内部浮动
只要把父元素设为BFC就可以清理子元素的浮动了,最常见的用法就是在父元素上设置overflow: hidden样式
主要用到
计算BFC的高度时,自然也会检测浮动或者定位的盒子高度。
(2) 解决外边距合并(塌陷)问题
主要用到
盒子垂直方向的距离由margin决定。属于同一个BFC的两个相邻盒子的margin会发生重叠
属于同一个sBFC的两个相邻盒子的margin会发生重叠,那么我们创建不属于同一个BFC,就不会发生margin重叠了。
(3) 制作右侧自适应的盒子问题
主要用到
普通流体元素BFC后,为了和浮动元素不产生任何交集,顺着浮动边缘形成自己的封闭上下文
BFC 总结
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。包括浮动,和外边距合并等等,因此,有了这个特性,我们布局的时候就不会出现意外情况了。
IFC(inline Formatting Context)叫做“行级格式化上下”相对BFC比较简单且问的也不是很多,这里大概做个了解
布局规则如下:
哪些属性开启了性能加速
何为硬件加速:就是将浏览器的渲染过程交给GPU(Graphics Processing Unit)处理,而不是使用自带的比较慢的渲染器。这样就可以使得animation与transition更加顺畅
我们可以在浏览器中用CSS开启硬件加速,使GPU发挥功能,从而提升性能
所谓GPU,就是图形处理器的缩写,相当于PC中的显卡。手机中的GPU也是为了对图形、图像处理而存在的,所谓强制渲染,就是hwa(hardware acceleration硬件加载)的一种,其存在的意义就是为了分担cpu的负担,其原理是通过GPU对软件图形的处理来减轻CPU的负担。从而使应用软件能够以更快的速度被处理,以达到提速的目的。
硬件加速的原理
浏览器接收到页面文档后,会将文档中的标记语言解析为DOM树。DOM树和CSS结合后形成浏览器构建页面的渲染树。渲染树中包含大量的渲染元素,每个渲染元素会被分到一个图层中,每个图层又会被加载到GPU形成渲染纹理,而图层在GPU中transform是不会触发repaint的,最终这些使用transform的图层都会由独立的合成器进程进行处理, CSS transform会创建了一个新的复合图层,可以被GPU直接用来执行transform操作。
浏览器什么时候会创建一个独立的复合图层呢?事实上一般是在以下几种情况下:
因为transform属性不会触发浏览器的repaint(重绘),而绝对定位absolute中的left和top则会一直触发repaint(重绘)。
为什么transform没有触发repaint呢?
简而言之,transform动画由GPU控制,支持硬件加载,并不需要软件方面的渲染。并不是所有的CSS属性都能触发GPU的硬件加载,事实上只有少数的属性可以,比如transform、opacity、filter
CSS animation、transform以及transition不会自动开启GPU加速,而是由浏览器的缓慢的软件渲染引擎来执行,那我们怎样才可以切换到GPU模式呢,很多浏览器提供了某些触发的CSS规则。
当浏览器检测到页面中某个DOM元素应用了某些CSS规则时就会开启,最显著的特征的元素是3D变化。
.cube{ translate3d(250px,250px,250px); rotate3d(250px,250px,250px,-120deg) scale3d(0.5,0.5,0.5);}
可能在一些情况下,我们并不需要对元素应用3D变幻的效果,那怎么办呢?这时候我们可以使用“欺骗”浏览器来开启硬件加速。虽然我们可能不想对元素应用3D变换,可我们一样可以开启3D引擎。例如我们可以用transform:translateZ(0);来开启硬件加速
.cube{ transform: translateZ(0);}
如果文章中有那块写得不太好或有问题欢迎大家指出,我也会在后面的文章不停修改。也希望自己进步的同时能跟你们一起成长。喜欢我文章的朋友们也可以关注一下
此时,年轻的我和你,轻装上阵;而后,富裕的你和我,满载而归。
作者:前端自学驿站
链接:
https://juejin.im/post/6888102016007176200
来源:掘金