0%

前端知识体系梳理(二-1)—— 重新认识HTML、CSS

当知道了浏览器展示页面的过程后,我们开始探究页面组成的每一部分,相信印象会更加深刻,这里从HTML、CSS开始

提纲:

  • 热身
    • 理解语义化
    • 再说重绘和回流
  • CSS 布局
    • 从全屏布局谈起
    • 多列布局
      • 定宽自适应跟随
      • 等分布局
      • 两侧固定中间自适应三栏布局
      • 不定宽自适应
      • 定宽自适应
    • 居中布局
      • 水平、垂直居中
      • 垂直居中
      • 水平居中
    • 也谈flex布局
  • 重新认识CSS
    • 选择器的权重和优先级
    • 盒模型
    • 浮动float
    • 定位position
    • CSS3动画

本篇不会细致到HTML、CSS的方方面面,讲解的内容主要是我觉得比较重要或者需要知道的。具体到个个细节的东西我暂时只整理到了自己的笔记上以做备忘和文档查阅。

热身

理解语义化

所谓“语义”就是为了更易读懂,这要分两部分:

  • 让人(写程序、读程序)更易读懂
  • 让机器(浏览器、搜索引擎)更易读懂

让人更易读懂
对于人来说,代码可读性、语义化就是一个非常广泛的概念了,例如定义 JS 变量的时候使用更易读懂的名称,定义 CSS class 的时候也一样,例如length list等,而不是使用a b这种谁都看不懂的名称。

不过我们平常考查的“语义化”并不会考查这么广义、这么泛的问题,而是考查 HTML 的语义化,是为了更好地让机器读懂 HTML。

让机器更易读懂
HTML 符合 XML 标准,但又和 XML 不一样 —— HTML 不允许像 XML 那样自定义标签名称,HTML 有自己规定的标签名称。问题就在这里 —— HTML 为何要自己规定那么多标签名称呢,例如p div h1 ul等 —— 就是为了语义化。其实,如果你精通 CSS 的话,你完全可以全部用<div>标签来实现所有的网页效果,其他的p h1 ul等标签可以一个都不用。但是我们不推荐这么做,这样做就失去了 HTML 语义化的意义。

拿搜索引擎来说,爬虫下载到我们网页的 HTML 代码,它如何更好地去理解网页的内容呢?—— 就是根据 HTML 既定的标签。h1标签就代表是标题;p里面的就是段落详细内容,权重肯定没有标题高;ul里面就是列表;strong就是加粗的强调的内容 …… 如果我们不按照 HTML 语义化来写,全部都用<div>标签,那搜索引擎将很难理解我们网页的内容。

为了加强 HTML 语义化,HTML5 标准中又增加了header section artical等标签。因此,书写 HTML 时,语义化是非常重要的,否则 W3C 也没必要辛辛苦苦制定出这些标准来。

再说重绘和回流

  • 重绘:指的是当页面中的元素简单地进行样式的变化,比如修改颜色、背景等,浏览器重新绘制样式
  • 回流:指的是处于文档流中 DOM 的尺寸大小、位置或者某些属性发生变化时,导致浏览器重新渲染部分或全部文档的情况

相比之下,回流要比重绘消耗性能开支更大。另外,一些属性的读取也会引起回流,比如读取某个 DOM 的高度和宽度,或者使用getComputedStyle方法。在写代码的时候要避免回流和重绘。
更深入的内容移步上一篇查看。

CSS布局

这里基本所有的布局都会讨论,但是大部分只会写出一种解决方案,其他的解决方案我自己整理了一份在笔记上备忘、方便查阅。内容有些多有时间有精力了再分享出来。

从全屏布局谈起

邮箱布局:

1
2
3
4
5
6
<div class="parent">
<div class="top">top</div>
<div class="left">left</div>
<div class="top">top</div>
<div class="bottom">bottom</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
html, body, .parent {
height: 100%;
overflow: hidden;
}
.top {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 100px;
}
.left {
position: absolute;
top: 100px;
bottom: 100px;
left: 0;
width: 100px;
}
.right {
position: absolute;
top: 100px;
bottom: 100px;
left: 100px;
right: 0;
overflow: auto; // 超出滚动
}
.bottom {
position: absolute;
left: 0;
right: 0;
bottom: 0;
height: 100px;
}

上边定宽定高的部分改为百分比,只用把px换成%即可。

多列布局

定宽自适应跟随

特点:左边定宽,右边自适应;右边高度增加,左边跟随,右边减少,左边也跟随;最终保证两边高度一样

1
2
3
4
5
6
7
8
9
<div class="parent">
<div class="left">
<p>left</p>
</div>
<div class="right">
<p>right</p>
<p>right</p>
</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.parent {
overflow: hidden;
}
.left, .right {
padding-bottom: 9999px;
margin-bottom: -9999px;
}
.left {
float: left;
width: 100px;
margin-right: 20px;
}
.right {
overflow: hidden;
}

等分布局

1
2
3
4
5
6
<div class="parent">
<div class="column"><p>1</p></div>
<div class="column"><p>2</p></div>
<div class="column"><p>3</p></div>
<div class="column"><p>4</p></div>
</div>
1
2
3
4
5
6
7
8
9
.parent {
margin-left: -20px;
}
.column {
box-sizing: border-box;
float: left;
width: 25%;
padding-left: 20px;
}

扩展出栅格布局的布局方案,大概如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
html, body {
margin: 0;
padding: 0;
height: 100%;
}
.row:after {
content: '';
display: table;
clear: both;
}
.row {
*zoom: 1;
}

*{
box-sizing: border-box;
}

.container{
padding: 0px 15px;
margin: 0 auto;
}
.row{
margin: 0 -15px;
}

@media (max-width: 768px){
.container{
width: auto;
}

}
@media (max-width: 992px) and (min-width: 768px){
.container{
width: 750px;
}
.col-md-1{
width: auto;
padding: 0px 15px;
}
.col-md-3{
width: auto;
padding: 0px 15px;
}
}
@media (min-width: 992px) and (max-width: 1200px){
.container{
width: 970px;
}
.col-md-3{
width: 25%;
float: left;
padding: 0px 15px;
}
.col-md-1{
width: 8.33333333%;
float: left;
padding: 0px 15px;
}
}
@media (min-width: 1200px){
.container{
width: 1170px;
}
.col-md-3{
width: 25%;
float: left;
padding: 0px 15px;
}
.col-md-1{
width: 8.33333333%;
float: left;
padding: 0px 15px;
}
}
-----------------------------------
<div class="container">
<div class="row">
<div class="col-md-1">col-md-1</div>
<div class="col-md-1">col-md-1</div>
<div class="col-md-1">col-md-1</div>
<div class="col-md-1">col-md-1</div>
<div class="col-md-1">col-md-1</div>
<div class="col-md-1">col-md-1</div>
<div class="col-md-1">col-md-1</div>
<div class="col-md-1">col-md-1</div>
<div class="col-md-1">col-md-1</div>
<div class="col-md-1">col-md-1</div>
<div class="col-md-1">col-md-1</div>
<div class="col-md-1">col-md-1</div>
</div>
<div class="row">
<div class="col-md-3">col-md-3</div>
<div class="col-md-3">col-md-3</div>
<div class="col-md-3">col-md-3</div>
<div class="col-md-3">col-md-3</div>
</div>
</div>

两侧固定中间自适应三栏布局

圣杯布局 & 双飞翼布局
两种布局达到效果上基本相同,都是两边两栏宽度固定,中间栏宽度自适应。在HTML结构上中间栏在最前面保证了最先渲染中间提升性能(因为这两种布局都比较老,我认为在现代浏览器中这点儿性能优化效果并不是很大),并且兼容性良好。

圣杯布局:

1
2
3
4
5
6
7
8
9
10
11
<div class="bd">
<div class="main text">
main
</div>
<div class="left text">
left
</div>
<div class="right text">
right
</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.bd {
overflow: hidden;
padding: 0 200px 0 200px;
}
.main {
float: left;
width: 100%;
height: 200px;
background-color: #ddd;
}
.left {
float: left;
width: 200px;
height: 200px;
background-color: #da4242;
/* 产生布局效果的属性 */
margin-left: -100%;
position: relative;
left: -200px;
}
.right {
float: left;
width: 200px;
height: 200px;
background-color: #4ddef1;
/* 产生布局效果的属性 */
margin-left: -200px;
position: relative;
left: 200px;
}

双飞翼布局:

1
2
3
4
5
6
7
8
9
10
11
<div class="bd">
<div class="main text">
<div class="main-content">main</div>
</div>
<div class="left text">
left
</div>
<div class="right text">
right
</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
.bd {
overflow: hidden;
}
.main {
float: left;
width: 100%;
height: 200px;
background-color: #ddd;
}
.main-content {
margin: 0 200px;
}
.left {
float: left;
width: 200px;
height: 200px;
background-color: #da4242;
/* 产生布局效果的属性 */
margin-left: -100%;
}
.right {
float: left;
width: 200px;
height: 200px;
background-color: #4ddef1;
/* 产生布局效果的属性 */
margin-left: -200px;
}

不定宽自适应

1
2
3
4
5
6
7
8
9
<div class="parent">
<div class="left">
<p>left</p>
</div>
<div class="right">
<p>right</p>
<p>right</p>
</div>
</div>
1
2
3
4
5
6
7
8
.left {
float: left;
width: 200px; // 这个宽度可以手动改变,不设可跟随内容宽度
margin-right: 20px;
}
.right {
overflow: hidden;
}

定宽自适应

1
2
3
4
5
6
7
8
9
<div class="parent">
<div class="left">
<p>left</p>
</div>
<div class="right">
<p>right</p>
<p>right</p>
</div>
</div>
1
2
3
4
5
6
7
.left {
float: left;
width: 100px;
}
.right {
margin-left: 120px;
}

居中布局

水平、垂直居中

1
2
3
<div class="parent">
<div class="child">DEMO</div>
</div>
1
2
3
4
5
6
7
8
9
.parent {
position: relative;
}
.child {
positon: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}

垂直居中

1
2
3
<div class="parent">
<div class="child">DEMO</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
.parent {
position: relative;
height: 300px;
}
.child {
width: 100px;
height: 50px;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
margin: auto;
}

水平居中

1
2
3
<div class="parent">
<div class="child">DEMO</div>
</div>
1
2
3
4
.child {
width: 100px; // 需设置一个宽度
margin: 0 auto;
}

也谈flex布局

  • flex container: diplay: flex;的元素
  • flex item: 弹性元素是【弹性容器中】【直接的】【在文档流中】的元素(float元素在这里说的文档流中)
  • flex-direction可决定主轴的方向,有四个可选值:
    • row(默认值):主轴为水平方向,起点在左端。
    • row-reverse:主轴为水平方向,起点在右端。
    • column:主轴为垂直方向,起点在上沿。
    • column-reverse:主轴为垂直方向,起点在下沿
  • justify-content属性定义了项目在主轴上的对齐方式,值如下:
    • flex-start(默认值):向主轴开始方向对齐。
    • flex-end:向主轴结束方向对齐。
    • center: 居中。
    • space-between:两端对齐,项目之间的间隔都相等。
    • space-around:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。
  • align-items属性定义项目在交叉轴上如何对齐,值如下:
    • flex-start:交叉轴的起点对齐。
    • flex-end:交叉轴的终点对齐。
    • center:交叉轴的中点对齐。
    • baseline: 项目的第一行文字的基线对齐。
    • stretch(默认值):如果项目未设置高度或设为。
    • auto,将占满整个容器的高度。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<style type="text/css">
.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>

重新认识CSS

选择器的权重和优先级

样式的优先级:
外部样式、内部样式和内联样式同时应用于同一个元素:
(内联样式)Inline style > (内部样式)Internal style sheet > (外部样式)External style sheet
例外:权重相同,如果外部样式放在内部样式的后面,则外部样式将覆盖内部样式。(内联的就不会)

选择器的优先级:
选择器权重越大越优先,权重相同时后边覆盖前边,!important优先级最高

权重分级:

  • 代表内联样式,如style=”xxx”,权值为 1000;
  • 代表 ID 选择器,如#content,权值为 100;
  • 代表类、伪类和属性选择器,如.content、:hover、[attribute],权值为 10;
  • 代表元素选择器和伪元素选择器,如div、p,权值为 1。

【需要注意的是:通用选择器(*)、子选择器(>)和相邻同胞选择器(+)并不在这四个等级中,所以他们的权值都为 0。】

盒模型

描述这个模型描述了元素所占空间的内容。

组成:内容(contents)、内边距(padding)、边框(border) 和 外边距(margin)
提示:背景应用于由内容和内边距、边框组成的区域。

直接设定盒子所占空间:box-sizing : content-box | border-box | padding-box(只有Firefox实现了这个值,它在Firefox 50中被删除。)

兼容性:
不幸的是,IE5.X 和 6 在怪异模式中使用自己的非标准模型。这些浏览器的 width 属性不是内容的宽度,而是内容、内边距和边框的宽度的总和(border-box)。

浮动float

脱离文档流:float脱离了文档流,但是还在文本流中,所以设置float的元素会有父标签出现坍塌的现象,以及文字环绕现象。

包裹性:diplay: block;的元素设置了float后从撑满父元素变为包裹效果(inline-block)

清空格: float 排版出来的网页严丝合缝,中间连个苍蝇都飞不进去。

clearfix:在设置float元素的父元素上设置:

1
2
3
4
5
6
7
8
.clearfix:after {
content: '';
diplay: table;
clear: both;
}
.clearfix {
*zoom: 1; // 兼容IE低版本
}

定位position

position: static(默认) | relative | absolute | fixed

position的值为absolute、fixed的元素脱离文档流
position的值为static、relative没有脱离文档流

relative:

  • 没有脱离文档流,占位(文档流中的位置始终被占用),相对于自身文档流中位置定位,不会影响其他元素,z-index变大

absolute:

  • 脱离文档流,不占位(引起父元素塌陷、后边元素重排),相对于最近的定位上下文元素(relative | absolute | fixed元素)或者浏览器边界定位,会影响其他元素,z-index变大
  • absolute 元素具有“跟随性”。虽然 absolute 元素脱离了文档结构,但是它的位置并没有发生变化,还是老老实实地呆在它原本的位置,因为我们此时没有设置 top、left 的值。
  • 同float:父元素塌陷,包裹性

fixed:

  • 同absolute,除了absolute 元素是根据最近的定位上下文定位,而 fixed 根据浏览器边界定位。

CSS3动画

定义关键帧:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@keyframes slidein {
0% {
margin-left: 100%;
width: 300%;
}
50% {
margin-left: 50%;
width: 150%;
}
100% {
margin-left: 0%;
width: 100%;
}
}

使用关键帧:

1
2
3
4
p {
animation-duration: 3s;
animation-name: slidein;
}

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

transition和animation区别
首先transition和animation都可以做动效,从语义上来理解,transition是过渡,【由一个状态过渡到另一个状态】,比如高度100px过渡到200px;而animation是动画,即更专业做动效的,animation有帧的概念,可以设置关键帧keyframe,一个动画可以由多个关键帧【多个状态过渡组成】,另外animation也包含上面提到的多个属性。