CSS中的行盒(line-boxes)和行内盒子(line-box)

2 篇文章 1 订阅

盒模型

  说到盒模型我们都知道,盒模型有两种,一个content-box和一个border-box 。
关于盒模型
盒模型
包含块详情

典型盒子的各个区域和边缘

典型盒子的各个区域和边缘

盒模型内部也就是content-box部分有三种情况:

  1. content-box内部是也是盒子,像俄罗斯套娃一样;
  2. content-box内部包含着一行一行的line-boxes(行盒);
  3. content-box 内部两种盒子都存在,但是内部最终还是line-boxes;

每个 HTML 元素实际上是一堆line-boxes。

在这里插入图片描述

line-boxes(行盒/行框)

  在行内格式化上下文中,line-box(行内盒子)从包含块的顶部开始一个接一个地水平排列。这些行内盒子之间遵循水平边距、边框和填充。这些行内盒子可以以不同的方式垂直对齐:它们的底部或顶部可以对齐,或者它们内部文本的基线可以对齐。形成一个矩形区域称为行框(line-boxes)。在这里插入图片描述

line-box (行内盒子)

一个line-box内部有三种,

  1. 直接是文本内容的,这种被称为匿名内联元素;
  2. 非替换元素(例如 span),
  3. 替换元素(例如img)

匿名内联元素

任何直接包含在块容器元素内(而不是内联元素内)的文本都必须被视为匿名内联元素。

<p>Some <em>emphasized</em> text</p>

上面的代码中 some 和text 由就属于匿名内联元素。
在这里插入图片描述

  蓝色部分便是一个line-box,也可说三个line-box并列在一块,每个字符一个,三个line-box的都是一样的,所以合在一起说也是一样的。

  行距、上高、下深这些名词则是继承而来的,有的甚至是铅字印刷时代的名词。想要详细了解的可以看下。你未必知道的CSS故事:揭开leading的面纱

  这些值以及比例是在设计字体时确定的,下面以“Arial”中的“ArialMT”字体为例,说说这些比例。使用fontforge软件打开“Arial”的字体文件我们可以获取一些信息。
在这里插入图片描述
在这里插入图片描述
根据上面的信息我们可以画出下图
在这里插入图片描述

数据以“Arial”为例,非实际比例。

  1. 2048标准高度(em-square)。不同字体的标准高度不同,比如256、1000、1024、2048等等都可以;
  2. 上高为1638,下深为410,这一对可以称为默认的上高和下深,有了上高和下深自然就确定了baseline的位置;
  3. win上高(1854)和win下深(434) 这一对则是windows系统下的上高和下深;HHead上高和HHead下深则是MacOS的,(我没有mac所以也没有测试)有的字体这两对上高和下深可能是不一致的;会出现同样的字体在不同的系统上,显示的位置不同。
  4. leading(行距/线距),leading的值是一分为二的放在内容区域(content-area)上下两个地方。
  5. 有了windows系统下的上高和下深以及行距自然就知道了window下的总高度了2355
  6. capital Height 大写字母的高度,所有大写字母高度都是一样的1467;
  7. x-height 小写字母x的高度 1062;
  8. 字形上高1491和字形下深431则指的是,这套字体中所有的字形达到的最高点和最低点,可以看到有的字形是会突破标准的下深的,不同字体设计不同,有的可能会突破上高,但是一般不会突破系统的上高和下深;因为突破了系统的上高和下深,显示的时候可能会出现重叠的情况;

上述的这些数据均是字体设计的时候就确定的,有了这些比例数据,接下来我们了一计算一些计算真实的line-box高度了。

已知

.main{
    font-family: Arial;
	font-size:100px;
}
  1. font-size对应的就是标准高度2048,同时它也是1em的值,也是标准行高;
  2. windows下的上高、下深和行距加起来(2355)对应的就是window下的line-height;
    那么:
  3. window下的行高就是 100 / 2048 * 2355 = 114.990234375 ≈ 115,此时115就是window下的line-height的值,也就是默认的那个normal; 并不是网上传的font-size的1.2或者1.3 什么的,而是字体设计时定下的比例;只不过大多数字体的比例都在1.2 到1.3 这个范围附近,推荐的比例也在这范围附近;当然我们可以重新设置这个比例,比如 设置line-height:2; 那么line-height就等于200px = 100 * 2;
  4. 大写字母的高度为 100 / 2048 * 1467= 71.630859375 ≈ 72;
  5. x的高度就是 100 / 2048 * 1106 = 51.85546875 ≈ 52,这也是1ex的值,(ex可以用来做居中对齐,真居中对齐!!!(* ̄︶ ̄));
  6. 线距 100 / 2048 * 67 = 3.271484375 ≈ 3, 一半100 / 2048 * 33.5 = 1.6357421875 ≈ 2;

我们知道大多数屏幕上的每个像素都是一个小灯泡,要么亮者要么不亮,所以像素最终会是个整数,具体如何计算的由浏览器决定,不同浏览器可能不同。
以font-size为100px的“Arial”为例,总leading为3,在chrome 中可以看到,1px被分到了上半部分,2px分配到了下半部分;有兴趣的话可以试验下。
在这里插入图片描述

非替换元素

非替换元素以span为例,span 标签是通用行内容器,并没有任何特殊语义;

  非替换元素的外边距,边框和内边距不会算入行框的计算,但是它们仍然渲染在行内盒周围。这意味着如果用’line-height’指定的高度小于包含的盒(contained boxes)的内容高度,背景与内边距和外边距的颜色可能会“渗入”进相邻的行框。

例如:
流入相邻行框
它的各条线的位置和匿名内联框相同,计算方式也是相同的,span就是个命名的行内盒子。

替换元素

  替换元素的内容实际由该内联元素的属性提供,比如img标签的src属性,img标签会使用src属性指定的图片,替换该元素的位置。
在这里插入图片描述
关于替换元素各条线的位置,以img为例:
在这里插入图片描述
vertical-aligin:baseline | top | text-top | middle | text-bottom | bottom …

  • baseline:子元素盒子的baseline与父盒子的baseline对齐。
  • text-top 子元素盒子的顶部和行盒子里内容区域的顶部(text-top)对齐。
  • center子元素盒子垂直中点(替换元素 )与行盒子的baseline+字母 x 高度的一半对齐
  • top 将子元素盒子的顶部和其所在的line box顶部对齐
  • bottom和top类似,只不过是底端对齐

  行内盒子的vertical-align等于text-top或者text-bottom的时候依赖的是其父元素也就是行盒(line-boxes)的text-top和text-bottom位置,行盒的text-top和text-bottom线的位置则是由其父元素的font-size、font-family等属性决定的。而对于所有的行内盒子(line-box) 来说,在定位的时候其实都不需要知道他们的text-top和text-bottom这两个线的位置,因为行内盒子就是最小的元素,它没有子元素了,也就没有元素需要这两条线来确定位置了,或者说行内盒子没有这两条线都可以。

行内盒子最应该关心的线应该是 top、bottom、baseline和middle这四条线

img和textare元素的baseline是这个盒子的下外边bottom margin 的边线,
input和select 标签的baseline是其内部的文字的baseline,其余线的位置和img相同。

PS:
当其它元素的display被设置为inline-* 的时候,top和text-top,bottom和text-bottom的位置也会如此。元素的top和bottom这两条线并不是固定的,始终在元素的最高和最低点,line-height 和height都会影响其位置。

inline-block 元素的各条线的位置

在这里插入图片描述
Inline-block 元素的外边缘(top和bottom)是其margin-box的顶部和底部边缘。

Inline-block 元素的基线取决于该元素是否具有流入内容:

  1. 在流入内容的情况下,行内块元素的基线是正常流中最后一个行框的基线。对于最后一个元素,它的基线是根据它自己的规则找到的。
  2. 如果有流入内容但overflow属性为visible以外的其他值,则基线是外边距框的底部边缘。
  3. 在没有流入内容的情况下(即替换元素例如img、canvas等等),基线边就是替换内容的底部边缘。

baseline 的位置
  在有子元素并且有内容的情况下,父元素(行盒)基线所在的位置是取在子元素还在默认位置时(可以理解为父元素中只有一个子元素时)他们的基线与父元素顶部距离最大的那个元素的基线位置(一般是最高的那个),其他同行元素相对于父元素的基线对齐。

line-height

  关于line-height 有两种说法,一种是line-height指的是两行文字的baseline之间的距离,另一种说法是一行文字的顶部到底部的距离,两者说法不同但是包含的高度是相同的都等于 行距(leading)+ 上高(ascent)+下深(descent),就CSS而言,或者说就本文而言采用第一种方法更容易理解和计算,就先采用第一种了。但是line-height 并不能理解为两条线之间的距离,个人感觉更应该理解为 line-height = 行距(leading)+ 上高(ascent)+下深(descent),不同的字体和字体大小都会计算出来不同的line-height。

  如果以baseline为标准给line-height下个更准确的定义的话就是,在font-size font-family相同的情况下相邻两个行盒(line-boxes)内的两个vertical-align相同的行内盒子(line-box)的baseline 距离;

  两个相邻的行盒子font-size或者font-family不同导致各自自的line-height不同的时候,它们的各自内部的两个vertical-align相同的行内盒子(line-box)的baseline之间的距离是,各自的line-height除以2然后加起来,如果从这个角度看那么line-height应该是行内盒子(line-box)的top到bottom之间的距离更合理些。

  我想这也是当给inline元素设置margin top/bottom以及padding top/bottom 要么无效要么不影响其垂直布局位置的原因。因为最开始css就是这么设计的,毕竟最开始只有inline和block这两种盒子,line-height就是baseline之间的距离,只是后来出现了inline-block 之类的奇怪的盒子导致前面的理论无法解释后面的盒子的行为。

不管怎么说line-height = 行距(leading)+ 上高(ascent)+下深(descent)这个应该是确定的。

line-boxes(行盒)

  了解完line-box(行内盒子),有了line-box(行内盒子)的高度,再说回line-boxes(行盒),计算line-boxes的高度。line-box都确定的情况下,line-boxes的高度主要受到各个line-box的vertical-aligin 属性影响。

举个栗子:

以仿宋字体为例:

 <div class="main">
      <span>Ax</span>
      <span class="baseline">A</span>
      <span class="top">B</span>
      <span class="text-top">C</span>
      <span class="middle">D</span>
      <span class="text-bottom">E</span>
      <span class="bottom">F</span>
    </div>
.main {
  font-family: FangSong;
  font-size: 200px;
  background-color: rgb(255, 0, 255);
  span {
    border: 1px solid #ffff;
    margin-right: 3px;
    background-color: rgb(0, 255, 0);
  }
  .text-top {
    vertical-align: text-top;
  }
  .text-bottom {
    vertical-align: text-bottom;
  }
  .middle {
    vertical-align: middle;
  }
  .top {
    vertical-align: top;
  }
  .bottom {
    vertical-align: bottom;
  }
}

在这里插入图片描述
为什么显示成这样,我们分析一下它的组成,标出各个子元素以及父元素的各条线的位置就知道了
在这里插入图片描述

    父元素的 font-family 和font-size已知的情况下行框的text-top、x-height half、 baseline、text-bottom;这四条线的位置就确定了(或者说确定了它们几个的相对位置),同时也确定了top线的最低位置和bottom线的最高位置。
  而top和bottom线的具体位置则由其子元素的位置确定之后再确定,所有子元素(除了vertical-align为top和bottom的子元素)中所处位置最高的子元素和所处位置最低的子元素分别确定top和bottom,如果所处最高元素的top比依据父元素计算出来的top线的位置低,则以父元素计算的位置为准,bottom同理;top和bottom这两条确定之后,也就可以确定vertical-align为top和bottom的子元素应该放在哪里了。

    top和bottom被称作是相对于行的值,所以要在其行框确定之后才能确定它们的位置,而text-top text-bottom baseline 等等被称为相对于父元素的值,只要父元素确定了,它们便确定了。(个人推测,详见vertical-align)它俩有点特殊,具体如下

  1. 子元素属性为 vertical-align:top 如果该子元素的总高度超过了其它元素计算出来的line-boxes 高度,此时其它线位置均不变,bottom线的位置下移;在这里插入图片描述

  2. 子元素属性为 vertical-align:bottom ,如果该子元素的高度超过了其他子元素计算出来的line-boxes的高度,此时top线位置不变,其它线均下移;在这里插入图片描述

  3. 两者都超过的时候,其它线的位置以高的那个为准,相等时以vertical-align:top的为准;

  换个角度来说,line-boxes的top和bottom线始终是line-boxes的顶和底;而vertical-align:top/bottom就是始终保持子元素的top/bottom 和line-boxes的对应线重合;

各个子元素的位置确定之后,line-boxes的top和bottom就可以确定了,然后这个line-boxes高度也就确定了。

  1. vertical-align 还有几个值 比如sub、super,sub使元素的基线与父元素的下标基线对齐。super使元素的基线与父元素的上标基线对齐。至于上标基线和下标基线在哪里css并没有规定,由浏览器各自的实现确定的;
  2. vertical-align 可以使用具体值将baseline相对于原有位置上下移动,从这个角度看上面的那些属性值也可以理解为,一个特殊的数字的别名;
  3. vertical-align 指定为百分比,使元素的基线对齐到父元素的基线之上的给定百分比,该百分比是line-height属性的百分比。可以是负数。

结语

   行盒(line-boxes)就像一个集装箱,把形态各异的行内盒子(line-box)包装起来,形成一个标准块(像一块砖头,怪不得叫搬砖的),一行一行的标准块叠起来,组成盒模型的content部分,从整体上来看所有的html标签最终都是由一个一个的line-box组成的。

参考:

  1. Deep dive CSS: font metrics, line-height and vertical-align
  2. 深入理解 CSS:字体度量、line-height 和 vertical-align
  3. line-height
  4. vertical-align
  5. 你未必知道的CSS故事:揭开leading的面纱
  6. css行高line-height的一些深入理解及应用
  7. 行高的计算与继承
  8. Vertical-Align: All You Need To Know (CSS)
  9. [翻译]关于Vertical-Align你需要知道的事情
  10. css vertical-align你真的很了解嘛
  11. https://drafts.csswg.org/css-display-3/#non-replaced
  12. http://www.ayqy.net/doc/css2-1/visudet.html
  • 8
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值