知识点梳理
- 选择器的权重和优先级
- 盒模型
- 盒⼦⼤⼩计算
- margin 的重叠计算
- 浮动
float
- 浮动布局概念
- 清理浮动
- 定位
position
- ⽂档流概念
- 定位分类
- fixed 定位特点
- 绝对定位计算⽅式
flex
布局- 如何实现居中对⻬?
- 理解语义化
CSS3
动画- 重绘和回流
选择器的权重和优先级
CSS 选择器有很多, 不同的选择器的权重和优先级不⼀样, 对于⼀个元素, 如果存在多个选择器, 那 么就需要根据权重来计算其优先级。
权重分为四级,分别是:
- 代表内联样式,如
style="xxx"
,权值为1000
- 代表
ID
选择器, 如#content
,权值为100
; - 代表类、伪类和属性选择器,如
.content
、:hover
、[attribute]
,权值为10
- 代表元素选择器和伪元素选择器,如
div
、p
,权值为1
需要注意的是: 通⽤选择器(*) 、⼦选择器 ( > ) 和相邻同胞选择器 ( + ) 并不在这四个等级中, 所 以他们的权值都为 0。 权重值⼤的选择器其优先级也⾼, 相同权重的优先级⼜遵循后定义覆盖前⾯定 义的情况。
盒模型
什么是"盒子"
⼀开始学 CSS 基础知识的时候⼀定学过 padding
border
和 margin
,即内边 距、边框和外边距。它们三者就构成了⼀个“ 盒⼦ ” 。 就像我们收到的快递, 本来买了⼀部⼩⼩的⼿ 机, 收到的却是那么⼤⼀个盒⼦。因为⼿机⽩⾊的包装盒和⼿机机器之间有间隔层( 内边距),⼿机 ⽩⾊盒⼦有厚度,虽然很薄 (边框),盒⼦和快递箱⼦之间还有⼀层泡沫板(外边距)。这就是⼀个 典型的盒⼦。
题⽬: 盒⼦模型的宽度如何计算
题⽬: 盒⼦模型的宽度如何计算
<div style="padding:10px; border:5px solid blue; margin: 10px; width:300px;">
之前看过⼀篇⽂章,叫做《浏览器⼯作原理:新式⽹络浏览器幕后揭秘》,
⽂章⾔简意赅的介绍的浏览器的⼯作过程,web前端
</div>
⽂字内容的宽度 刚好是 300px , 也就是我们设置的宽度。
因此,在盒⼦模型中, 我们设置的宽度都是内容宽度, 不是整个盒⼦的宽度。 ⽽整个盒⼦的宽度是:(内容宽度
+ border
宽度 + padding
宽度 + margin
宽度) 之和 。 这样我们改四个中的其中⼀ 个, 都会导致盒⼦宽度的改变。这对我们来说不友好。
没关系, 这个东⻄不友好早就有⼈发现了,⽽且已经解决。
充满⽗容器的盒⼦
默认情况下,div
是 display:block
,宽度会充满整个⽗容器。如下图:
<div style="padding:10px; border:5px solid blue; margin: 10px;width:300px;">
之前看过⼀篇⽂章,叫做《浏览器⼯作原理:新式⽹络浏览器幕后揭秘》,
⽂章⾔简意赅的介绍的浏览器的⼯作过程,web前端
之前看过⼀篇⽂章,叫做《浏览器⼯作原理:新式⽹络浏览器幕后揭秘》,
⽂章⾔简意赅的介绍的浏览器的⼯作过程,web前端
</div>
但是别忘记,这个div是个盒⼦模型,它的整个宽度包括(内容宽度+border宽度
+padding宽度
+margin宽度
),整个的宽度充满⽗容器。
问题就在这⾥。如果⽗容器宽度不变,我们⼿动增⼤margin
、border
或 padding
其中⼀项的宽度值,都会导致内容宽度的减少。极端情况下,如果内容的宽度压缩到不能再压缩了(例如⼀个字的宽度),那么浏览器会强迫增加⽗容器的宽度。这可不是我们想要看到的。
包裹内容的盒⼦
这种情况下⽐较简单,内容的宽度按照内容计算,盒⼦的宽度将在内容宽度的基础上再增加(padding
宽度+border
宽度+margin
宽度)之和。
<div style="padding: 10px;border: 5px solid blue; margin: 10px; width: 300px">
之前看过⼀篇⽂章, 叫做《浏览器⼯作原理: 新式⽹络浏览器幕后揭秘》
</div>
box-sizing:border-box
前⾯提到,为盒⼦模型设置宽度,结果只是设置了内容的宽度,这个不合理。如何解决这⼀问题?答案就是为盒⼦指定样式:box-sizing:border-box
。
<div style="padding: 10px;border: 5px solid blue; margin: 10px; width: 300px; box-sizing: border-box">
之前看过⼀篇⽂章, 叫做《浏览器⼯作原理: 新式⽹络浏览器幕后揭秘》
</div>
上图中,为div设置了box-sizing:border-box
之后,300px的宽度是内容+padding+边框的宽度(不包括margin),这样就⽐较符合我们的实际要求了。建议⼤家在为系统写CSS时候,第⼀个样式是:
* {
box-sizing: border-box;
}
⼤名鼎鼎的Bootstrap也把box-sizing:border-box
加⼊到它的*
选择器中,我们为什么不这样做呢?
纵向margin重叠
这⾥提到margin,就不得不提⼀下margin的这⼀特性——纵向重叠。如<p>
的纵向margin是16px,那么两个<p>
之间纵向的距离是多少?——按常理来说应该是16 + 16 = 32px,但是答案仍然是16px。因为纵向的margin是会重叠的,如果两者不⼀样⼤的话,⼤的会把⼩的“吃掉”。
浮动float
float⽤于⽹⻚布局⽐较多,使⽤起来也⽐较简单,总结了⼀些⽐较重要、需要注意的知识点。
误解和误用
float被设计出来的初衷是⽤于⽂字环绕效果,即⼀个图⽚⼀段⽂字,图⽚float:left
之后,⽂字会环绕图⽚。
<div>
<img src="img/xxx.jpg" alt="" style="float: left">
⼀段⽂字⼀段⽂字⼀段⽂字⼀段⽂字⼀段⽂字⼀段⽂字⼀段⽂字⼀段⽂字⼀段⽂字
</div>
但是,后来⼤家发现结合float + div
可以实现之前通过table实现的⽹⻚布局,因此就被“误⽤”于⽹⻚布局了。
题目:为何 float 会导致父元素塌陷?
破坏性
float的破坏性——float破坏了⽗标签的原本结构,使得⽗标签出现了坍塌现象。导致这⼀现象的最根本原因在于:被设置了float的元素会脱离⽂档流。其根本原因在于float的设计初衷是解决⽂字环绕图⽚的问题。
包裹性
包裹性也是float的⼀个⾮常重要的特性,⼤家⽤float时⼀定要熟知这⼀特性。如果给div增float:left
之后,它突然变得紧凑了,宽度发⽣了变化,把内容中的三个字包裹了——这就是包裹性。为div设置了float之后,其宽度会⾃动调整为包裹住内容宽度,⽽不是撑满整个⽗容器。注意,此时div虽然体现了包裹性,但是它的display样式是没有变化的,还是display: block
。float为什么要具有包裹性?其实答案还是得从float的设计初衷来寻找,float是被设计⽤于实现⽂字环绕效果的。⽂字环绕图⽚⽐较好理解,但是如果想要让⽂字环绕⼀个div呢?此时div不被“包裹”起来的话,就⽆法实现环绕效果了。
清空格float
还有⼀个可能不是很熟悉的特性——清空格。
<div style="border: 2px solid blue; padding: 3px">
<img src="1.jpg" alt="" />
<img src="2.jpg" alt="" />
<img src="3.jpg" alt="" />
<img src="4.jpg" alt="" />
</div>
加上float:left
之后:
上⾯第⼀张图中,正常的img中间是会有空格的,因为多个img标签会有换⾏,⽽浏览器识别换⾏为空格,这也是很正常的。第⼆张图中,为img增加了float:left
的样式,这就使得img之间没有了空格,4个img紧紧挨着。
如果⼤家之前没注意,现在想想之前写过的程序,是不是有这个特性。为什么float适合⽤于⽹⻚排版(俗称“砌砖头”)?就是因为float排版出来的⽹⻚严丝合缝,中间连个苍蝇都⻜不进去。
“清空格”这⼀特性的根本原因是float会导致节点脱离⽂档流结构。它都不属于⽂档流结构了,那么它身边的什么换⾏、空格就都和它没了关系,它就尽量往⼀边靠拢,能靠多近就靠多近,这就是清空格的本质。
⽬:⼿写clearfix
clearfix
清除浮动的影响,⼀般使⽤的样式如下,统称clearfix
代码。所有float元素的⽗容器,⼀般情况下都应该加clearfix
这个class。
.clearfix:after {
content: '';
display: table;
clear: both;
}
.clearfix {
/* 兼容 IE 低版本 */
*zoom : 1;
}
<div class="clearfix">
<img src="1.jpg" alt="" style="float: left" />
<img src="2.jpg" alt="" style="float: left" />
</div>
小结
float的设计初衷是解决⽂字环绕图⽚的问题,后来误打误撞⽤于做布局,因此有许多不合适或者需要注意的地⽅。
- 圣杯布局
<style>
#container {
padding-left: 200px;
padding-right: 150px;
overflow: auto;
}
#container p {
float: left;
}
.center {
width: 100%;
background-color: lightcoral;
}
.left {
width: 200px;
position: relative;
left: -200px;
margin-left: -100%;
background-color: lightcyan;
}
.right {
width: 150px;
margin-right: -150px;
background-color: lightgreen;
}
.clearfix:after {
content: "";
display: table;
clear: both;
}
</style>
</head>
<body>
<div id="container" class="clearfix">
<p class="center">我是中间</p>
<p class="left">我是左边</p>
<p class="right">我是右边</p>
</div>
- 双飞翼布局
<style>
.float {
float: left;
}
#main {
width: 100%;
height: 200px;
background-color: lightpink;
}
#main-wrap {
margin: 0 190px 0 190px;
}
#left {
width: 190px;
height: 200px;
background-color: lightsalmon;
margin-left: -100%;
}
#right {
width: 190px;
height: 200px;
background-color: lightskyblue;
margin-left: -190px;
}
</style>
</head>
<body>
<div id="main" class="float">
<div id="main-wrap">main</div>
</div>
<div id="left" class="float">left</div>
<div id="right" class="float">right</div>
</body>
定位position
position⽤于⽹⻚元素的定位,可设置static/relative/absolute/fixed这些值,其中static是默认值。
题⽬:relative和absolute有何区别?
relative
相对定位relative可以⽤⼀个例⼦很轻松地演示出来。
然后我们在第三个<p>
上⾯,加上position:relative
并且设置left和top值,看这个<p>
有什么变化。
<p>第一段文字</p>
<p>第一段文字</p>
<p style="position:relative; top: 10px; left: 10px">第一段文字</p>
<p>第一段文字</p>
上图中,⼤家应该要识别出两个信息(相信⼤部分⼈会忽略第⼆个信息)
- 第三个
<p>
发⽣了位置变化,分别向右向下移动了10px
; - 其他的三个
<p>
位置没有发⽣变化,这⼀点也很重要。
relative会导致⾃身位置的相对变化,⽽不会影响其他元素的位置、⼤⼩。 这是relative的要点之⼀。还有第⼆个要点,就是relative产⽣⼀个新的定位上下⽂。
absolute
先写⼀个基本的demo。
<p>第一段文字</p>
<p>第一段文字</p>
<p style="background: pink;">第一段文字</p>
<p>第一段文字</p>
然后,我们把第三个<p>
改为position:absolute;
,看看会发⽣什么变化。
从上⾯的结果中,我们能看出⼏点信息:
-
absolute元素脱离了⽂档结构。和
relative
不同,其他三个元素的位置重新排列了。只要元素会脱离⽂档结构,它就会产⽣破坏性,导致⽗元素坍塌。(此时你应该能⽴刻想起来,float元素也会脱离⽂档结构。) -
absolute元素具有“包裹性”。之前
<p>
的宽度是撑满整个屏幕的,⽽此时<p>
的宽度刚好是内容的宽度。 -
absolute元素具有“跟随性”。虽然absolute元素脱离了⽂档结构,但是它的位置并没有发⽣变化,还是⽼⽼实实地呆在它原本的位置,因为我们此时没有设置top、left的值。absolute元素会悬浮在⻚⾯上⽅,会遮挡住下⽅的⻚⾯内容。
最后,通过给absolute元素设置top
、left
值,可⾃定义其内容,这个都是平时⽐较常⽤的了。这⾥需要注意的是,设置了top、left值时,元素是相对于最近的定位上下⽂来定位的,⽽不是相对于浏览器定位。
fixed
其实fixed和absolute是⼀样的,唯⼀的区别在于:absolute元素是根据最近的定位上下⽂确定位置,⽽fixed根据window(或者iframe)确定位置。
题⽬:relative、absolute和fixed分别依据谁来定位?
定位上下文
relative元素的定位永远是相对于元素⾃身位置的,和其他元素没关系,也不会影响其他元素。
fixed元素的定位是相对于window(或者iframe)边界的,和其他元素没有关系。但是它具有破坏性,会导致其他元素位置的变化。
absolute的定位相对于前两者要复杂许多。如果为absolute设置了top、left,浏览器会根据什么去确定它的纵向和横向的偏移量呢?答案是浏览器会递归查找该元素的所有⽗元素,如果找到⼀个设置了position:relative/absolute/fixed
的元素,就以该元素为基准定位,如果没找到,就以浏览器边界定位。
flex
布局
布局的传统解决⽅案基于盒⼦模型,依赖display属性+position属性+float属性。它对于那些特殊布局⾮常不⽅便,⽐如,垂直居中就不容易实现。在⽬前主流的移动端⻚⾯中,使⽤flex布局能更好地完成需求。
基本使用
任何一个容器都可以使用flex布局,代码也很简单,强烈建议学习!!
注意,第三个
<style>
.container {
display: flex;
}
.item {
border: 1px solid #000;
flex: 1;
}
</style>
<div class="container">
<div class="item">aaa</div>
<div class="item" style="flex: 2">bbb</div>
<div class="item">ccc</div>
<div class="item">ddd</div>
</div>
设计原理
设置了display: flex
的元素,我们称为“容器”(flex container),其所有的⼦节点我们称为“成员”(flex item)。容器默认存在两根轴:⽔平的主轴(main axis)和垂直的交叉轴(cross axis)。主轴的开始位置(与边框的交叉点)叫做main start,结束位置叫做main end;交叉轴的开始位置叫做cross start,结束位置叫做cross end。项⽬默认沿主轴排列。单个项⽬占据的主轴空间叫做main size,占据的交叉轴空间叫做cross size。
将以上⽂字和图⽚结合起来,再详细看⼀遍,这样就能理解flex的设计原理,才能更好地实际使⽤。
设置主轴的⽅向
flex-direction
可决定主轴的⽅向,有四个可选值:
- row(默认值):主轴为⽔平⽅向,起点在左端。
- row-reverse:主轴为⽔平⽅向,起点在右端。
- column:主轴为垂直⽅向,起点在上沿。
- column-reverse:主轴为垂直⽅向,起点在下沿。
.box {
flex-direction: column-reverse | cocolumn | row | row-reverse;
}
设置主轴的对⻬⽅式
justify-content
属性定义了项⽬在主轴上的对⻬⽅式,值如下:
- flex-start(默认值):向主轴开始⽅向对⻬。
- flex-end:向主轴结束⽅向对⻬。
- center:居中。space-between:两端对⻬,项⽬之间的间隔都相等。
- space-around:每个项⽬两侧的间隔相等。所以,项⽬之间的间隔⽐项⽬与边框的间隔⼤⼀倍。
.box {
justify-content: flex-start | flex-end | center | space-between |space-around;
}
交叉轴的对⻬⽅式
align-items
属性定义项⽬在交叉轴上如何对⻬,值如下:
- flex-start:交叉轴的起点对⻬。
- flex-end:交叉轴的终点对⻬。
- center:交叉轴的中点对⻬。
- baseline:项⽬的第⼀⾏⽂字的基线对⻬。
- stretch(默认值):如果项⽬未设置⾼度或设为auto,将占满整个容器的⾼度。
.box {align-items: flex-start | flex-end | center | baseline | stretch;}
如何实现居中对⻬?
题⽬:如何实现⽔平居中?
⽔平居中
inline元素⽤text-align: center;
即可,如下:
.container {
text-align: center;
}
block元素可使⽤margin: auto;
,PC时代的很多⽹站都这么搞。
.container {
text-align: center;
}
.item {
position: relative;
width: 500px;
}
垂直居中
inline元素可设置line-height
的值等于height值,如单⾏⽂字垂直居中:
.container {
height: 50px;
line-height: 50;
}
绝对定位元素,可结合left
和margin
实现,但是必须知道尺⼨。
- 优点:兼容性好
- 缺点:需要提前知道尺⼨
.container {
position: relative;
height: 200px;
}
.item {
width: 80px;
height: 40px;
position: absolute;
left: 50%;
top: 50%;
margin-top: -20px;
margin-left: -40px;
}
绝对定位可结合transform
实现居中。
- 优点:不需要提前知道尺⼨
- 缺点:兼容性不好
.container {
position: relative;
height: 200px;
}
.item {
width: 80px;
height: 40px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
background: blue;
}
绝对定位结合margin: auto
,不需要提前知道尺⼨,兼容性好。
.container {
position: relative;
height: 3px;
}
.item {
width: 100px;
height: 300px;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
}
其他的解决⽅案还有,不过没必要掌握太多..
理解语义化
题⽬:如何理解HTML语义化?
所谓“语义”就是为了更易读懂,这要分两部分:
- 让⼈(写程序、读程序)更易读懂
- 让机器(浏览器、搜索引擎)更易读懂
让⼈更易读懂
对于⼈来说,代码可读性、语义化就是⼀个⾮常⼴泛的概念了,例如定义JS变量的时候使⽤更易读懂的名称,定义CSS class的时候也⼀样,例如lengthlist等,⽽不是使⽤ab这种谁都看不懂的名称。
不过我们平常考查的“语义化”并不会考查这么⼴义、这么泛的问题,⽽是考查HTML的语义化,是为了更好地让机器读懂HTML。
让机器更易读懂
HTML符合XML标准,但⼜和XML不⼀样—— HTML不允许像XML那样⾃定义标签名称,HTML有⾃⼰规定的标签名称。问题就在这⾥—— HTML为何要⾃⼰规定那么多标签名称呢,例如p div h1 ul
等——就是为了语义化。其实,如果你精通CSS的话,你完全可以全部⽤
拿搜索引擎来说,爬⾍下载到我们⽹⻚的HTML代码,它如何更好地去理解⽹⻚的内容呢?——就是根据HTML既定的标签。h1
标签就代表是标题;p
⾥⾯的就是段落详细内容,权重肯定没有标题⾼;ul
⾥⾯就是列表;strong
就是加粗的强调的内容……如果我们不按照HTML语义化来写,全部都⽤<div>
标签,那搜索引擎将很难理解我们⽹⻚的内容。
为了加强HTML语义化,HTML5标准中⼜增加了header section article
等标签。因此,书写HTML时,语义化是⾮常重要的,否则W3C也没必要⾟⾟苦苦制定出这些标准来。
CSS3动画
CSS3可以实现动画,代替原来的Flash和JavaScript⽅案。
⾸先,使⽤@keyframes
定义⼀个动画,名称为testAnimation
,如下代码,通过百分⽐来设置不同的CSS样式,规定动画的变化。所有的动画变化都可以这么定义出来。
@keyframes testAnimation {
0% {background: red; ;left: 0; top: 0}
25% {background: green; ;left: 200px; top: 0}
50% {background: blue; ;left: 200px; top: 200px}
75% {background: yellow; ;left: 0; top: 200px}
100% {background: pink; ;left: 0; top: 0}
}
然后,针对⼀个CSS选择器来设置动画,例如针对div元素设置动画,如下:
div {
width: 100px;
height: 50px;
position: absolute;
animation-name: myfrist;
animation-duration: 5s;
}
animation-name
对应到动画名称,animation-duration
是动画时⻓,还有其他属性:
- animation-timing-function:规定动画的速度曲线。默认是ease
- animation-delay:规定动画何时开始。默认是0
- animation-iteration-count:规定动画被播放的次数。默认是1
- animation-direction:规定动画是否在下⼀周期逆向地播放。默认是normal
- animation-play-state:规定动画是否正在运⾏或暂停。默认是running
- animation-fill-mode:规定动画执⾏之前和之后如何给动画的⽬标应⽤,默认是none,保留在最后⼀帧可以⽤
forwards
题⽬:CSS的
transition
和animation
有何区别?
⾸先transition
和animation
都可以做动效,从语义上来理解,transition是过渡,由⼀个状态过渡到另⼀个状态,⽐如⾼度100px过渡到200px;⽽animation是动画,即更专业做动效的,animation有帧
的概念,可以设置关键帧keyframe
nimation是动画,即更专业做动效的,animation有帧的概念,可以设置关键帧keyframe
,⼀个动画可以由多个关键帧多个状态过渡组成,另外animation也包含上⾯提到的多个属性。
重绘和回流
重绘和回流是⾯试题经常考的题⽬,也是性能优化当中应该注意的点。
-
重绘:指的是当⻚⾯中的元素不脱离⽂档流,⽽简单地进⾏样式的变化,⽐如修改颜⾊、背景等,浏览器重新绘制样式
-
回流:指的是处于⽂档流中DOM的尺⼨⼤⼩、位置或者某些属性发⽣变化时,导致浏览器重新渲染部分或全部⽂档的情况
相⽐之下,回流要⽐重绘消耗性能开⽀更⼤。另外,⼀些属性的读取也会引起回流,⽐如读取某个DOM的⾼度和宽度,或者使⽤getComputedStyle⽅法。在写代码的时候要避免回流和重绘。
题⽬:找出下⾯代码的优化点,并且优化它
var data = ['string1', 'string2', 'string3']
for (var i=0; i < data.length; i++){
var dom = document.getElementById('list')
dom.innerHTML += '<li>' + data[i] + '</li>'
}
上⾯的代码在循环中每次都获取dom
,然后对其内部的HTML进⾏累加li,每次都会操作DOM结构,可以改成使⽤documentFragment
或者先遍历组成HTML的字符串,最后操作⼀次innerHTML
。
小结
总结了CSS和HTML常考的知识点,包括CSS中⽐较重要的定位、布局的知识,也介绍了⼀些CSS3的知识点概念和题⽬,以及HTML的语义化。