lovelmh13/myBlog

IFC

Opened this issue · 1 comments

visual formatting model 视觉格式化模型

CSS 视觉格式化模型(visual formatting model)是用来处理和在视觉媒体上显示文档时使用的计算规则。该模型是 CSS 的基础概念之一。

视觉格式化模型会根据CSS盒子模型将文档中的元素转换为一个个盒子,每个盒子的布局由以下因素决定:

  • 盒子的尺寸:精确指定、由约束条件指定或没有指定
  • 盒子的类型:行内盒子(inline)、行内级盒子(inline-level)、原子行内级盒子(atomic inline-level)、块盒子(block)
  • 定位方案(positioning scheme):普通流定位、浮动定位或绝对定位
  • 文档树中的其它元素:即当前盒子的子元素或兄弟元素
  • 视口尺寸与位置
  • 所包含的图片的尺寸
  • 其他的某些外部因素

在 IFC 中可能会涉及到的模型有:

  • 行内级元素:inline-level element,display 为 inline、inline-block、inline-table 的元素称为行内级元素。与块级元素一样,元素是否是行内级元素仅是元素本身的属性,并不直接用于格式化上下文的创建或布局。
  • 行内级盒子:inline-level box,由行内级元素生成。行内级盒子包括行内盒子和原子行内级盒子两种,区别在于该盒子是否参与行内格式化上下文的创建。
  • 行内盒子:inline box,参与行内格式化上下文创建的行内级盒子称为行内盒子。与块盒子类似,行内盒子也分为具名行内盒子和匿名行内盒子(anonymous inline box)两种。
  • 原子行内级盒子:atomic inline-level box,不参与行内格式化上下文创建的行内级盒子。原子行内级盒子一开始叫做原子行内盒子(atomic inline box),后被修正。原子行内级盒子的内容不会拆分成多行显示。

观察到,“原子行内级盒子的内容不会拆分成多行显示”,这说明 inline-block 和 inline-table 创建的正是原子行内级盒子。

原因如下:

<style>
.s1 {
  display: inline; /* default value*/
  border: 5px solid rebeccapurple;
}
.s2 {
  border: 5px solid goldenrod;
  display: inline-block;
}
</style>
 
<div style="width: 15em">
  The text in the span
  <span class="s1">can be split in several lines as it</span>
  is an inline box.
</div>
 
<!-- 在同一个行内格式化上下文中,原子行内级盒子( atomic inline-level box ) 不能拆分成多行 -->
<!-- 指定为 inline-block, “cannot be split into several lines as it” 都是在同一个行内,即使因为宽度导致换行,也可以看出,他们还是在同一个区域,并没有被“多行” -->
<div style="width: 15em">
  The text in the span
  <span class="s2">cannot be split in several lines as it</span>
  is an inline-block box.
</div>

image

争议:

css 2 9.2.2 中说:

Inline-level elements generate inline-level boxes, which are boxes that participate in an inline formatting context.

内行级元素 生成参数 IFC 的行内级盒子

这与上面 mdn 中说的 “行内级盒子包括行内盒子和原子行内级盒子两种,区别在于该盒子是否参与行内格式化上下文的创建” 不一致。

IFC - inline formatting context (行内格式化模型)

只要是在某个元素内(即使是块级元素),其内部的内容(文字或者元素)按照书写模式依次排列,就形成了 IFC, 换行会分割成的 IFC。
书写模式:水平方向是从左到右,竖直方向是从上到下排列。

  1. 在一个框里的同一行的区域叫: 行框(line box)。比如下面代码的 .h1 和 .h2 都形成了一个 line box
    行框的的大小足以包含这个行中的所有行内盒子(inline box)。行框的高度是当前所有 行内框 根据 vertical-align 值进行垂直方向对其后,由当前行所有 行内框 最高的顶边和最低底边的实际距决定的。
    如下代码:div 中的 ' One Two Three ' 就是在同一个 IFC 中。
<style>
.h1 {
  writing-mode: horizontal-tb;
}
 
.v1 {
  writing-mode: vertical-rl;
}
</style>
 
<div class="example h1">One Two Three</div>
<div class="example v1">One Two Three</div>

image

  1. 如果一行不够(有宽度设定),将会重新在当前方向上新开一行。
    一个 inline box 被分割成多行时, margin padding border 会在 line box 换行处失效。
    如下代码:
<style>
.s1 {
 border: 5px solid rebeccapurple;
}
</style>
<div class="example" style="width: 20em">
  Before that night—<span class="s1"
    >a memorable night, as it was to prove—hundreds of millions of
    people</span
  >
  had watched the rising smoke-wreaths of their fires without drawing any
  special inspiration from the fact.”
</div>

image

  1. 设定为 inline-block 则不会新开一行
<style>
.s2 {
  border: 5px solid goldenrod;
  display: inline-block;
}
</style>
 
<!-- inline-block -->
<div class="example" style="width: 20em">
  Before that night—<span class="s2">a memorable night, as it was to prove—hundreds of millions of people</span>
  had watched the rising smoke-wreaths of their fires without drawing any special inspiration from the fact.”
</div>

image

  1. 垂直方向的对齐 vertical-align
<style>
.s3 {
  font-size: 200%;
  vertical-align: top;
}
</style>
 
<!-- 垂直方向 -->
<div class="example horizontal">
  Before that night—<span class="s3">a memorable night</span>, as it was to
  prove—hundreds of millions of people had watched the rising smoke-wreaths
  of their fires without drawing any special inspiration from the fact.”
</div>

image

  1. 水平方向的对齐 text-align
<style>
.d4 {
  text-align: center;
}
</style>
 
<div class="example horizontal d4">One Two Three</div>

image

  1. 有浮动的时候

行框(line box) 一般尺寸都相同。但是,在同一个「块级格式化上下文」里,如果有一个浮动元素,浮动元素会让包裹他的 line box 变短。

由于 float 意味着使用块布局,所以它会把 inline inline-block inline-table 等计算为 block,详情见:float mdn

<style>
.d5 {
  background-color: rgb(224, 206, 247);
  border: 5px solid rebeccapurple;
}
.float {
  float: left;
  width: 200px;
  height: 150px;
  background-color: white;
  border: 1px solid black;
  padding: 10px;
}
</style>
 
<div class="d5">
  <div class="float">I am a floated box!</div>
  <p>I am content inside the container.</p>
</div>
</style>

image

white-space 设置如何处理元素中的 空白

image

vertical-align 垂直对齐

先送上一个方便调试的链接:vertical-align 属性测试实验面板

基线

line-height 指定元素行框(line boxes)的最小高度;

vertical-align 的默认值就是基线。

关于 line-height 代码如下,

<style>
.s1 {
  font-size: 40px;
  vertical-align: bottom;
  border: 1px solid red;
  line-height: 100px;
}
</style>
<div class="d1">
  x
  <span class="s1">span</span>
</div>

image

虽然我们是给 span 标签加了 100px 的 line-htight,但是发现 span 高度并不是 100px , 100px 高的是外层的 d1。这充分说明了 line-height 指定的是 line boxe 的最小高度。

从文章前面的描述,我们已经知道了 line-height 是指:在一个框里的同一行的区域。

一、基线位置不固定

image

  1. 在有文字的内联元素中默认基线是字母 x 的下边缘。(汉字的基线不太一样)

“alphabetic” baseline: “字母”基线 – 英文
“hanging” baseline: “悬挂”基线 – 印度文
“ideographic” baseline: “表意”基线 – 中文
image

  1. img 的基线就是图片的底边
  2. inline-block box ( 行内块元素 )
    a. 如果该元素中有内联元素,基线就是最后一行内联元素的基线。
    b. 如果 inline-block box 中没有内联元素或者 overflow 不为 visible,默认基线是 margin-bottom 的顶部。

二、vertical-align 基线对齐

vertical-align 是个相对的对齐的单位。

image
image

前面的 1 2 都不难理解,这里说一下第三点

第三点有两种情况,先看第一种。

  1. 如果该元素中有内联元素,基线就是最后一行内联元素的基线
    上代码:
<style>
  .d1 {
    height: 100px;
    line-height: 100px;
  }
  .s1 {
    display: inline-block;
    border: 1px solid red;
    vertical-align: text-top;
  }
  .s2 {
    font-size: 40px;
    color: darkcyan;
    vertical-align: text-top;
  }
  .img1 {
    display: inline-block;
    vertical-align: text-top;
  }
</style>
 
 
<div class="d1">
  x
  <span class="s1">spanx
    <span class="s2">spanx2是我</span>  
  </span>  
  <img class="img1" src="./1.jpg" alt="" />
</div>

image

这里 spanx2 我懵了,先不说了...

懵逼了看这个:vertical-align 在和谁对齐?

注意一下:

  • top 内联元素的顶边和行内最高元素的顶边对齐(注意,包括 margin,且内联元素有行高,并不是内联元素里的文字与基线对齐,而是元素本身)
<div style="background: #398dee;padding-top:20px">
    <span style="font-size: 30px">x</span>
    <img src="./man_active.png" style="margin-top: 30px">
    <span style="color: red; vertical-align: top;">top</span>
</div>

image

  1. 是和最高元素的顶边而不是和行的顶边对齐。因为设置了行的padding-top之后元素并没有顶在最上面;
  2. 最高元素的顶边包括margin,看图可以发现设置了maigin-top也是会算在内的。图片显示明显“top”的顶部和图片顶不对齐啊,不要忘了top这个元素是有行高的。而这里是说的元素的顶并不是字母的顶部。

是否学会了,测试一下,来看一看,inline-block元素设置margin-bottom为负值后为什么会下移?

image

作者:大漠
链接:https://www.zhihu.com/question/61032688/answer/201637589
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

在规范中display取值为inline-block,是这样描述的:

This value causes an element to generate an inline-level block container. The inside of an inline-block is formatted as a block box, and the element itself is formatted as an atomic inline-level box.
大致的意思,会让元素生成一个linline-level块容器,而一个inline-block内格式化之后类似于block box,但是元素自身却被格式化一个原子类linline-level box。

反正这样的描述蛮蛋疼的。不过这里说到的inline-block元素,那么他的对齐方式和vertical-align是非常有关系的,默认情况下:

image

是以baseline为基础对齐,这个时候就又引出来baseline的概念了。要了解这个概念和line-height之类的又有关系了。把正复杂,蛋疼。咱先不说。继续说对齐。如果把第二个元素内容去掉:

image

是不是觉得非常的神奇。回到规范中,CSS2的可视化格式模型文档中有一么一段话:

The baseline of an ‘inline-block’ is the baseline of its last line box in the normal flow, unless it has either no in-flow line boxes or if its ‘overflow’ property has a computed value other than ‘visible’, in which case the baseline is the bottom margin edge.
大至意思:

‘inline-block’的基线是正常流中最后一个line box的基线, 除非,这个line box里面既没有line boxes或者本身’overflow’属性的计算值而不是’visible’, 这种情况下基线是margin底边缘。

通俗的话描述就是:

一个inline-block元素,如果里面没有inline内联元素,或者overflow不是visible,则该元素的基线就是其margin底边缘,否则,其基线就是元素里面最后一行内联元素的基线。

把你的demo稍为修改一下,先把第二个margin-bottom干掉

image

继续变一下,并在第二个中加方字:

image

这个没有添加任何margin-bottom,第二个成这样了。

会发现,明明尺寸、display水平都是一样的,结果呢,两个却不在一个水平线上对齐,为什么呢?哈哈,上面的规范已经说明了一切。第一个框框里面没有内联元素,因此,基线就是容器的margin下边缘,也就是下边框下面的位置;而第二个框框里面有字符,纯正的内联元素,因此,第二个框框就是这些字符的基线,也就是字母x的下边缘了。于是,我们就看到了框框1下边缘和框框2里面字符x底边对齐的好戏。

其实看到这里,你应该知道一些原因了。把div的文字去掉,然后加上margin-bottom。其实也是改变了元素的baseline了(你就当作改变了)。

如果你在div中添加一个vertical-align改变他的对齐方式。就变了:

image

tips:

ex 单位
1ex 相当于一个 x 字母的高度,不受任何字体的影响。所以是天然对文字居中的。当使用 1ex 的元素的高度小于1ex 时,可以使用这种方法垂直对(不是垂直居中对齐)

未完...

https://www.w3.org/TR/CSS2/visuren.html
https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Visual_formatting_model
https://developer.mozilla.org/zh-CN/docs/Web/CSS/vertical-align
https://www.zhangxinxu.com/wordpress/2015/06/about-letter-x-of-css/
https://www.brunildo.org/test/inline-block.html
https://www.zhihu.com/question/61032688
https://www.jianshu.com/p/ce7e4a997a2c
https://developer.mozilla.org/zh-CN/docs/Web/CSS/Inline_formatting_context
https://developer.mozilla.org/zh-CN/docs/CSS/float
https://www.zhangxinxu.com/wordpress/2015/08/css-deep-understand-vertical-align-and-line-height
https://www.zhangxinxu.com/wordpress/2010/05/%e6%88%91%e5%af%b9css-vertical-align%e7%9a%84%e4%b8%80%e4%ba%9b%e7%90%86%e8%a7%a3%e4%b8%8e%e8%ae%a4%e8%af%86%ef%bc%88%e4%b8%80%ef%bc%89/
https://drafts.csswg.org/css2/#inline-boxes
https://drafts.csswg.org/css2/#inline-formatting
https://drafts.csswg.org/css2/#value-def-inline-block
https://www.w3.org/TR/CSS2/visuren.html#inline-formatting

偶然间搜到,牛的