一些基本概念

  • viewport: 展现网页的媒体,比如窗口或者某个区域,它的大小是有限制的,为了不被平台术语所束缚,我们给他起名viewport,中文意思就是视口。
  • canvas: 而我们在渲染网页的时候通常并不知道我们需要多大的空间,而且这些空间通常尺寸会超过viewport的大小,于是实际上我们需要设想一个无限大的画布来绘制我们的元素,我们把它称为canvas。
  • box: element(元素)和node(节点)是大家很熟悉的概念,当我们做布局计算的时候,通常会把节点变成box,一个节点可能产生多个box,伪元素也会产生box。
  • render tree: 对应于dom树,我们把box的包含关系构成的属性结构成为渲染树render tree

BFC

首先我们来考虑一个基本的情况:

run

<html>
<head><title>囧</title></head>
<body>
<div style="width:300px;height:50px;"></div>
<div style="width:300px;height:20px;"></div>
<div style="height:50px;"></div>
<div style="width:300px;height:50px;"></div>
</body>
</html>

之所以简单是因为这些div每一个只产生一个盒子,默认的display下,div产生块级盒,为了让块级盒按照我们的意愿排布,我们需要引入一个概念:block formatting context,简称BFC。

BFC其实是个相当简单的概念,然而因为实在中文中没啥合适的词来形容(你不觉得"块级格式化上下文"比BFC更让人觉得不知所云么?),这个概念已经被传得极其神秘:

在 CSS 面试中问 BFC 等概念,就如在 JS 面试中问闭包等概念一样,经常会刷掉一些真正优秀的人。 ——玉伯

甚至很多人连它是动词还是名词都搞不清,不信你可以搜索一下触发BFC,亲,BFC是名词啊……怎么它就能触发呢?

简单地说,BFC就是像例子里面一样顺次竖着排块级盒的一种上下文。竖着排盒子而已,竖着排盒子有什么理解不了的啊我X?

好吧平复一下情绪,我们继续说,canvas会设立一个BFC,这也是最外层的formatting context了,问题的复杂性在于有些块级盒内部也可以产生BFC(至少它必须也能包含块级盒),于是说BFC是可以嵌套滴:

run

<html>
<head><title>囧</title></head>
<body>
<div style="width:300px;height:100px;">
<div style="width:300px;height:20px;"></div>
<div style="height:50px;"></div>
</div>
<div style="height:50px;"></div>
</body>
</html>

不是所有块级盒内部都可以产生BFC,比如说要是这盒里面连块级盒都没有,都是行内盒那就产生IFC:

run

<html>
<head><title>囧</title></head>
<body>
<div style="width:300px;height:100px;overflow:visible;">
<span>囧</span><span>囧囧</span>
</div>
<div style="height:50px;"></div>
</body>
</html>

不过,只要它的子节点里面有一个块级盒,它就产生BFC,那些行内元素,会自动套一个匿名的块级行盒。

run

<html>
<head><title>囧</title></head>
<body>
<div style="width:300px;height:100px;overflow:visible;">
<span>囧</span><div>啦啦啦</div><span>囧囧</span>
</div>
<div style="height:50px;"></div>
</body>
</html>

又比如说overflow:visible的块盒就不产生BFC,不但不产生BFC,啥FC都不产生,它的子元素直接搞进自己外层的BFC鸟:

run

<html>
<head><title>囧</title></head>
<body>
<div style="width:300px;overflow:visible;">
<p style="width:200px;height:20px;"></p>
<p style="height:50px;">aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaaaa aaaa aaaa aaaa aaaa aaaa aaaa aaaa</p>
</div>
<p style="height:50px;"></p>
</body>
</html>

overflow:visible这个限制只对所谓的块盒(既包含块级盒、自己又是块级盒)存在,有些盒内部也能包含块级元素,但是它本身又不是块级元素(比如display为table-cell、inline-block、或者盒本身是flex item等),因为外面不是BFC,所以它们不论如何一定会给包含的块级盒创建一个新的BFC出来。

同一个BFC里面的盒还会有margin collapse现象,详情见此文 《谈margin collapsing(外边距叠加)》

IFC

IFC里面可能有文字、行内元素混合排布:

run

<html>
<head><title>囧</title></head>
<body>
<div style="">
<span>囧</span>囧囧囧<span>囧囧</span>
</div>
</body>
</html>

文本的排布是个很复杂的事情,在dom树中,我们存储的是字符和字符串,而在render tree中,我们要使用一个新的概念:字型(glyph)。字体文件(通常是ttf,ture type格式的)中包含着不同字体下字符到字型的规则。

一个字型有很多属性,下面这张图来自freetype,它是大部分浏览器使用的文字排版基础库:

详情请看这里

图中的那根加粗的X轴就是传说中的基线(base line)了,文字默认是按照基线对齐的。

下面这个demo展示了一个IFC中的几条重要的基准线:

baseline
 
sub
 
super
 
top
 
text-top
 
middle
 
bottom
 
text-bottom

 

great it works!2囧啊

在水平方向,文字的排布主要受到以下属性影响

  • word-break, word-spacing, word-wrap
  • letter-spacing
  • white-space
  • text-align
  • hyphenate-character, hyphenate-limit-after, hyphenate-limit-before, hyphenate-limit-lines, hyphens
  • justify-content
  • ……

总之很复杂,讲也讲不完,而且大家又不要写浏览器所以大家就大概望文生义一下好了(po主被扔蛋中……)。

对于一个正常的"行盒"来说,文字总是垂直居中排布的。

在纵向,文本排布主要受line-height属性影响,在有行内盒参与的情况下就复杂了,

一个行内盒的vertical-align可以有这样几种取值:

  • baseline
  • sub
  • super
  • top
  • text-top
  • middle
  • bottom
  • text-bottom

它也可以是某一指定高度。根据行内盒的对齐方式,它有可能把这行盒向上或者向下"撑大",造成超过行高的情况。

所以行盒在BFC中占据的实际高度,很可能大于line-height。

文字的baseline很好理解,而行内元素则比较复杂,特别是当行内元素自身又是容器的时候:

run

<html>
<head><title>囧</title></head>
<body>
<div style="overflow:visible;">
<span>囧</span>囧囧囧<div style="display:inline-block;width:300px;height:300px;"></div><span>囧囧</span>
</div>
</body>
</html>

run


<html>
<head><title>囧</title></head>
<body>
<div style="overflow:visible;">
<span>囧</span>囧囧囧<div style="display:inline-block;width:300px;height:300px;">123<br/>123<br/>123</div><span>囧囧</span>
</div>
</body>
</html>

浮动

浮动是个行级的行为,当遇到浮动元素的时候,会首先"假装"它是个行内元素进行排版,排好后就往浮动的方向挤到挤不过去为止(遇到边界或者其它浮动元素)。

run

<html>
<head><title>囧</title></head>
<body>
<div style="">
<span>囧</span>囧囧囧<div style="display:inline-block;width:300px;height:300px;float:left"></div><span>囧囧</span>
</div>
</body>
</html>

run

<html>
<head><title>囧</title></head>
<body>
<div style="">
<span>囧</span>囧囧囧<div style="display:inline-block;width:300px;height:300px;float:left"></div><span>囧囧</span><br/>
<div style="display:inline-block;width:300px;height:300px;float:left"></div>
</div>
</body>
</html>

某一方向有clear的时候,浮动元素总是挤到边界,在垂直方向上的行为类似"换行"。

run

<html>
<head><title>囧</title></head>
<body>
<div style="">
<span>囧</span>囧囧囧<div style="display:inline-block;width:300px;height:300px;float:left"></div><span>囧囧</span><br/><div style="clear:left;display:inline-block;width:300px;height:300px;float:left"></div>
</div>
</body>
</html>

排好一个浮动元素之后,这一行就要重排一次。所以说浮动元素会造成行级的reflow。重排的时候,行盒会躲开浮动元素。之后的块级盒(不论是行盒还是其它盒)也都会躲开浮动元素排布。

最新文章

  1. 用C语言编写生成小学四则运算程序
  2. Jquery全选单选功能
  3. GIS理论(墨卡托投影、地理坐标系、地面分辨率、地图比例尺、Bing Maps Tile System)
  4. JAVA并发编程的艺术目录
  5. Lintcode: Maximum Subarray Difference
  6. bind,call,apply区别
  7. Xmarks丢失书签
  8. Android 多点触控错误处理(java.lang.IllegalArgumentException: pointerIndex out of range)
  9. 基于Windows的套接字相关函数及示例
  10. WebRTC clientICE 延迟问题
  11. linux 输入输出重定向
  12. 利用Inotify和Rsync将webproject文件自己主动同步到多台应用server
  13. Poj 2777 Count Color(线段树基础)
  14. 重写IHttpHandler,实现前后端分离
  15. FZU 1502 Letter Deletion(DP)
  16. Swoole笔记(四)
  17. 【RN6752】模拟高清AHD芯片或成为车机新标配
  18. 4月22日MySQL学习
  19. CF176E Archaeology
  20. df -i 100%时处理方法

热门文章

  1. 华为终端开放实验室Android P Beta 4测试能力上线
  2. abp相关
  3. Spring MVC可参数化的视图控制器
  4. PYTHON -创建 表 和 插入 数据
  5. Hough变换的基本思考
  6. mybatis基础,mybatis配置文件核心组件typeAliases元素
  7. ZOJ1311(Network)
  8. Sping Cloud 微服务框架学习
  9. nginx + uwsgi + django/flask Nginx + php-fpm + PHP
  10. &lt;2013 12 28&gt; AOI PCB设计