内容简介:前言:接下来的几篇系列文章我们讲一个东西:盒子(BOX)。 “盒模型”(box model)作为 CSS 看待元素的一种方式,CSS 将每个元素都看作由一个盒子表示。从某方面来说,对于初级、中级学习者的我们,大可将 CSS 的学习看作是对“盒子”的学习。 为什么这么说?请看下图我个人的 CSS 学习流程:图中我们可以看到,几乎所有的内容都是围绕着“盒子”这个东西在展开。本篇我们将阐述最基本的理论知识,将“盒子”的方方面面一步步带到我们跟前。
本文推荐 PC 端阅读~ 本文同步更新于: - 「公众号:前端一万小时」 - 「知乎:Oli's 前端一万小时」 - 「语雀:前端一万小时」 本文版权归 “前端一万小时” 所有,未经授权,请勿转载! 复制代码
前言:接下来的几篇系列文章我们讲一个东西:盒子(BOX)。 “盒模型”(box model)作为 CSS 看待元素的一种方式,CSS 将每个元素都看作由一个盒子表示。从某方面来说,对于初级、中级学习者的我们,大可将 CSS 的学习看作是对“盒子”的学习。 为什么这么说?请看下图我个人的 CSS 学习流程:
图中我们可以看到,几乎所有的内容都是围绕着“盒子”这个东西在展开。
本篇我们将阐述最基本的理论知识,将“盒子”的方方面面一步步带到我们跟前。
1 什么是“盒子”
“盒子 box”由 CSS 引擎根据文档中的内容所创建,主要用于文档元素的格式化、定位和布局等。
盒子与元素并不是一一对应的,有时多个元素会合并生成一个盒子,有时一个元素会生成多个盒子(如匿名盒子)。
一个完整的“盒子”中心有一个内容区(content area)。这个内容区周围有可选的 padding、边框和 margin。这些项之所以被认为是可选的,是因为它们的宽度可以设置为 0,实际上就是从“盒子”上去除这些项。
一个完整的“盒子”
2 “视觉格式化模型”概述
CSS 视觉格式化模型(visual formatting model)是用来处理和在视觉媒体上显示文档时使用的计算规则。
通俗的讲就是:页面(文档树)可以想象成是由一个个 box 组合而成的,而“视觉格式化模型(Visual formatting model)” 是一套规则,将这些 box “布局”成访问者看到的样子。
每个盒子的“布局”由以下因素决定( 本篇文章和下一篇文章主要讲解第①、②点,其属于“最基本的视觉格式化”,而对于剩下的要点,我们在接下来的系列文章中会挨个讨论 ):
① 盒子的尺寸:精确指定、由约束条件指定或没有指定;
② 盒子的类型:行内盒子(inline box)、行内级盒子(inline-level box)、原子行内级盒子(atomic inline-level box)、块盒子(block box);
③ 定位方案(positioning scheme):普通流定位、浮动定位或绝对定位;
④ 文档树中的其它元素:即当前盒子的子元素或兄弟元素;
⑤ 视口尺寸与位置;
⑥ 所包含的图片的尺寸;
⑦ 其他的某些外部因素。
每一个元素都是一个“盒子”,“盒子”可以嵌套“盒子”
:bulb:如上图所示, 视觉格式化模型 会根据盒子的“包含块”( containing block )——(包含其他盒子的块称为“包含块”)的边界来渲染盒子。通常,盒子会创建一个包含其后代元素的“包含块”,但是盒子并不由“包含块”所限制,当盒子的布局跑到”包含块“的外面时称为溢出( overflow )。
上图中,section 的包含块是 body ,header、article、footer 的包含块是 section。
:warning:区别:
- “盒子模型”是处理盒子本身的内部属性——边距、边框等;
- 而“视觉格式化模型”是用来处理这些盒子的摆放。
3 关于“盒子”我们一定需要知道的——基本视觉格式化
3.1 “盒子”的生成
盒子的生成是 CSS “视觉格式化模型”的一部分,用于从文档元素生成盒子。
盒子有不同的类型,盒子的类型取决于 CSS 的 display 属性——元素“角色”的改变。
3.1.1 “块级元素”和“块级盒子”
或 table 时,该元素将成为“块级元素”。
这些元素在正常流中时,会在其框之前和之后生成“换行”,所以处于
正常流中的块级元素会“垂直”摆放 。选择器 { display: block、list-item 或 table; } 复制代码
:bulb:(“正常流”是指:西方语言文本从左向右、从上向下显示的方向,这也是我们熟悉的传统 HTML 文档的文本布局方向。注意,在非西方语言中,流方向可能不同。)
但,元素是否是“块级元素”仅是元素本身的属性,并不直接用于格式化上下文的创建或布局。
一个“块级元素”会被格式化成一个块(例如文章的一个段落),且默认按照垂直方向依次排列。
:bulb:一个“块级元素”都会至少生成一个“块级盒子”,也有可能生成多个(例如列表项元素)。而“块级盒子”才会参与“块格式化上下文(block formatting context)”的创建。
3.1.2 “行内级元素”和“行内盒子”
当元素的 display 属性为 inline、inline-block 或 inline-table 时,该元素将成为“行内级元素”。
选择器 { display: inline、inline-block 或 inline-table; } 复制代码
这些元素不会在之前或之后生成“行分隔符”,所以处于正常流中的块级元素会 “水平” 摆放,它们是块级元素的后代。
显示时,它 不会生成内容块 ,但是可以与其他行内级内容一起显示为多行。
:bulb:同理,“行内级元素”会生成“行内级盒子”,该盒子同时会参与“行内格式化上下文(inline formatting context)”的创建。
:trophy:小总结:相对更详细的“盒子”细分:
:warning: 注意 :一定要记得的是,display 之所以得名,是因为它影响的是元素如何“显示”,而不影响他本质上是何种元素,也就不能乱玩“嵌套关系”!
一个极端的反例就是:你不能让一个“链接”来包围一个“段落”。
<a href="http://…" style="display: block;"> <p style="display: inline;">这是一个错误的示例</p> </a> 复制代码
(对于生成不同类型“盒子”在实际项目中的运用,我们将在后续文章详细讨论。例如:怎样给“链接”加样式——生成导航栏、怎样给“表单”加样式等。)
3.2不同类型“盒子”在格式化方式上也有所不同
本篇我们主要探讨 “块盒子”格式化,下篇文章讨论“行内盒子”格式化。
块盒子
3.2.1水平格式化
正常流中,“块盒子”的水平部分 = 其父元素的 width = 7 个属性之和——(margin-left :heavy_plus_sign:margin-right) :heavy_plus_sign: (padding-left :heavy_plus_sign: padding-right):heavy_plus_sign:(border-left :heavy_plus_sign: border-right):heavy_plus_sign: 内容区自身 width 。
在这 7 个属性中只有 3 个属性的值可以设置为 auto:width、margin-left、margin-right。其余的要不必须是确定的值,要不就是默认值 0。
:rocket:可详细分为以下 5 种组合:
- 3 个都不是 auto:按 CSS 的术语来讲,这叫“格式化属性过分受限”, 此时总会把 margin-right 强制为 auto 来适应父元素的宽度 ;
- 2 个不是 auto:是 auto 的将自动调整到适应父级元素的宽度;
- margin-left、margin-right 是 auto:他们会自动设置为相等的长度, 导致此元素在其父级元素中居中 ;
- 一个 margin 和 width 是auto:auto 的 margin 会减为0,width 自动填充其包含块;
- 3 个都是 auto:两个外边距减为 0,width 会尽可能的宽(自动充满)。
:warning:注意:由于 水平 margin 不会合 并,父元素的 padding 、边框、margin 可能会对子元素带来“偏移”的影响。
3.2.2垂直格式化
正常流中,“块盒子”的垂直部分 = 其父元素的 heigh t = 7 个属性之和——(margin-top :heavy_plus_sign: margin-bottom) :heavy_plus_sign: (padding-top :heavy_plus_sign: padding-bottom):heavy_plus_sign:(border-top :heavy_plus_sign: border-bottom):heavy_plus_sign: 内容区自身 height 。
同理,在这 7 个属性中只有 3 个的值可以设置为 auto:height、margin-top、margin-bottom。其余的要不必须是确定的值,要不就是默认值 0。
:warning:不过,margin-top 和 margin-bottom 设置为 auto 也没有什么用,因为会被重置为 0。所以,想利用上下 margin 都是 auto 来垂直居中是不可能的。
垂直格式化的另一个重要方面是垂直相邻 margin 的合并。
这种合并行为只应用于 margin,如果元素有 padding 和边框,padding 和边框是不会合并的。当两个或更多垂直 margin 相遇时,他们将形成唯一一个 margin,这个 margin 的高度等于两个发生叠加的 margin 的高度中的较大者。
:warning:注意:当一个元素包含在另一个元素中时,彼此相邻的 margin-bottom 和 magin-top 也会发生叠加,取较大者。
3.2.3 负 margin
提问:水平或垂直方向各自 7 大属性相加要等于父元素的 width 或 height,那 margin 为负值会造成什么结果?
1. 水平方向
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>JS Bin</title> </head> <body> <div> <p class="wide">How are you?</p> <p>Fine,thank you,and you?</p> </div> </body> </html> 复制代码
(1)类型①
div { width: 400px; border: 3px solid black; } p.wide { border: 1px dashed black; margin-left: 20px; width: auto; margin-right: -50px; background-color: yellow; } 复制代码
(2)类型②
div { width: 400px; border: 3px solid black; } p.wide { border: 1px dashed black; margin-left: 20px; width: 500px; margin-right: auto; background-color: yellow; } 复制代码
(3)类型③
div { width: 400px; border: 3px solid black; } p.wide { border: 1px dashed black; margin-left: -50px; width: auto; margin-right: 10px; background-color: yellow; } 复制代码
2. 垂直方向
(1)类型 ①:负 margin-top
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>JS Bin</title> </head> <body> <div> <p class="wide1">How are you?</p> <p class="wide2">Fine,thank you,and you?</p> </div> </body> </html> 复制代码
div { width: 400px; border: 3px solid black; } p.wide1 { border: 1px dashed black; margin-top: -20px; /*修改这里的值来观察效果*/ margin-right: 20px; margin-bottom: 30px; margin-left: 20px; width: auto; background-color: yellow; } p.wide2 { border: 1px dashed black; margin-top: ; margin-right: 20px; margin-bottom: ; margin-left: 20px; width: auto; background-color: grey; } 复制代码
:bulb:把段落1的 margin-top 设为“负”,它就被向上“拉”了 20 像素,且紧挨它的段落2也相应向上拉了 20 像素。
(2)类型 ②:负 margin-bottom
div { width: 400px; border: 3px solid black; } p.wide1 { border: 1px dashed black; margin-top: px; margin-right: 20px; margin-bottom: -50px; /*修改这里的值来观察效果*/ margin-left: 20px; width: auto; background-color: yellow; } p.wide2 {border: 1px dashed black; margin-top: ; margin-right: 20px; margin-bottom: ; margin-left: 20px; width: auto; background-color: grey; } 复制代码
:bulb:把段落1的 margin-bottom 设为“负”,段落2会根据段落1底端的位置放置。
(3)类型 ③:正负 margin 合并
“块盒子”重叠的时候,如果垂直 margin 都为负值,浏览器会取两个 margin 绝对值的最大值;如果一个正 margin 与一个负 margin 合并,则会从正 margin 减去这个负 margin 的绝对值。
:link:效果及源码链接<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>JS Bin</title> </head> <body> <div> <ul> <li>Fine</li> <li>thank you</li> <li>and you?</li> </ul> <p>回答 How are you? 的方式!</p> </div> </body> </html> 复制代码
div { width: 400px; border: 3px solid black; } ul { border: 1px dashed black; margin-top: px; margin-right: 20px; margin-bottom: -15px; /*①修改这里的值来观察效果*/ margin-left: 20px; width: auto; background-color: yellow; } li { border: 1px dashed black; margin-top: ; margin-right: 20px; margin-bottom: 20px; /*②修改这里的值来观察效果*/ margin-left: 20px; width: auto; background-color: grey; } p { border: 1px dashed black; margin-top: -18px; /*①修改这里的值来观察效果*/ margin-right: 20px; margin-bottom: px; margin-left: 20px; width: auto; background-color: yellow; } 复制代码
:bulb:ul 和 p 重叠的 margin 都为“负”,则取绝对这较大者(-18px)
:bulb:当上边的较大者(-18px)增加到 li 的最大正 margin 上(20px)时,就得到了 20px - 18px =2px
后记:这篇我们学习了“块盒子”的格式化方式,下一篇我们接着这篇继续探讨“行内盒子”的格式化方式。在“行内盒子”格式化方式中,我们会谈到很多细小的基础知识,和本篇的学习方式一样,让我们尽可能的用代码、用图片来攻克它们。
加油!
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。