一些基本概念

  • 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。重排的时候,行盒会躲开浮动元素。之后的块级盒(不论是行盒还是其它盒)也都会躲开浮动元素排布。

bfc (收集的)的更多相关文章

  1. 前端精选文摘:BFC 神奇背后的原理

    BFC 已经是一个耳听熟闻的词语了,网上有许多关于 BFC 的文章,介绍了如何触发 BFC 以及 BFC 的一些用处(如清浮动,防止 margin 重叠等).虽然我知道如何利用 BFC 解决这些问题, ...

  2. 【转】前端精选文摘:BFC 神奇背后的原理

    BFC 已经是一个耳听熟闻的词语了,网上有许多关于 BFC 的文章,介绍了如何触发 BFC 以及 BFC 的一些用处(如清浮动,防止 margin 重叠等).虽然我知道如何利用 BFC 解决这些问题, ...

  3. 【理论面试篇】收集整理来自网络上的一些常见的 经典前端、H5面试题 Web前端开发面试题

    ##2017.10.30收集 面试技巧 5.1 面试形式 1)        一般而言,小公司做笔试题:大公司面谈项目经验:做地图的一定考算法 2)        面试官喜欢什么样的人 ü  技术好. ...

  4. 【编码题篇】收集整理来自网络上的一些常见的 经典前端、H5面试题 Web前端开发面试题

    编写一个方法 求一个字符串的字节长度假设:一个英文字符占用一个字节,一个中文字符占用两个字节 function GetBytes(str){ var len = str.length; var byt ...

  5. 跟着9张思维导图学习Javascript js 关键字和保留字 css3中的BFC,IFC,GFC和FFC

    跟着9张思维导图学习Javascript   学习的道路就是要不断的总结归纳,好记性不如烂笔头,so,下面将 po 出我收集的 9 张 javascript 相关的思维导图(非原创). 思维导图小ti ...

  6. 十分钟复习CSS盒模型与BFC

    css盒模型与BFC 本文为收集整理总结网上资源 旨在系统复习css盒模型与bfc 节省复习时间 阅读10分钟 什么是盒模型 每一个文档中,每个元素都被表示为一个矩形的盒子,它都会具有内容区.padd ...

  7. 深入理解BFC

    定义 在解释BFC之前,先说一下文档流.我们常说的文档流其实分为定位流.浮动流和普通流三种.而普通流其实就是指BFC中的FC.FC是formatting context的首字母缩写,直译过来是格式化上 ...

  8. “fixed+relative==absolute”——对BFC的再次思考

    好久没写博客了,刚好今天跨年夜没约到什么妹子,在家宅着不如写点东西好了. 需求 昨天晚上,给公司年会做一个移动端的投票页面,遇到一个UI优化的问题: · 正文内容少于一屏时,投票提交按钮固定显示在页面 ...

  9. 关于CSS inline-block、BFC以及外边距合并的几个小问题

    CSS inline-block和BCF对于初学者来说,总是弄不太明白,下面记录下我在学习这块知识的过程中遇到的几个问题,供大家参考,有不足的地方,欢迎大家批评指正. 一.在什么场景下会出现外边距合并 ...

随机推荐

  1. Thinkphp5 使用命令行模式(cli模式)

    Tp5的cli模式跟Tp3.2变化较大,有自己的一套方式,在这里做个搬运工,把Tp文档的东西搬运过来,方便大家. 原出处截图 创建自定义命令行 第一步,配置command.php文件,目录在appli ...

  2. get方式请求乱码

    -----------------jsp--------------- var search = $("#searchName").val();search = encodeURI ...

  3. websocket数据流解析

    ceilometer获取数据暂时先不做解答,本篇注重websocket解决浏览器与openstack组件之间的实时状态更新. 大致流程如下: nginx配置的反向代理如下: /etc/nginx/ng ...

  4. WPF数据模板样式选择器

    在使用数据模板样式选择器时,不能设置ItemContainerStyle的属性值,如果设置了该值,那么数据模板样式选择器会失去作用. 在使用数据模板样式选择器时,首先要创建数据模板样式选择器对象,此对 ...

  5. YII配置rabbitMQ时前期工作各种坑

    背景如下: 项目需要做一个订阅/发布的功能,然后一大堆讨论不做说明,确认使用rabbitMQ来做: okay,既然 要这个来做,我们下载这个东西吧!在官网上下载就okay了,不做说明,下载安装的时候会 ...

  6. CGI FastCGI PHP-CGI PHP-FRM

    CGI(Common GateWay Interface )通用网关接口,CGI可以让一个客户端,从网页浏览器向执行在Web服务器上的程序请求数据.CGI描述了客户端和这个程序之间传输数据的一种协议标 ...

  7. hihocoder 1279(状压)

    坑爹的题目.不过不能说不是一道挺好的题目. 坑主要坑在,妹的我一样的复杂度,写的姿势略差了点然后就一直超时. 比赛的时候我还直接就看错题目,把AND运算看成了OR...还敲完交了一发. 这题很容易想到 ...

  8. EasyNVR摄像机无插件直播流媒体服务器前端构建之输入框样式的调整

    EasyNVR授权方式分为软件的授权和硬件授权两种方式,软件授权需要在软件输入永久邀请码可以激化永久授权 起初我们的界面设计是为了满足功能的需求就是 ,用户可以输入激活码提交,完成永久授权. 在实际的 ...

  9. springboot之修改内置tomcat配置项

    1.spring boot默认端口号是8080,如果要修改端口的话,只需要修改application.properties文件,在其中加入 例如: server.port=8081 2.在正常的项目中 ...

  10. Introduction to Mathematical Thinking - Week 9

    错题 评分出错 题目要求的是 "any" ,而答案只给出了一个.所以认为回答者没有理解题意,连 any 都没有理解.所以 0 分. 第一,标准的归纳法只能对自然数使用,而题目要求的 ...