0%

HTML 与 CSS 基础(4):CSS 三大特性及盒子模型

这篇文章继续学习 CSS 的基础知识,主要学习 CSS 的三大特性等、CSS 的盒子模型,同时也会介绍如何实现圆角边框、盒子阴影、文字阴影等页面效果。

CSS 的三大特性

CSS 有 3 个非常重要的特性:层叠性、继承性、优先级。

层叠性

相同选择器设置同样的样式,此时一个样式就会覆盖(层叠)另一个冲突的样式。层叠性主要解决样式冲突的问题。层叠性的原则:

  • 样式冲突情况下,后出现的规则将覆盖(层叠)先出现的规则
  • 样式不冲突不会层叠。

当因为层叠性而导致样式被覆盖时,Chrome 的工具会给出提出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<head>
<style>
div {
color: blue;
}

div {
color: red;
}
</style>
</head>
<body>
<div>
你好
</div>
</body>

继承性

CSS 的继承性是指子继承会继承父标签的某些样式,如文本颜色、字体大小等。当某个样式是从父元素继承而来,Chrome 的工具也会有对应的提示:

1
2
3
4
5
6
7
8
9
10
11
12
<head>
<style>
div {
color: blue;
}
</style>
</head>
<body>
<div>
<p>段落</p>
</div>
</body>
  • 恰当地使用继承可以简化代码,降低 CSS 样式的复杂性
  • 子元素可以继承父元素的某些样式,主要是与文字相关的属性,例如 text-、font-、line- 这些元素开头的属性、以及 color 属性

行高的继承有些特殊,行高我们使用带单位的数值来指定,也可以不用单位,此时它表示的是行高与当前字体大小的倍数关系,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<head>
<style>
body {
font: 16px/1.5 Microsoft Yahei;
}
div {
font-size: 20px;
}

p {
font-size: 30px;
}
</style>
</head>
<body>
<div>
div 你好
</div>

<p>段落 你好</p>
</body>

在这个例子中

  • div、p 子元素重新设置了自己字体大小,但是没有设置行高,因此子元素会继承父元素的行高设置 1.5
  • 由于倍数是相对于当前元素自己的字体大小计算的,所以 div 的行高为 20px * 1.5 = 30px,而 p 的行高为 30px * 1.5 = 45px

通过倍数来设置行高的优势是:子元素可以根据自己的文字大小自动调整行高

优先级

当同一个元素指定了多个选择器,且这些选择器都设置某个同样的样式,就会有优先级的产生:

  • 如果选择器相同,则执行层叠性判断
  • 如果选择器不同,则根据选择器权重执行

选择器的权重如下(从低到高排列):

选择器 权重
继承或者 * 0,0,0,0
元素选择器 0,0,0,1
类选择器、伪类选择器 0,0,1,0
ID 选择器 0,1,0,0
行内样式 style=“” 1,0,0,0
!important 无穷大
  • 权重是由 4 组数字组成的
  • 等级判断从左向右判断,如果某位数值相同,则判断下一位数值
  • 特别需要注意,继承的权重是 0,不管父元素的权重多高,子元素从其继承得到的权重都是 0

如下是一个示例:虽然父元素 body 设置了 !important,但是子元素从其继承得到的权重是 0,不如元素选择器自己的权重,因此最终 div 内文字的颜色为 blue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<head>
<style>
body {
color: red !important;
}
div {
color: blue;
}
</style>
</head>
<body>
<div>
div 你好
</div>
</body>

如果是复合选择器,则会有权重叠加,需要计算权重。但是需要注意,权重虽然会叠加,但是永远不会产生进位:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<head>
<style>
.test {
color: red;
}
.test li {
color: skyblue;
}
ul li {
color: orange
}
li {
color: black;
}
</style>
</head>
<body>
<ul class="test">
<li>test1</li>
<li>test2</li>
<li>test3</li>
</ul>
</body>

在该例子中:

  • .test 选择器的权重为 0,0,1,0
  • .test li 选择器的权重为 0,0,1,10,0,1,0 + 0,0,0,1
  • ul li 选择器的权重为 0,0,0,20,0,0,1 + 0,0,0,1
  • li 选择器的权重为 0,0,0,1

比较之后,.test li 选择器的权重最高,因此最终 li 元素的文字颜色为 skyblue。

盒子模型

页面布局要学习三大核心:盒子模型、浮动和定位。学习好 盒子模型 才能帮助我们布局页面。网页布局的过程可以分为以下 3 个步骤:

  • 准备好相关的网页元素,网页元素基本都是盒子 Box
  • 利用 CSS 设置好盒子样式,然后摆放到相应位置
  • 往盒子里面装内容

网页布局的核心本质就是利用 CSS 摆盒子

盒子模型的组成

所谓盒子模型,就是把 HTML 页面中的布局元素看作是一个矩形的盒子,也就是装内容的容器。这个盒子包括:

  • 边框(border):盒子的边框
  • 内容(conent):盒子内盛装的内容
  • 内边距(padding):盒子边框和内容之间的区域
  • 外边距(margin):盒子边框与其他盒子边框之间区域

如下是盒子模型的示意图:

边框

border 可以设置元素的边框,它是一个复合属性,可以设置边框的宽度、样式和颜色。语法如下:

1
border: border-width || border-style || border-color
  • border-width:定义边框粗细,单位为 px
  • border-style:定义边框的样式,默认为 none,可以是 solid(实线)、dashed(虚线)、点线(dotted)等
  • boeder-color:定义边框颜色
1
2
3
4
5
6
7
div {
width: 300px;
height: 200px;
border-width: 5px;
border-style: solid;
border-color: blue;
}

通过 border 属性可以一次性设置边框的宽度、样式和颜色(没有顺序要求,但是一般按照该顺序书写),因此如下写法也是等效的,但是代码更加简单:

1
border: 5px solid blue;

盒子是包含 4 条边的,因此每条边框都可以单独设置其属性:

1
2
3
4
border-top: 5px solid blue;
border-bottom: 10px dashed red;
border-left: 10px dotted yellow;
border-right: 10px dotted skyblue;

而下面的 CSS 规则,则让上边框有专门的样式,其余边框都使用另一种样式:

1
2
3
/* 注意有顺序要求,利用 CSS 的层叠性 */
border: 10px dashed red;
border-top: 5px solid blue;

我们可以用 CSS 来控制 table 的显示,如下是一个示例:

1
2
3
4
5
6
7
8
9
10
11
12
table {
width: 500px;
height: 300px;
}

table,
th,
td {
border: 10px solid blue;
border-collapse: collapse;
text-align: center;
}
  • border-collapse:用来控制相邻单元格的边框是否合并为单一的边框,默认为 separate(分开),设置为 collapse 则会让相邻边框合并在一起

需要注意,当我们通过 width/hegith 属性来设置盒子的大小时,边框是不会算在内的。因此在设置边框大小后,会增加盒子的实际大小,例如如下 div 的实际尺寸是 320 * 320:

1
2
3
4
5
6
div {
background-color: pink;
width: 300px;
height: 300px;
border: 10px solid green;
}

内边距

padding 属性用来设置盒子内边距,也就是内容区域和边框之间的空间。其可以设置如下四个属性:

  • padding-top:上内边距
  • padding-bottom:下内边距
  • padding-left:左内边距
  • padding-right:右内边距

可以直接通过 padding 属性来一次性设置四个方向的内边距:

  • padding: 10px; 所有方向内边距都是 10px
  • paddding: 10px 20px; 上和下内边距是 10px,左右内边距是 20px
  • padding: 10px 20px 30px; 上内边距是 10px,左右内边距是 20px,下内边距是 30px
  • paddding: 10px 20px 30px 40px; 上内边距是 10px,右内边距是 20px,下内边距是 30px,左内边距是 40px(顺时针方向)

需要注意,当我们通过 width/height 属性来设置盒子的大小后,在通过 padding 属性设置内边距后,也会增大盒子的实际大小,例如如下 div 的实际尺寸是 340 * 340:

1
2
3
4
5
6
div {
background-color: pink;
width: 300px;
height: 300px;
padding: 20px;
}

padding 的内边距可以撑开盒子,有时候我们可以巧妙的利用该特性来保证不同大小盒子间隔的一致性。例如导航栏每个链接块的文字大小不一致,如果直接设置固定的宽度,那么文字少的盒子之间空隙就会很大。此时我们可以不设置固定宽度,而是设置固定 padding,让其自动撑开盒子,保持间隔的统一。

1
2
3
4
5
.nav a {
display: inline-block;
height: 41px;
padding: 0 20px;
}

需要特别注意的是,如果盒子没有指定 width 或者 height,则 padding 设置不会在对应的方向改变盒子的大小。而一旦设置了(即使设置成 width: 100%,即表示和父元素一样宽),padding 设置就会在对应的方向增大盒子的大小。

外边距

margin 属性用来设置盒子外边距,也就是盒子与盒子之间的距离。其可以设置如下四个属性:

  • margin-top:上外边距
  • margin-bottom:下外边距
  • margin-left:左外边距
  • margin-right:右外边距

可以通过 margin 属性来一次性设置四个方向的外边距,其设置值的规则和 padding 属性类似,这里就不再赘述。

外边距有一个典型应用,它可以让块级盒子水平居中,但是有两个前提:

  • 盒子必须设置了宽度(width)
  • 盒子左右的外边距都设置为 auto

例如:

1
2
3
4
5
6
div {
height: 200px;
width: 200px;
background-color: pink;
margin: 0 auto;
}

注意该方法是让块级元素水平居中,行内元素或者行内块元素水平居中只需要给其父元素添加 text-align: center; 即可。

在使用 margin 定义块元素的垂直外边距时,可能会出现外边距的合并。主要有两种情况:

  • 相邻块元素垂直外边距的合并:

    • 当上下相邻的两个块元素相遇时,如果上面元素设置了 margin-bottom,下面元素设置了 margin-top,则它们之间的外边距会取两者之间较大的值(而不是两者之和)
    • 解决方法是:尽量只给一个盒子设置外边距
  • 嵌套块元素垂直外边距的塌陷

    • 对于两个嵌套关系的块元素,父元素有上外边距同时子元素也有上外边距,此时父元素会塌陷两者之中较大的外边距值

例如对于如下例子,父元素最终的 margin-top 是 100px,而不是 50px:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<head>
<style>
#father {
height: 200px;
width: 200px;
margin-top: 50px;
background-color: pink;
}

#son {
height: 100px;
width: 100px;
background-color: blue;
margin-top: 50px
}
</style>
</head>
<body>
<div id="father">
<div id="son"></div>
</div>
</body>

解决方案有几种:

  • 可以为父元素定义上边框
  • 可以为父元素定义上内边距
  • 可以为父元素添加 overflow: hidden(常用)

另外还有其他方法,例如浮动、固定、绝对定位的盒子不会有塌陷问题,后面再介绍。

清除网页元素的内外边距

很多网页元素都带有默认的内外边距,而且不同浏览器默认值也不一致。因此我们在布局前,可以通过以下 CSS 代码清除元素的内外边距:

1
2
3
4
5
/* 以下代码经常会作为 CSS 的第一行代码出现 */
* {
margin: 0;
padding: 0;
}

另外行内元素为了照顾兼容性,尽量只设置左右内外边距,不要设置上下内外边距(如果的确需要设置,转换为块级或行内块元素即可)。

圆角边框

在 CSS3 中,新增了圆角边框样式,这样盒子就可以变成圆角了。border-radius 属性用于设置外边框圆角,其语法如下:

1
border-radius: length;
  • 参数值可以是数值(px)或者百分比形式,length 表示圆形半径的长度。
  • 如果想要一个圆形按钮,可以先将盒子设置成正方形,之后再将 border-radius 的 length 直接设置成宽度或高度的一半即可,或者直接写成 50%
  • 该属性是一个简写属性,可以设置四个方向的圆角(顺时针):
    • border-top-left-radius:上左圆角
    • border-top-right-radius:上右圆角
    • border-bottom-right-radius:下右圆角
    • border-bottom-left-radius:下左圆角

盒子阴影

CSS3 中新增了盒子阴影,可以通过 box-shadow 属性来设置,其语法如下:

1
box-shadow: h-shadow v-shadow blur spread color inset;
  • h-shadow:阴影在水平轴的位置,允许为负值
  • v-shadow:阴影在垂直轴的位置,允许为负值
  • blur:模糊距离,可选,影响阴影的模糊(虚化)程序,值越大虚化程度越高
  • spread:阴影的尺寸,可选,正值会让阴影扩大,负值会让阴影缩小
  • color:阴影的颜色
  • inset:可选,将外部阴影(outset)改为内部阴影

注意,默认就是外部阴影,不需要显式设置。如果显式设置 outset,反而会造成阴影无效。另外,盒子阴影不占用空间,不会影响其他盒子排列。

如下是一个示例:

1
2
3
div:hover {
box-shadow: 10px 10px 10px -4px rgba(0,0,0,.5);
}

文字阴影

CSS3 中也可以设置文字阴影,可以使用 text-shadow 属性,其语法如下:

1
text-shadow: h-shadow v-shadow blur color;
  • h-shadow:阴影在水平轴的位置,允许为负值
  • v-shadow:阴影在垂直轴的位置,允许为负值
  • blur:模糊距离,可选,影响阴影的模糊(虚化)程序,值越大虚化程度越高
  • color:阴影的颜色

如下是一个示例:

1
2
3
4
5
div {
font-size: 100px;
font-weight: 800;
text-shadow: 10px 10px 10px red;
}