阅读 696

css_08 | CSS——CSS 基本视觉格式化:② “行内盒子”格式化

本文推荐 PC 端阅读~

本文版权归 “公众号 | 前端一万小时” 所有,未经授权,请勿转载!
复制代码

获取编号.png

css_08
复制代码

涉及面试题.png

1. line-height: 2; 和 line-height: 200%; 有什么区别?
2. 在什么场景下会出现外边距合并?如何合并?如何不让相邻元素外边距合并?给个父子外边距合并的范例。
3. 行内元素的“边框”、“边界”等“框属性”是由 font-size 还是 line-height 控制?
4. height=line-height 可以用来垂直居中单行文本?代码怎么实现?
5. inline-block 有什么特性?
6. inline-block 在实际工作中有什么作用?
7. 怎么去除两个按钮中间的缝隙问题?
8. 一个页面有一排高度不一样的产品图,这时如果我们用 inline-block ,怎样使他们“顶端对齐”?
复制代码

前言: 作为学习“基本视觉格式化”的第二篇,我们在对上一篇中“块盒子”整个“格式化”过程中可以得到:
所谓的“格式化”,其实就是确定这个“块/行内 盒子”的自身长度、高度,以及与其上下左右相邻“盒子”之间的距离和协调的过程。在确定这个“长度、高度、距离和协调”的过程中会有很多“规则”,那我们学的就是这个“规则”。
接下来的“行内盒子”格式化相对于“块盒子”格式化的知识点会更细、更分散。不过作为最基本的理论知识,这篇依然很重要。



1 “行内盒子”怎么来的

当元素的 display 属性为 inline、inline-block 或 inline-table 时,该元素将成为“行内级元素”。

选择器 {
    display: inline、inline-block 或 inline-table;
}
复制代码

这些元素不会在之前或之后生成“行分隔符”,所以处于正常流中的行内元素会 “水平” 摆放,它们是块级元素的后代。
显示时,它不会生成内容块,但是可以与其他行内级内容一起显示为多行。
同理,“行内级元素”会生成“行内级盒子”,该盒子同时会参与“行内格式化上下文(inline formatting context)”的创建。

🏆小总结:
“行内元素”在一个文本内生成“行内盒子”,而不会打断这行文本(即这种元素可以出现在另一个元素的内容中,而不会破坏其显示,常见的如:aspanstrongem 等)。


2 “行内盒子”格式化

在正式学习前,有一个观念我们需要建立:
从某种程度上来讲,块级元素中包含的各“文本行”本身都是“行内元素”(即使它没有用行内元素的标记包围起来)。

既然“文本行”可以看作是“行内元素”,那我们就可以把抽象化的“行内元素”、“行内盒子”具象成:给“文本”格式化。然后举一反三,彻底弄懂与之相关的所有知识。
接下来,我们先学习一些前置基础知识,然后再细讲怎样“格式化”。

2.1 一些基本概念

2.1.1 匿名文本

<div>生活不像林黛玉<span>不会因为忧郁</span>而风情万种</div>
复制代码

未包含在行内元素的字符串(生活不像林黛玉 而风情万种)就叫“匿名文本”。

注意,空格也是匿名文本的一部分,因为空格与其他字符一样都是正常的字符。

2.1.2 非替换元素、替换元素

  • 非替换元素:
    如果元素的内容包含在文档中,则称之为“非替换元素”。
    例如:如果一个段落的文本内容都放在该元素的本身之内,这个段落就是一个“非替换元素”。
  • 替换元素:
    指用作为其他内容占位符的一个元素。
    例如:
    img 元素,它只是指向一个图像文件,这个图像文件将插入到文档流中该 img 元素本身所在的位置;
    大多数“表单”元素也可以“替换”(如 <input type="radio"> )。

2.1.3 “文本行”基础概念——内容区、行内框/行内盒子、间距、行框

08-01.png
08-02.png

  1. 内容区
  • 非替换元素中,内容区可以是元素中各字符的 em 框串在一起构成的框(font-size 的值确定了各个 em 框的高度),也可以是由元素中字符字形描述的框。换句话说,内容区的高度就是 font-size 的值。

  • 替换元素中,内容区就是元素的固有高度再加上可能有的 margin、边框或 padding 。

  1. 行间距
    行间距是 font-size 与 line-height 的差值,被分成两半在内容区的上下(上下半间距)。
    行间距只应用于非替换元素。

  2. 行内框(即行内各个元素对应生成的“行内盒子”)

  • 非替换元素,行内框高度 = line-height ;

  • 替换元素:

    ① “替换元素”不与文字结合(如 img 元素):行内框高度 = 替换元素的固有高度再加上可能有的 margin、边框或 padding ;
    ② “替换元素”文字结合(如 input 中 type=text 、 type=textarea 、 type=button 等与文字结合的表单元素):如果字体行高大于“替换元素的固有高度再加上可能有的 margin、边框或 padding”,则“行内框”的高度为“行高”。否则就是“替换元素的固有高度再加上可能有的 margin、边框或 padding”。总之就是“谁大是谁”!

  1. 行高
    两行文字“基线”的距离。

  2. 行框(即文本整行对应生成的“行内盒子”)
    一行有很多“行内盒子——inline box”,“行框”是包含该行中出现的“行内盒子”的最高点和最低点的最小盒子。
    换句话说,“行框”的上边界要位于最高“行内盒子”的上边界,而“行框”的底边要放在最低“行内盒子”的下边界。

  3. 基线
    不同元素的“基线”位置不同,整个“行框”会有一个“基线”,行内元素的位置是基于两者“基线”对齐。

2.2 行内盒子格式化

要弄清“行内盒子格式化”,让我们先充分理解关于“文本”的两个重要属性——line-height 和 vertical-align 。

2.2.1 line-height

08-03.png

⚠️line-height 只影响行内元素和其他行内内容,而不影响块级元素,至少不会直接影响块级元素。
⚠️line-height 有继承性

2.2.2 vertical-align

作为 line-height 的“断背”:vertical-align ,这个属性只能用于“行内元素”和“替换”元素,且不能继承

行内元素/替换元素 {
    vertical-align: 值;
}
复制代码

有以下“值”可以取:

  • baseline
    元素基线与父元素的基线对齐。
    ⚠️对于一些可替换元素,比如 type=textarea , HTML 标准没有说明它的基线,这意味着对其使用这个关键字时,各浏览器表现可能不一样。

  • sub
    元素基线与父元素的下标基线对齐。

  • super
    元素基线与父元素的上标基线对齐。

  • text-top
    元素顶端与父元素字体的顶端对齐。

  • text-bottom
    元素底端与父元素字体的底端对齐。

  • middle
    元素中垂线与父元素的基线加上小写 x 一半的高度值对齐。

  • <length>
    元素基线超过父元素的基线指定高度(可以取负值)。

  • <percentage>
    <length> ,百分比相对于 line-height ——🤣这是证明他们俩是“断背”强有力的证据。

💡以下两个值是相对于整行文本来说的:

  • top
    元素及其后代的顶端与整行的顶端对齐。

  • bottom
    元素及其后代的底端与整行的底端对齐。
    如果元素没有基线 baseline,则以它的外边距的下边缘为基线。

2.3 总结:“行内盒子”格式化步骤概述
08-04.png

  • 首先,以下步骤确定文本行中各元素对应的“行内盒子”的高度:
    第一,得到各行内“非替换元素”及不属于后代行内元素的所有文本的 font-size 值和 line-height 值,再将 line-height 减去 font-size,这就得到了框的“行间距”。这个“行间距”除以 2,将其一半分别应用到 “em 框”的顶部和底部;
    第二,得到各“替换元素”的 height、margin-top、margin-bottom,padding-top、 padding-bottom、border-top-width 和 border-bottom-width 值,把它们加在一起。

  • 其次,对于各内容区,确定它在整行“基线”的上方和下方分别超出多少:
    这个任务并不容易:你必须知道各元素及匿名文本各部分的“基线”的位置, 还要知道该行本身“基线”的位置,然后把它们对齐。另外,对于替换元素,要将其底边放在整行的“基线”上。

  • 继而,对于指定了 vertical-align 值的元素,确定其垂直偏移量:
    由此可知该元素的“行内盒子”要向上或向下移动多远,并改变元素在“基线”上方或下方超出的距离。

  • 最后,既然已经知道了所有“行内盒子”会放在哪里,再来计算最后的“行内盒子”——行框的高度:
    为此,只需将“基线”与最高“行内框”顶端之间的距离加上“基线”与最低“行内框”底端之间的距离。

2.4 实例讲解——弄懂 line-height

2.4.1 ❓问:line-height: 2;line-height: 200%; 有什么区别?

答:
line-height: 2; 和 line-height: 200%; 都表示行高是字体大小的 2 倍,但是它们是有区别的。
当它们写在父容器中时,子元素的字体大小不一样的时候,区别就体现出来了:

  • line-height: 2; 写在父容器中,那么子元素的行高都是自身高度的 2 倍,是相对大小。子元素的字体大小不同,行高也会不同
  • line-height: 200%; 写在父容器中,那么浏览器会立刻计算出行高的具体值,假如父容器的默认字体大小16px ,那么计算得到的行高就是 2×16px=32px ,子元素的行高都会继承这个 32px ,是固定大小。子元素的字体大小不同,行高都是固定某个值。

2.4.2 ❓问:行内元素的“边框”、“边界”等“框属性”是由 font-size 还是 line-height 控制?

答:
对于行内元素来说,上下的 margin padding 不生效,只有左右的 margin padding 生效!
上下 padding 只是撑开了边框,对高度是没有影响的。你对他加一些边框和背景色,他也可以看得到变化,但实质上对高度没有影响。
所以,行内元素的“边框”、“边界”是由 font-size 而不是 line-height 控制。

2.4.3 ❓问:height=line-height 可以用来垂直居中单行文本?

答:是的。
HTML

<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8">
  <title>JS Bin</title>
 </head>
 <body>
  <p>Hello Oli的前端一万小时</p>
 </body>
</html>
复制代码

CSS

p {
  width: 300px; 
  border: 1px solid blue;
  height: 50px;
  line-height: 50px;
}
复制代码

08-06.png

2.5 实例讲解——弄懂 inline-block

2.5.1 ❓问:inline-block 有什么特性?

答:

  • 既呈现 inline 的特性(不占据一整行,宽度由内容宽度决定);
  • 又呈现 block 特性(可设置宽高,内外边距)。

2.5.2 ❓问:inline-block 在实际工作中有什么作用?

答:
如果看到页面上有一排并列的按钮,如果不用浮动,就可以用 inline-block 。
HTML

<div class="wrap">
  <span class="box">hello,Oli的前端一万小时</span>
  <span class="box">hello,Oli的前端一万小时</span>
 </div>
复制代码


CSS

body {
  text-align: center;
}
.box {
  border: 1px solid;
  width: 100px;
  display: inline-block;
}
复制代码

08-07.png

2.5.3 ❓问:怎么去除上边问题中两个按钮中间的缝隙问题?

答:
之所以有空隙,是因为 html 文档里边两个 span 之间有很多空白字符,被浏览器当做一个,故会有空隙。
解决方式有 2 种:

  • 第一种是在 html 里边把这个空格去掉;
<div class="wrap">
  <span class="box">hello,Oli的前端一万小时</span><span class="box">hello,Oli的前端一万小时</span>
</div>
复制代码
  • 第二种是把包含两个 span 的 div 字体先设置为 0 (这里的空白字符就没有宽度高度,不占位),然后再在 box 里边去设置回去。
body {
   text-align:center;
}
.wrap {
   font-size: 0;
}
.box {
   border:1px solid;
   width: 100px;
   display: inline-block;
   font-size: 14px;
}
复制代码

2.5.4 ❓问:一个页面有一排高度不一样的产品图,这时如果我们用 inline-block ,怎样使他们“顶端对齐”?

答:
HTML

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body>
  <div class="wrap">
   <span class="box b1">hello,Oli的前端一万小时</span>
   <span class="box b2">hello,Oli的前端一万小时</span>
  </div>
</body>
</html>
复制代码

CSS

body {
   text-align:center;
}
.wrap {
   font-size: 0;
}
.box {
   border:1px solid;
   width: 100px;
   display: inline-block;
   font-size: 14px;
}
.b1 {
   padding: 40px;
}
.b2 {
   padding: 10px;
}
复制代码

以上代码会出现以下问题(它会以字的“基线”对齐,而不会以整个框的顶端对齐):

08-08.png

如果想对齐(用 vertical-align 属性):
CSS

body {
  text-align:center;
}
.wrap {
  font-size: 0;
}
.box {
  border: 1px solid;
  width: 100px;
  display: inline-block;
  font-size: 14px;
  vertical-align: top;
}
.b1 {
  padding: 40px;
}
.b2 {
  padding: 10px;
}
复制代码


后记: 后续的文章将还会涉及“行内盒子”在实例中的运用,届时我们还再用代码来阐述本篇的基础理论,眼下不作过多赘述。

我们都要记住一点:理论不懂就实践,实践不会就学理论!

祝好,qdywxs ♥ you!

关注下面的标签,发现更多相似文章
评论