IFC(Inline Formatting Context)内联格式化上下文

IFC(Inline Formatting Context)内联格式化上下文

与IFC之对应的是BFC : block formating context(块级格式化上下文),BFC在网页布局中的应用场景更是极其丰富,了解它会了解很多bug出现的原因,以及自行找到解决办法。为了更好地理解IFC,建议首先了解下列三个知识点

IFC跟BFC一样,它不是一个元素,不是一种属性,而是一种环境,一种上下文,一种布局特性。

符合以下条件即会生成一个IFC

块级元素中仅包含内联级别元素

形成条件非常简单,需要注意的是当IFC中有块级元素插入时,会产生两个匿名块将父元素分割开来,产生两个IFC,这里不做过多介绍。

IFC布局规则

引用w3c的IFC布局规则如下:

高度抽象版(不易读懂)

  • 子元素水平方向横向排列,并且垂直方向起点为元素顶部。
  • 子元素只会计算横向样式空间,【padding、border、margin】,垂直方向样式空间不会被计算,【padding、border、margin】。
  • 在垂直方向上,子元素会以不同形式来对齐(vertical-align)
  • 能把在一行上的框都完全包含进去的一个矩形区域,被称为该行的行框(line box)。行框的宽度是由包含块(containing box)和与其中的浮动来决定。
  • IFC中的"line box"一般左右边贴紧其包含块,但float元素会优先排列。
  • IFC中的"line box"高度由 CSS 行高计算规则来确定,同个IFC下的多个line box高度可能会不同。
  • 当 inline-level boxes的总宽度少于包含它们的line box时,其水平渲染规则由 text-align 属性值来决定。
  • 当一个"inline box"超过父元素的宽度时,它会被分割成多个boxes,这些 boxes 分布在多个"line box"中(一部分留在原来的"line box",一部分换行排列在下一个"line box"里)。如果子元素未设置强制换行的情况下,"inline box"将不可被分割,将会溢出父元素。

白话版(易读懂)

在IFC中,内联元素在水平方向上一个接一个的排布,其中,容器之间水平方向上的margin,padding,border方向上是有效的。他们垂直方向上的对齐由vertical-align来决定,比如底部(bottom)或顶端(top)对齐,或者基线(baseline)对齐。他们对齐完了之后形成的这个四方块儿区域,叫做一个line box(行框)。

一个line box的宽度由包含它的元素的宽度和包含它的元素里面有没有float元素来决定,而高度由内部元素中实际高度最高的元素而计算出来。

//其实这句话解释了为什么内联元素是不能设置垂直方向的padding,margin等,因为即使设置了,也不会影响line box的高度,可能会在每个浏览器的表现各异,但大多数不会达到预期的效果。

line box的高度是足够高来包含他内部的容器们的,也可能比它包含的容器们都高(比如在基线对齐的时候),如图:
img
当他包含的内部容器的高度小于line box的高度的时候,内部容器的垂直位置由自己的vertical这个属性来确定。当内部的容器盒子太多了一个line box装不下来,他们折行之后会变成两个或者多个line box, line box们相互之间垂直方向不能分离,不能重叠。

一般来说,line box的左边缘挨着包含它的元素的左边缘,并且右边缘挨着包含它的元素的右边缘,浮动元素会在包含他们的元素的 边缘和line box的边缘之间,所以,虽然在同一个IFC下的line box们通常拥有相同的宽度(就是包含他们的容器的宽度),但是也会因为浮动元素的捣乱,导致line box们的可用宽度产生了变化不一样了。在同一个Ifc下的line box们的高度也会不一样(比如说,一个line box里有个比较大的image,他就高了)。

补充图方便理解

img

如果一个line box 里的内联元素们的宽度总和小于这个line box的宽度,那么他们在这个line box里的水平方向的排布方式由 text-align这个属性来决定,如果这个属性被设置成了“justify”,可以使这些盒子在剩余空间内拉伸(除了inline-table 和 inline-block的元素)。//实现类似两端对齐的效果,但不是所有浏览器都支持。

当内联元素的宽度超过了line box的宽度,那么它会折行分裂成了几个line box,如果这个元素里面的内容不可以折行,例如只有一个字,或者white-space设置了nowrap/pre。那么内联元素会溢出line box。

当一个内联元素分裂时,分裂处的 margins, borders 和 padding不会有任何视觉效果(或者其他任何分裂,只要是有多个line box)。

line box 的生存条件是在IFC中并且包含inline-level元素,如果line box里没有文本,空白,换行符,内联元素,也没有其他的存在IFC环境中的元素,(如inline-block,inline- table,images等),将会被视为零高度,也将会被视为没有意义。

补充:在IFC的环境中,是不能存在block-level元素的,如果将block-level元素插入到IFC中,那么此IFC将会被破坏掉, 而block-level元素前的元素和block-level元素后的元素将会各自自动产生一个匿名容器其包围,这个匿名的容器内部环境将是一个新的 IFC。


例1:

img

P是一个块元素,它包含了5个内联元素,其中,有三个是匿名的。

  • 匿名: “Several”
  • EM: “emphasized words”
  • 匿名: “appear”
  • STRONG: “in this”
  • 匿名: “sentence, dear.”

这段代码里,在line box里,有5个inline的元素,P建立了包含line box的容器箱。

如果这个P的宽度足够,将会产生唯一的一个line box。如下图:

img

如果P的宽度不够,将会被分割成多个line box。如下图:

img

例2:
img

img

  1. margin,在emphasized前和word之后水平方向上起了作用。分割处无作用,垂直方向无作用。
  2. padding,在emphasized前和word之后水平方向上起了作用。分割处无作用,垂直方向无作用。
  3. border,看那个虚线的表现形式。

经过了上面的阐述,我们回到博客开使的问题上。实现未知尺寸的文本/元素/图片 在某个元素内垂直居中。

上面曾经说过:

在一个line box中,当他包含的内部容器的高度小于line box的高度的时候,内部容器的垂直位置由自己的vertical这个属性来确定。
那么,我们设想一下,如果手动创建一个IFC的环境,让line box的高度是包含块的高度的100%,让line box内部的元素使用vertical-align:middle,就可以实现垂直居中。

一个line box的高度由内部元素中实际高度最高的元素而计算出来。
所以,我们在line box中插入一个高度100%的inline-block元素。则会把整个line box撑高直到包含块的100%。

概念图:
img

其中,高级浏览器可以直接在外面的包含层使用:after来在内部追加创建一个伪元素,而低级浏览器不支持:after的写法,则在html模板中 创建一个空的元素, 设置其高度为100%则与包含层相同,宽度为零,内容为空,则可以实现将自己内部撑大为一个line box,但不占据任何空间。那么自己内部的其他元素可以通过转化为inline 或者 inline-block 来实现在line box中的垂直居中。表现形式就是在外面的包含层中垂直居中。

代码如下:

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>IFC应用实例</title>
    <meta name="copyright" content="www.ohweb.cn" />
    <meta name="author" content="weinan" />
</head>
<body>
    <style>
    /* comm 核心部分 */
    .g-ifc-wrap:after,
    .g-ifc-wrap-after{content:'';height:100%;width:0;display:inline-block;*display:inline;*zoom:1;margin-left:-5px;font-size:0;vertical-align:middle;}
    .g-ifc-item{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;}
    /* test */
    #test{height:300px;width:500px;background-color:#878787;border:3px solid #526f39;}
    #test p{background-color:#7ff30a;color:#000;font-weight:bold;}
    </style>
    <div id="test" class="g-ifc-wrap">
        <p class="g-ifc-item">我想要基于外面的容器居中</p>
        <img class="g-ifc-item" alt="我也是" src="http://dh2.kimg.cn/v/upload/20140325/9aa6e7f4e477d9af9c463c5604070ed4.jpg?v=1395739057" />
        <!--[if lte IE 7]><span class="g-ifc-wrap-after"></span>< ![endif]-->
    </div>
</body>
</html>

表现形式如下:

chrome等高级浏览器:

img


小结 :

当我们详细的了解IFC的原理之后,可以更有自信的应用它来做很多事情。

例如有些网站会摒弃float这种bug多多的布局方式,而全部使用IFC的环境来进行布局(当然了,很精确的时候也需要解决inline-level元素之间的间隙)。

或者实现一些如图片文字的居中对齐,自适应高度等很多灵活的效果。

同时,当我们的网页产生一些bug的时候,我们也可以明白为何如此并且思考好的解决方法而不是去网上找“万金油”。这将使我们对自己的网页有了更深的掌控性。


本文转载自 https://www.cnblogs.com/weinan/p/3665766.html

作者:荒漠千蝶

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值