这是我参与「第四届青训营」笔记创作活动的的第3天
前言
我们在上一篇中学习了CSS的基本用法,可以做出一些比较简单的样式表了,接下来我们就需要学习CSS的进阶用法了。
选择器的优先级
我们来看下面这段代码,这里我们对同一个标签通过不同的选择器使用了两种不同颜色的样式表,那么实际上这个样式表到底是什么颜色呢?
<h1 class="Title"> The title</h1>
<style>
.Title{
color: blue;
}
h1{
color: red;
}
</style>
我们会发现是蓝色的而不是红色的。
选择器优先级的基本原则是:越特殊的选择器优先级越高,即id选择器大于伪类选择器大于标签选择器,多个class的选择器大于较少个class的选择器。就好比你在玩三国杀的时候,当武将的技能和游戏基本规则起冲突的时候听谁的?当然是听武将的了。所以标签选择器的规则也是这样的,对某一个个体元素,肯定优先去执行他元素中特有的部分。
如果想要了解更详细的选择器等级,可以参考CSS选择器的优先级(精讲版) (biancheng.net)。
选择器的继承
当每一个元素去找其对应的样式表的时候,如果找不到,他会怎么办?在HTML标准中,规定了如果一个元素找不到样式表,那么就会把其父元素的样式应用在其身上。比如我们让一段文字中出现加粗倾斜等效果,但是我们却没有规定加粗的strong标签和倾斜的em标签的样式,就像这样:
<p>This is a text , <em>this is an em text,</em>
<strong>and this is a strong text</strong></p>
<style>
p{
color: blue;
}
</style>
大家可以注意到我把一句话分成了两行,其实这是可以的。在HTML中,多个连续的空白会被缩减为一个。
我们会发现,斜体和加粗的部分也都是蓝色的。
但是并不是所有的属性都会被继承,这个时候可以进行显式继承:只要将对应的属性值改为inherit就可以了。比如这样一段代码就和上一段的效果是一样的。
<style>
p{
color: blue;
}
em{
color: inherit;
}
strong{
color: inherit;
}
</style>
属性的初始值
所有的属性都有一个默认的初始值,如果一个标签没有继承到任何一个样式表,那么就使用的是初始值。我们也可以通过把一个属性设置为initial来将其显示设置为初始值。
CSS的求值过程
一个CSS样式表的求值过程大概可以用下面这张图概括:
(图源CSS 特异度、继承、求值过程简介_LAinKH的博客-CSDN博客)
值的计算是一个很复杂的过程,很多人在做前端的时候也很容易被困扰,因此就需要我们在写页面的时候对于这些个值一定要搞清楚。
盒模型
网页中的一个元素,它到底遵循什么样的规律呢?=能否把所有的元素都抽象成一种模型呢?当然是可以的。在CSS中,每个元素其实都是以盒模型的方式构建的。每一个盒模型就是一个元素,在里面放入内容,便于设计者设计和开发者的编写。
一个典型的盒模型的组成如下图:
(图源CSS盒模型详解(图文教程) - 千古壹号 - 博客园 (cnblogs.com))
最外层的部分叫做margin,也就是外边距。外边距规定了两个盒模型之间的距离,通常来讲都是透明的。换句话说,其实网页上的所有盒模型其实是“紧贴”在一起的,用户看到的距离都是设置外边距的结果。再往里的部分是border,也就是边界。边界决定了一个盒模型的最外层。边界里面的就是padding,即内边距。内边距决定了内容到边框中间的距离,通常也是透明的。最里面的content就是实际的内容了。
我们在浏览器开发工具中,找到已计算选项卡,就可以找到对应元素的盒模型了。
下面介绍盒模型的一些属性。
内容属性
width指定了内容的宽度,其取值可以为长度、百分数和auto。当其为auto时,会由浏览器根据其他属性来自动调整宽度;当其为百分数时,其取值为相对于容器的content宽度。height属性也差不多,不过只有当容器本身有指定的高度时、百分数高度才会生效。
内边距属性
设定padding时,我们既可以将四个方向的宽度设置为一样,也可以将四个方向的宽度设定为不同,顺序为上右下左。比如:
<div style="padding: 100px">I can change the padding size to 100px</div>
<div style="padding: 20px 20px 50px 20px">Here only one side of padding is 50px</div>
此时两个元素的盒模型如下图:
顺便一提这里的div标签和p标签类似,都表示HTML文档中的一个段落。但是目前来讲显然是div更为常用。
边界属性
边界其实就是一个边框,我们可以用border-width属性调整边框的宽度,当然也可以用单独的属性具体调整其中某一个方向的宽度,用border-style调整边框的样式,用border-color调整边框的颜色。
当四个方向的边框颜色都不一样的时候,我们可以发现他是斜着切过来的,而不是垂直的结构。
<div style=" border-width: 50px ; border-style: solid;
border-bottom-color: blue; border-left-color: red;
border-right-color: coral; border-top-color:green">
<br><br>you can see what the border like</div>
最后的结果就像这样:
注意一定要有border-style否则默认值的话是none,是无论如何都看不到的。
外边距属性
利用margin属性可以指定外边距的宽度。这里有一个语法糖:当你的margin-left和margin-right都是auto的时候,浏览器就会自动帮你设置为居中。但是可不止这么简单。在垂直方向上,两个元素的间距并不是其上下margin的和,而是两个元素中margin较大的那个,我们称其为margin collapse。例如:
<div class="a"></div>
<div class="b"></div>
<style>
.a {
background: lightblue;
height: 100px;
margin-bottom: 5px;
}
.b {
background: coral;
height: 100px;
margin-top: 100px;
}
</style>
这时候两个方块的间距就是100px而不是105px。
可以看到body的大小为300px。
盒模型属性
利用box-sizing属性,我们可以设置整个盒模型的width属性所包含的范围。如果为content-sizing的话,那么我们在调整width的时候,调整的就只是内容部分的宽度;如果为border-sizing的话,那么元素的width就会包括border和padding的宽度。
盒模型中元素的显示
在一个大小固定的盒模型中,如果内容太多了就会溢出。这就是overflow属性。该属性有三个值:visible,内容正常向下溢出不做任何处理;hidden,溢出的内容会被隐藏起来看不到;scroll,它会生成一个滚轮,让你方便的浏览所有的内容。
<p style=" border: black solid 10px ;overflow: visible; height: 50px">
The common starling is a medium-sized perching bird in the starling
family, Sturnidae. It is about 20 cm (8 in) long and has glossy black
plumage, which is speckled with white at some times of year. The legs are
pink and the bill is black in winter and yellow in summer; young birds
have browner plumage than the adults. It is a noisy bird, especially in
communal roosts, with an unmusical but varied song.
</p>
<br><br><br><br>
<p style=" border: black solid 10px ;overflow: hidden; height: 50px">
The common starling is a medium-sized perching bird in the starling
family, Sturnidae. It is about 20 cm (8 in) long and has glossy black
plumage, which is speckled with white at some times of year. The legs are
pink and the bill is black in winter and yellow in summer; young birds
have browner plumage than the adults. It is a noisy bird, especially in
communal roosts, with an unmusical but varied song.
</p>
<p style=" border: black solid 10px ;overflow: scroll; height: 50px">
The common starling is a medium-sized perching bird in the starling
family, Sturnidae. It is about 20 cm (8 in) long and has glossy black
plumage, which is speckled with white at some times of year. The legs are
pink and the bill is black in winter and yellow in summer; young birds
have browner plumage than the adults. It is a noisy bird, especially in
communal roosts, with an unmusical but varied song.
</p>
就会得到这样的效果。
常规流布局模式——块元素与行元素
在盒模型布局中,一般分为两种,一种叫做块级(Block Level Box),一种叫做行级(Inline Level Box)。块级元素不能和其他的盒模型并列摆放,但可以使用所有的盒模型属性;行级元素需要和其他的行级元素放在一行或者放在几行中呈现,不能使用width和height属性。
上一段话中元素和盒模型是混用的,这是因为我们是在写HTML和css的复合体,在HTML中成为块元素,而在css中则称为块级盒模型。如果想知道两个语言中的块元素和行元素列表,请参考有关语言标准。不过我们在实际使用中,通过修改CSS中的display属性为block或者inline,可以调整每个盒模型到底属于哪一类。你甚至还可以将其改为inline-block和none,前者本身为行元素但是可以设置宽高,而后者会在排版的时候会被完全忽略。
行元素的排版
如果一个盒模型内只有行元素,那么就会创建一个行内格式化上下文(Inline Formatting Context,简称IFC)。一个IFC的排版规则是这样的:里面所有的元素会在一行内水平摆放,一行放不下的时候则换行显示;text-align属性决定了一行内盒模型的水平对齐;vertical-align属性则决定了一个元素在行内的垂直对齐;并且其会避开浮动元素。
<div>
This is a paragraph of text with long word Honorificabilitudinitatibus. Here is an image
<img src="kirbyWalking.gif" alt="KirbyWalking">
And <em>Inline Block</em>
</div>
<style>
div {
width: 10em;
background: #411;
}
em {
display: inline-block;
width: 3em;
background: #33c;
}
</style>
那么看起来就是这样。注意不同元素之间的排版以及当一行放不下所有元素的时候是怎么做的。如果想让长单词强制换行,可以将overflow-warp属性改为break-word。
块元素的排版
当我们创建某些块元素的时候,就会创建一个块级格式化上下文(Black Foamattting Context)。这些块元素可以是根元素、也可以是浮动元素/绝对定位元素/inline-block、也可以是Flex子项和Grid子项、还可以是overflow属性不为visible的块元素、也可以是display属性为flow-root的元素,其中有些我们之后再讲。
BFC内部的排版规则遵循以下的规律:盒模型从上到下摆放;垂直方向上会有magrin collapse;内部盒模型的margin不会与外面的合并;并且其不会和浮动元素重叠。下面是一个BFC的例子:
<span>
This is a text and
<div>block</div>
and other text.
</span>
<style>
span {
line-height: 3;
border: 2px solid red;
background: coral;
}
div {
line-height: 1.5;
background: lime;
}
</style>
页面上显示的结果就是这样的。
Flex Box
上面的东西看上去比较的繁琐,因此随着CSS的版本迭代,我们迎来了一种新的排版模式:Flex Box。这是一种新的盒模型,它可以用来控制子盒模型的摆放朝向、摆放顺序、每个盒子的宽高、水平和垂直对齐以及是否允许折行等属性。也是目前使用的最广泛的模型。
这是flex排版的一个最基本的例子,里面的元素全部使用了默认的设置。
<div class="container">
<div class="a">A</div>
<div class="b">B</div>
<div class="c">C</div>
</div>
<style>
.container {
display: flex;
border: 2px solid #966;
}
.a, .b, .c {
text-align: center;
padding: 1em;
}
.a {
background: greenyellow;
}
.b {
background: coral;
}
.c {
background: deepskyblue;
}
</style>
在页面上就是这样的。
我们接下来对它的属性进行一些简单的介绍。
flex-direction属性定义了容器内元素的布局方向。如果是column,则元素的顺序为从上到下;若为column-reverse,则元素顺序从下到上。同理,row是从左到右,而row-reverse是从右到左。justify-content属性定义了模型内元素的对齐方式,默认为flex-start,即前端对齐。如果我们想居中对齐可以使用center,想在末端对齐可以用flex-end。而align-items属性定义了元素的垂直对齐方式,可以使用顶部对齐、底部对齐、居中对齐等。此外还有很多的属性,这里就不一一介绍了。
上面这些都是flex容器的属性,而我们还可以对其中的每一个元素单独设置属性。比如align-self属性规定了某个元素自己单独的对齐方式、order属性规定了某个元素在容器内的顺序,而你也可以通过调整flex-grow、flex-shrink和flex-basis来调整每个元素的弹性。
关于如何使用Flex box的详细教程,我们可以参照CSS Flexbox (w3school.com.cn),根据后面的实例我们可以发现使用这种模式可以很好的创建响应式布局的网站。
总结
由于篇幅所限和目前的使用情况,本文就不再讲浮动布局了,感兴趣的小伙伴可以自行搜索。关于Grid布局,由于其比Flex box更加复杂,之后会专门拿出一篇文章来进行详细的介绍。