垂直对齐有什么问题:基线?

时间:2017-05-16 08:30:57

标签: css vertical-alignment baseline

我以为我了解CSS,但我现在需要向某人解释一下,我发现我做不到。

我的问题基本上归结为:当同一行中有其他路线时,为什么会忽略vertical-align:baseline

示例:如果第二个跨度为vertical-align:bottom,则第一个跨度的垂直对齐将被忽略baseline;它的行为就像它有bottom一样。

span:first-child {vertical-align:baseline}
span:last-child {font-size:3em; vertical-align:bottom;}
<p>
  <span>one</span> <span>two</span>
</p>

如果所有跨度都具有baseline以外的垂直对齐,或者如果它们都是baseline,则它们的行为与预期一致。

span:first-child {vertical-align:top}
span:last-child {font-size:3em; vertical-align:bottom;}
<p>
  <span>one</span> <span>two</span>
</p>

span:first-child {vertical-align:baseline}
span:last-child {font-size:3em; vertical-align:baseline;}
<p>
  <span>one</span> <span>two</span>
</p>

如果这是正常行为,为什么不在任何地方描述?我没有找到任何说明基线和顶部/底部以这种方式相互干扰的来源。

3 个答案:

答案 0 :(得分:34)

垂直对齐

vertical-align用于对齐inline-level elements。这些是元素,其display属性的计算结果为:

  • inline
  • inline-block
  • inline-table(在此答案中未考虑)

内联级元素以行的形式排列在一起。一旦有多个元素不适合当前行,就会在其下面创建一个新行。所有这些行都有一个所谓的行框,它包含了其行的所有内容。不同大小的内容意味着不同高度的线框。

在下图中,线框的顶部和底部用红线表示。 enter image description here

在这些行框内,属性vertical-align负责对齐各个元素。

基线

垂直对齐的最重要参考点是所涉及元素的基线。在某些情况下,元素封闭盒的顶部和底部边缘也很重要。

内联元素

enter image description here

线条高度的顶部和底部边缘用红线表示,字体的高度用绿线表示,基线用蓝线表示。

在左侧,文本的行高设置为与font-size相同的高度。绿色和红色线在每侧折叠成一条线。

在中间,行高是font-size的两倍。

在右侧,行高是字体大小的一半。

请注意,如果线条高度小于字体高度,则内联元素的外边缘(红线)无关紧要。

内联块元素

enter image description here

从左到右,您会看到:

  • inline-block内容为inline-block

  • 的元素
  • overflow: hidden内容为in-flowinline-block

  • 的元素
  • inline-block元素,内容没有in-flow(但内容区域有高度)

边距的边界用红线表示,边框是黄色,填充绿色,内容区域是蓝色。每个inline-block元素的基线显示为蓝线。

inline-block元素的基线取决于元素是否具有in-flow内容。如果:

  • in-flow内容overflow元素的基线是正常流程中最后一个内容元素的基线(左侧示例

  • in-flow内容但vertical-align属性评估的内容不是可见的,基线是边距框的下边缘(中间示例

  • 没有in-flow内容,基线再次是边距框的下边缘(右侧示例

行框

in-flow

使用vertical-align时,这可能是最令人困惑的部分。这意味着,基线被放置在需要满足所有其他条件的地方,例如font-size最小化线框的高度。这是等式中的自由参数

由于线框的基线是不可见的,因此它可能不会立即显而易见。但是,你可以很容易地看到它。只需在问题的行尾添加一个字符,例如&#34; x&#34;在图中。如果此字符未以任何方式对齐,则默认情况下它将位于基线上。

在其基线附近,线框有我们称之为文本框的内容(图中的绿线)。文本框可以简单地被视为行框内的内联元素,没有任何对齐。它的高度等于其父元素的vertical-align。因此,文本框仅包含行框的无格式文本。由于此文本框与基线相关联,因此它会在基线移动时移动。

片段

如果您想在此处使用各种font-sizelet sl1 = document.getElementById('sl1'); let sl2 = document.getElementById('sl2'); let sl3 = document.getElementById('sl3'); let sl4 = document.getElementById('sl4'); let elm1 = document.getElementById('elm1'); let elm2 = document.getElementById('elm2'); let elm3 = document.getElementById('elm3'); let elm4 = document.getElementById('elm4'); let ip1 = document.getElementById('ip1'); let ip2 = document.getElementById('ip2'); let ip3 = document.getElementById('ip3'); let ip4 = document.getElementById('ip4'); let slArr = [sl1, sl2, sl3, sl4]; let elmArr = [elm1, elm2, elm3, elm4]; let ipArr = [ip1, ip2, ip3, ip4]; let valueArr = ['baseline', 'top', 'middle', 'bottom']; for (let i = 0; i < slArr.length; i++) { slArr[i].addEventListener('change', (event) => { elmArr[i].style.verticalAlign = event.target.value; elmArr[i].innerHTML = event.target.value; addDiv(); }) } for (let i = 0; i < ipArr.length; i++) { ipArr[i].addEventListener('change', (event) => { elmArr[i].style.fontSize = event.target.value + 'em'; addDiv(); }) } document.getElementById('btnRandom').addEventListener('click', () => { for (let i = 0; i < elmArr.length; i++) { let element = elmArr[i]; let fontSize = Math.floor(Math.random() * 4 + 1); ipArr[i].value = fontSize; element.style.fontSize = fontSize + 'em'; let styleIndex = Math.floor(Math.random() * 4); element.style.verticalAlign = valueArr[styleIndex]; element.innerHTML = valueArr[styleIndex]; slArr[i].selectedIndex = styleIndex; } }, this); function addDiv() { let view = document.getElementById('viewer'); view.innerHTML = ""; elmArr.forEach(function(element) { let div = document.createElement('div'); div.appendChild(element.cloneNode()); view.appendChild(div); }, this); }进行一些实验,那么您可以在其中试用一段代码。也可以在enter image description here中找到。

&#13;
&#13;
.header span {
  color: #000;
}

select {
  width: 100px;
}

#elms {
  border: solid 1px #000;
  margin-top: 20px;
  position: relative;
}

span {
  color: #FFF;
  font-size: 1em;
}

#elm1 {
  background-color: #300;
}

#elm2 {
  background-color: #6B0;
}

#elm3 {
  background-color: #90A;
}

#elm4 {
  background-color: #B00;
}

div {
  z-index: -1;
}

#div1 {
  width: 100%;
  height: 1px;
  background-color: #000;
  position: absolute;
  left: 0;
  top: 25%;
}

#div2 {
  width: 100%;
  height: 1px;
  background-color: #000;
  position: absolute;
  left: 0;
  top: 50%;
}

#div3 {
  width: 100%;
  height: 1px;
  background-color: #000;
  position: absolute;
  left: 0;
  top: 75%;
}
&#13;
<div class="header"> <span style="width: 100px;display: block;float: left;margin-right: 20px;">vertical align</span> <span>font-size(em)</span> </div>
<div>

  <select name="sl1" id="sl1">
    <option value="baseline">baseline</option>
    <option value="top">top</option>
    <option value="middle">middle</option>
    <option value="bottom">bottom</option>
  </select>
  <input type="number" value="1" id="ip1" />
  <br>
  <select name="sl2" id="sl2">
    <option value="baseline">baseline</option>
    <option value="top">top</option>
    <option value="middle">middle</option>
    <option value="bottom">bottom</option>
  </select>
  <input type="number" value="1" id="ip2" />
  <br>
  <select name="sl3" id="sl3">
    <option value="baseline">baseline</option>
    <option value="top">top</option>
    <option value="middle">middle</option>
    <option value="bottom">bottom</option>
  </select>
  <input type="number" value="1" id="ip3" />
  <br>
  <select name="sl4" id="sl4">
    <option value="baseline">baseline</option>
    <option value="top">top</option>
    <option value="middle">middle</option>
    <option value="bottom">bottom</option>
  </select>
  <input type="number" value="1" id="ip4" />
  <br>
  <button id="btnRandom" (onclick)="random()">Random</button>
</div>
<div id="elms">
  <span id="elm1">one</span>
  <span id="elm2">two</span>
  <span id="elm3">three</span>
  <span id="elm4">four</span>
  <div id="div1"></div>
  <div id="div2"></div>
  <div id="div3"></div>
</div>
<div id="viewer"></div>
&#13;
{{1}}
&#13;
&#13;
&#13;

此代码段由JSFiddle生成。

来源:请注意,这是由Christopher Aue撰写的Duannx摘录。

答案 1 :(得分:5)

问题是vertical-align: baseline;被忽略的原因。嗯,我不这么认为。在您的第一个代码段中,您使用baselinebottom明确区分了两个<span>元素。那么baseline做了什么?那么baseline将元素的基线与父元素的基线对齐。在下面的示例中,我复制并调整了一些部分以区别对待。

&#13;
&#13;
span.one {vertical-align:baseline}
span.two {vertical-align:middle;}
&#13;
<p>
  <span class="one">one</span> <span class="two">two</span>
</p>
&#13;
&#13;
&#13;

正如您所看到的,baseline对齐方式与middle对齐方式一样正常。

现在让我们测试别的东西。让我们交换baselinemiddle的对齐并修改middle并添加第三个<span>

&#13;
&#13;
span.one { vertical-align: top;}
span.two { vertical-align: baseline;}

span.three {vertical-align: middle; height: 20px; }
p {
height: 50px;
background-color: grey;
}
&#13;
<p>
  <span class="one">one</span> <span class="two">two</span> <span class="two">two</span><br><br> <span class="three">three</span>
</p>
&#13;
&#13;
&#13;

现在,如果您要编辑第二个代码段并查看vertical-align <span class="three">,您可以清楚地看到,在更改对齐时,文字确实会改变它的位置

但是您对同一行上的文字有疑问,所以让我们看看下面的代码片段。

&#13;
&#13;
span.one { vertical-align: middle;}
span.two { vertical-align: baseline;}

span.three {vertical-align: middle; height: 20px; }
p {
height: 50px;
background-color: grey;
}
&#13;
<p>
  <span class="one">one</span> <span class="two">two</span> <span class="two">two</span><span class="three">three</span>
</p>
&#13;
&#13;
&#13;

正如您在第三个片段中看到的那样,我将第三个<span>放在第一个和第二个旁边。它确实有所作为。在这种情况下,baselinemiddle对齐不同。这是因为baseline抓取了父级的baseline。由于父母的身高正常,因此不会影响baselinetop对齐。但是当你使用middlesub时,这显然是有区别的。

有关每个路线的信息,请查看此link

答案 2 :(得分:1)

一个简短的解释:起点是知道父级基线的位置。在<p>标记或<span>设置为vertical-alignment的{​​{1}}内添加一些文本(下面的跨度为“ one”)。跨度“ 1”的基线是字符的底部,例如字母“ n”的底部。

然后很容易看出另一个跨度相对于它的变化。我在跨度“一”周围添加了边框,以便我们可以清楚地看到其上边缘和下边缘。

baseline
span {  }
span:nth-child(1) {vertical-align:baseline; font-size:3em; border: 1px solid gray}
span:nth-child(2) {vertical-align:top; color:red}
span:nth-child(3) {vertical-align:middle; color:green;}
span:nth-child(4) {vertical-align:bottom; color:blue;}