![219a4e284d69533d92473a31f9c08b9b.png](https://i-blog.csdnimg.cn/blog_migrate/afb0deabb5733d16cf46607f95da676c.jpeg)
昨天的章节看过了盒模型的填充(内边距)和边框,以及不占据空间的轮廓,由于 CSS 3 引入了一些相对方便的新属性,这一章节除了继续来看盒模型的(外)边距以及尺寸,也要看看弹性盒子。
1 边距
Margin (外)边距是元素边界与其周围之间的距离,包括如下属性:
- margin-top:设置顶边的边距
- margin-right:设置右边的边距
- margin-bottom:设置底边的页边距
- margin-left:设置左边的边距
- margin:简写属性,在单个声明中设置所有边的边距,和其他有四方向属性的简写一致,也是可以使用 1 - 4 个值来进行设置的,具体规则可以参考盒模型(1)当中的 padding 部分。
下面是个例子:
<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
img {
border: 4px solid black;
background: lightgray;
padding: 4px;
margin: 4px 20px;
}
</style>
</head>
<body>
<img src="download.png" alt="download">
<img src="download.png" alt="download">
</body>
</html>
![39f58d0f6e6a96a7217ee74534f208e8.png](https://i-blog.csdnimg.cn/blog_migrate/74d21aaedc23e42d4a70da16325d0539.jpeg)
![639f87b34f946e329391aa6d8f5b241d.png](https://i-blog.csdnimg.cn/blog_migrate/300e928335fc82a6cd79c23858a9cc7f.jpeg)
当然,虽然设置了(外)边距,但是因为没有明确的边界,所以肉眼基本是看不出来大小的,只能通过最后一张截图的盒模型来看到该设置是如何生效的。
2 尺寸
可以使用 width, height 以及相关的属性来控制元素的尺寸,包括:
- width, height:设置元素的宽度和高度
- min-width, min-height:设置元素的最小可接受宽度或高度
- max-width, max-height:设置元素的最大可接受宽度或高度
- box-sizing:设置元素框的哪个部分用于大小调整,可以接受的值根据盒模型包括
- content-box
- padding-box
- border-box
- margin-box
所有这些属性的默认值是auto,浏览器会找出元素的宽度和高度。
2.1 尺寸设置
通过这些属性,我们可以显式的设置元素的尺寸,比如:
<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
div {
width: 75%;
height: 100px;
border: thin solid black;
}
img {
background: lightgray;
border: 4px solid black;
margin: 2px;
height: 50%;
}
#first {
box-sizing: border-box;
width: 50%;
}
#second {
box-sizing: content-box;
}
</style>
</head>
<body>
<div>
<img id="first" src="download.png" alt="download">
<img id="second" src="download.png" alt="download">
</div>
</body>
</html>
![7d99c395156127eae5fc1091c33f8bbf.png](https://i-blog.csdnimg.cn/blog_migrate/8cb2212410b0e80080438c6d9dc2ec1e.jpeg)
上面的代码将 #first 的宽度显式的指定为 div 宽度的 50%, 而 div 的宽度为浏览器当前宽度的 75% ,所以看起来变形了。
而 img 的高度设置为 div 高度的 50%,所以两个图标事实上为 50px 高,至于 #second 没有变形的原因,是因为没有显式的指定宽度,也就是默认值 auto。
通过上面的例子,我们也可以看看如果将宽度和高度设置为自动,会是怎样的,如下:
<!DOCTYPE HTML>
<html>
<head>
<style type="text/css">
p {
padding: 10px;
margin: 10px;
border: thin solid black;
width: auto;
min-width: 200px;
}
img#x-aspect-1 {
border: 1px solid black;
margin: 5px;
width: 200px;
height: auto;
}
</style>
</head>
<body>
<p>This is a test. This is a test.</p>
<img src="download.png" id="x-aspect-1" />
</body>
</html>
![4e3b20ae1bb91b8c8bac24fcc8ce4d96.png](https://i-blog.csdnimg.cn/blog_migrate/1523b8e1e0911bffcc2d16e1be80679a.jpeg)
上面的代码,设置了 img 的宽度,而高度显式的设置为 auto (当前不显式的设置也是一样的),所以图片本身被放大了,并且维持了原有比例;而 p 的宽度设置为 auto,但是有个最小的宽度,也就是说即使窗口缩小的更多,p 元素的宽度也不会小于下面图片的宽度。
2.2 框大小
CSS 3 引入的 box-sizing 属性可以设置 width 和 height 属性中,包含了 padding 和 border,这个属性的主要目的是为了解决原来设置了填充和边框之后,与自己预期元素尺寸不符合的情况而出现的。
下面是个例子:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>hello</title>
<style>
.div1 {
width: 300px;
height: 100px;
border: 1px solid blue;
}
.div2 {
width: 300px;
height: 100px;
padding: 50px;
border: 1px solid red;
}
</style>
</head>
<body>
<div class="div1">这个是个较小的框 (width 为 300px ,height 为 100px)。</div>
<div class="div2">这个是个较大的框 (width 为 300px ,height 为 100px)。</div>
</body>
</html>
![8901d45bab834758d22d82978d5a914e.png](https://i-blog.csdnimg.cn/blog_migrate/792636d905c028fe5d9e0dbad8e8ca29.jpeg)
上面的代码中可以看到,两个 div 设置了同样的高度和宽度,但因为填充(内边距)的不同,造成了框的大小有明显的不同。
而通过设置 box-sizing 我们可以明显看到,两个框大小一致了:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>hello</title>
<style>
.div1 {
width: 300px;
height: 100px;
border: 1px solid blue;
box-sizing: border-box;
}
.div2 {
width: 300px;
height: 100px;
padding: 50px;
border: 1px solid red;
box-sizing: border-box;
}
</style>
</head>
<body>
<div class="div1">现在的框一样大</div>
<div class="div2">现在的框一样大</div>
</body>
</html>
![07cdd532d83035821111d8e6bc492da9.png](https://i-blog.csdnimg.cn/blog_migrate/16feb3fe9e219b3a92c9d2e05e5026d3.jpeg)
如上所示,这个元素可以让所有元素以更直观的方式展示大小。很多浏览器已经支持 box-sizing: border-box; (但是并非所有 - 这就是为什么有时 input 和 text 元素设置了 width: 100%; 后的宽度却不一样)。
推荐所有元素都使用 box-sizing:
* {
box-sizing: border-box;
}
3 弹性盒子
弹性盒子是 CSS 3 的一种新的布局模式。
CSS 3 弹性盒( Flexible Box 或 flexbox),是一种当页面需要适应不同的屏幕大小以及设备类型时确保元素拥有恰当的行为的布局方式。
引入弹性盒布局模型的目的是提供一种更加有效的方式来对一个容器中的子元素进行排列、对齐和分配空白空间。
3.1 简介
弹性盒子由弹性容器(Flex container)和弹性子元素(Flex item)组成,通过设置 display 属性的值为 flex 或 inline-flex将其定义为弹性容器。
弹性容器内包含了一个或多个弹性子元素。
注意: 弹性容器外及弹性子元素内是正常渲染的。弹性盒子只定义了弹性子元素如何在弹性容器内布局。
弹性子元素通常在弹性盒子内一行显示,默认情况每个容器只有一行,下面是个例子:
<!DOCTYPE html>
<html>
<head>
<style>
.flex-container {
display: flex;
width: 400px;
height: 250px;
background-color: lightgrey;
}
.flex-item {
background-color: cornflowerblue;
width: 100px;
height: 100px;
margin: 10px;
}
</style>
</head>
<body>
<div class="flex-container">
<div class="flex-item">flex item 1</div>
<div class="flex-item">flex item 2</div>
<div class="flex-item">flex item 3</div>
</div>
</body>
</html>
![0d213123f04ba776f6ad6de962483614.png](https://i-blog.csdnimg.cn/blog_migrate/0ac4748bd0f6ee06b29826f395e48c0c.jpeg)
上面的代码是一个基础的例子,我们还可以修改排列方式。
如果我们设置 direction 属性为 rtl(右到左),其余什么都不改变,则弹性子元素的排列方式也会改变,页面布局也跟着改变:
body {
direction: rtl;
}
![e1e6b4e2d732d86855ad76585e78dd1e.png](https://i-blog.csdnimg.cn/blog_migrate/85a30d810a3b369c6a892e3ef7b108db.jpeg)
这样设置,所有的容器都会遵循从右向左的方式排列,不过文字不会,因为英文本身不是从右向左排列的语言。
3.2 子元素排列(容器属性)
flex-direction 顺序指定了弹性子元素在父容器中的位置,它可以在不设置整体 direction 的情况下,单独设置弹性子元素的排列方式,它可以包含如下值:
- row:横向从左到右排列(左对齐),默认的排列方式
- row-reverse:反转横向排列(右对齐,从后往前排,最后一项排在最前面
- column:纵向排列
- column-reverse:反转纵向排列,从后往前排,最后一项排在最上面
在3.1这一节中的第一个例子的基础上,加一行代码即可:
.flex-container {
display: flex;
flex-direction: row-reverse; /* 增加该行 */
width: 400px;
height: 250px;
background-color: lightgrey;
}
![cb5366e873076e0147e03f33c1808e8c.png](https://i-blog.csdnimg.cn/blog_migrate/94d5648b24fdd61452976fae15ab1f47.jpeg)
这种方式,仅仅将弹性子元素的排序反了过来,但是并不影响其他元素。
而通过设置为 column 可以让弹性子元素纵向排列:
flex-direction: column;
![b7f404a7f2850856ae93a1d9b839cb05.png](https://i-blog.csdnimg.cn/blog_migrate/3a91cd6b5ae42a56fa13b1034c3a39ae.jpeg)
同样也可以进行纵向的反序排列:
flex-direction: column-reverse;
![cc882e76e56dfa54239fa169af281ed8.png](https://i-blog.csdnimg.cn/blog_migrate/fa5b7c559a8952f020f64c5ecf84d68c.jpeg)
3.3 水平对齐(容器属性)
justify-content 属性应用在弹性子元素上,设置它(们)在母元素当中的水平对齐方式,它可以包含如下值:
- flex-start:项目位于容器的开头,这个是默认值,即子元素靠头部排列
- flex-end:项目位于容器的结尾,即子元素靠尾部反向排列
- center:项目位于容器的中心,即子元素居中
- space-between:项目位于各行之间留有空白的容器内,相邻项目的间隔相等
- space-around:项目位于各行之前、之间、之后都留有空白的容器内,彼此间隔相等(比如是20px),同时首尾两边和子元素之间留有一半的间隔(1/2 * 20px = 10px)
因为 flex-start 是默认值,所以从 flex-end 开始,我们逐一演示几个值的渲染效果:
flex-end:
.flex-container {
display: flex;
justify-content: flex-end; /* 增加该行 */
width: 400px;
height: 250px;
background-color: lightgrey;
}
![5a8466b27b14e677d9d9d63d655a3aa2.png](https://i-blog.csdnimg.cn/blog_migrate/c088a7b866b60fda12b0cff461c7563c.jpeg)
center:
justify-content: center;
![8aadc5e81794780e1b7b9a84694264e0.png](https://i-blog.csdnimg.cn/blog_migrate/723b20f3edb92d70cf2fe54497329e45.jpeg)
space-between:
justify-content: space-between;
![3e4e753238baa6d0dd005b803aa858c1.png](https://i-blog.csdnimg.cn/blog_migrate/ecf815b361f5dfc1c9181d5d21819cc3.jpeg)
space-around:
justify-content: space-around;
![23b35c1fc79dc2ac3ae81b9bcdce9e3c.png](https://i-blog.csdnimg.cn/blog_migrate/60a769b3b8e857cf940a64979a8f455e.jpeg)
3.4 垂直对齐(容器属性)
align-items 属性应用在弹性子元素上,设置它(们)在母元素当中的垂直对齐方式,它可以包含如下值:
- stretch:默认值,元素被拉伸以适应容器
- flex-start:元素位于容器的开头
- flex-end:元素位于容器的结尾
- center:元素位于容器的中心
- baseline:元素位于容器的基线上,通常是和 flex-start 相同的结果
我们在上面代码的基础上,依次来看看各属性的渲染结果:
stretch:
.flex-container {
display: flex;
align-items: stretch; /* 增加该行 */
width: 400px;
height: 250px;
background-color: lightgrey;
}
.flex-item {
background-color: cornflowerblue;
width: 100px;
margin: 10px;
}
![b6120c6f15991af6731278e8194cf49c.png](https://i-blog.csdnimg.cn/blog_migrate/6cfc36a4b2c1f507275bfd9d3fa72710.jpeg)
flex-start:
align-items: flex-start;
![9f44166fc8328da0ed052dba08efe442.png](https://i-blog.csdnimg.cn/blog_migrate/137938d751a07dc578920d0b9025f557.jpeg)
flex-end:
align-items: flex-end;
![69c6b118eaa6cf3c4a16d8be61a6034b.png](https://i-blog.csdnimg.cn/blog_migrate/31c056c037ef983b3c6691a07747f697.jpeg)
center:
align-items: center;
![eebba2d5-4551-eb11-8da9-e4434bdf6706.png](http://p01.5ceimg.com/content/eebba2d5-4551-eb11-8da9-e4434bdf6706.png)
baseline:
align-items: baseline;
![92a051c915d79e99fef7e32c0047c782.png](https://i-blog.csdnimg.cn/blog_migrate/2a5869534c098c8cbc1266adbc630bb1.jpeg)
3.5 子元素换行(容器属性)
flex-wrap 属性用于指定子元素换行方式,它可以包含如下值:
- nowrap:默认,弹性容器为单行,该情况下弹性子项可能会溢出容器
- wrap:弹性容器为多行,该情况下弹性子项溢出的部分会被放置到新行,子项内部会发生断行
- wrap-reverse:反序 wrap 排列
同样分别来看渲染效果:
nowrap:
.flex-container {
display: flex;
flex-wrap: nowrap; /* 增加该行 */
align-content: center; /* 为了效果明显,将子元素垂直居中 */
width: 300px;
height: 300px;
background-color: lightgrey;
}
.flex-item {
background-color: cornflowerblue;
width: 100px;
height: 100px;
margin: 10px;
}
![49a7f1e5671ba43e9bb0f448780602e0.png](https://i-blog.csdnimg.cn/blog_migrate/63d4288f616a0f9b33d51f6a73cf72f7.jpeg)
wrap:
flex-wrap: wrap;
![45999b762eedd74151c03677bf1e66be.png](https://i-blog.csdnimg.cn/blog_migrate/a539b0774c56972b822528021af3a5e3.jpeg)
wrap-reverse:
flex-wrap: wrap-reverse;
![eb3c7ada25a031ff92fd319123d8c93a.png](https://i-blog.csdnimg.cn/blog_migrate/b8b87f11ac607cfcbd59e5d496c5f603.jpeg)
3.6 子元素排序(子元素属性)
order 属性可以手动的指定子元素的序号,它只接受整数值:数值小的排在前面,可以为负值。
下面是个例子:
<!DOCTYPE html>
<html>
<head>
<style>
.flex-container {
display: flex;
width: 400px;
height: 250px;
background-color: lightgrey;
}
.flex-item {
background-color: cornflowerblue;
width: 100px;
height: 100px;
margin: 10px;
}
.first {
order: -1;
}
</style>
</head>
<body>
<div class="flex-container">
<div class="flex-item">flex item 1</div>
<div class="flex-item first">flex item 2</div>
<div class="flex-item">flex item 3</div>
</div>
</body>
</html>
![c7a56ab9bc37d657d0c9b8109630eaea.png](https://i-blog.csdnimg.cn/blog_migrate/ce0a7022cec8f978ad13795f6af6f166.jpeg)
可以看到,我们给 flex item 2 定义了新的 class 为 first,这里我们定义 .first 的序号为 -1,所以它的排序变成了第一位。
3.7 子元素对齐(子元素属性)
设置子元素的 margin 值为 auto,自动获取弹性容器中剩余的空间。所以设置垂直方向margin 值为 auto,可以使弹性子元素在弹性容器的两上轴方向都完全居中。
以下例子在第一个弹性子元素上设置了 margin-right: auto; ,它将剩余的空间放置在元素的右侧:
.flex-item:first-child {
margin-right: auto;
}
![1b20c1d26950aa954f18c3bd79cbe5a1.png](https://i-blog.csdnimg.cn/blog_migrate/3aa8f6574e000ccd8a10974f7ceb2112.jpeg)
下面的例子则可以完美解决我们平时碰到的居中问题,使用弹性盒子,居中变的很简单,只要设置 margin: auto; 就可以使得弹性子元素在两上轴方向上完全居中:
.flex-item {
background-color: cornflowerblue;
width: 75px;
height: 75px;
margin: auto;
}
![651018bccaaf4c7965360b6765dcd658.png](https://i-blog.csdnimg.cn/blog_migrate/c06b715036574c7ca0c92bb66aa26911.jpeg)
3.8 子元素垂直位置(子元素属性)
align-self 属性用于设置子元素自身的垂直位置,它可以包含如下值:
- auto:默认值,元素继承了它的父容器的 align-items 属性。如果没有父容器则为 stretch
- flex-start:元素位于容器的开头
- flex-end:元素位于容器的结尾
- center:元素位于容器的中心
- baseline:元素位于容器的基线上
- stretch:元素被拉伸以适应容器
下面是个例子:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>hello</title>
<style>
.flex-container {
display: flex;
width: 400px;
height: 250px;
background-color: lightgrey;
}
.flex-item {
background-color: cornflowerblue;
width: 60px;
min-height: 100px;
margin: 10px;
}
.item1 {
align-self: flex-start;
}
.item2 {
align-self: flex-end;
}
.item3 {
align-self: center;
}
.item4 {
align-self: baseline;
}
.item5 {
align-self: stretch;
}
</style>
</head>
<body>
<div class="flex-container">
<div class="flex-item item1">flex-start</div>
<div class="flex-item item2">flex-end</div>
<div class="flex-item item3">center</div>
<div class="flex-item item4">baseline</div>
<div class="flex-item item5">stretch</div>
</div>
</body>
</html>
![e054adbddd606b992c91d3c34cd28db6.png](https://i-blog.csdnimg.cn/blog_migrate/13dd80363b992264127599a319b1f39b.jpeg)
3.9 子元素空间(子元素属性)
flex 属性用于指定弹性子元素如何分配空间,它是 flex-grow、flex-shrink 和 flex-basis 属性的简写属性,可以包含如下值:
- none:与 0 0 auto 相同
- auto:与 1 1 auto 相同
- [ flex-grow ]:一个数字,规定项目将相对于其他灵活的项目进行扩展的量
- [ flex-shrink ]:一个数字,规定项目将相对于其他灵活的项目进行收缩的量
- [ flex-basis ]:项目的长度,可以包含值:auto、inherit 或 CSS 长度单位
下面的例子里,第一个弹性子元素占用了 1/2 的空间,其他两个各占 1/4 的空间:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>hello</title>
<style>
.flex-container {
display: flex;
width: 400px;
height: 250px;
background-color: lightgrey;
}
.flex-item {
background-color: cornflowerblue;
margin: 10px;
}
.item1 {
flex: 2;
}
.item2 {
flex: 1;
}
.item3 {
flex: 1;
}
</style>
</head>
<body>
<div class="flex-container">
<div class="flex-item item1">flex item 1</div>
<div class="flex-item item2">flex item 2</div>
<div class="flex-item item3">flex item 3</div>
</div>
</body>
</html>
![2b56b1cbe0f8e9b2b49b3e9499c7d5aa.png](https://i-blog.csdnimg.cn/blog_migrate/ffb8019847f1a5131d00f2e3ab3e3c57.jpeg)