有没有办法让文本字符齐平到 HTML5 中的边界框顶部?

Is there a way to make text characters flush to the top of their bounding box in HTML5?

这是 HTML 中的一个标签元素,红色虚线轮廓显示它的边界框。请注意,字符 not 与其边界框的上边缘齐平:

line-height:1.2; /* default */


这是显示上图的 JSFiddle http://jsfiddle.net/6gLQU/16/.

这里是相同的文本,其中 line-height 样式设置为 1 或 100%(更好但仍然不齐平):

line-height:1;

最后,如果我将 line-height 样式设置为 .8 (80%),如 this code example,它是齐平的,除了最后一个测试文本中的一个小但可接受的单个像素差异.这很好,但如果有不止一行文本(多行),那么下一行会被拉得太高,因为这会使每行高度达到其实际高度的 80%。

line-height:.8;

这是 JSFiddle 代码 http://jsfiddle.net/6gLQU/16/


(不懂Flash的可以跳过这一段) 在 Flash TLF(FTE 或 Flash 文本引擎)中,如果您添加一个文本字段,使用 FTE 或 TLF 作为它的引擎,文本字符将对齐到边界矩形的最顶部。它们看起来像最后一张图片中的文本(字符紧贴边界框的顶部边框)。


在 HTML 中,文本字符未对齐到边界矩形的顶部,如上例所示。当您增加字体大小时,您也会增加从字符顶部到边界框矩形顶部的间隙。

在我对 HTML 和 CSS 中使用的文本的研究中,字体样式 line-height 将调整文本字符在其边界框内的位置(如上图)。在 Flash 中,line-height 样式不会影响文本第一行中的字符,但会调整以下行以及 HTML 中的字符(因此它在 HTML 或 Flash 中不起作用多线)。

我已经确定,如果我在 HTML 中将行高设置为 .8 或 80%,则字体会与边界框的顶部齐平(如上所示)。伟大的!这就是我想要的,但它不适用于多行文本。如果不止一行,则下一行是 "pulled up" 并与前一行重叠,因为很明显,我只给每行提供了其实际高度的 80%。


无论如何,我的问题是:

  1. 有没有其他方法可以让 HTML 字符齐平到边界框的顶部?我对 line-height 使用的 hack 导致多行文本靠得太近。
  2. Flash TLF 中是否有设置使其行为和显示像 HTML 文本行?也就是说,使其不会将文本字符拉到边界框的顶部(匹配 HTML 布局规则)。

我找到了一个使用负边距的替代方案 space 但我必须手动输入它。这并不理想,因为它对每种字体大小都有不同的值(通过反复试验发现)并且它会向上移动文本框,而不是字符。通过 line-height hack,我可以使用 .8 并且我知道它会被正确定位。

这是一张 link to the code 和使用负边距的图片。我只将它应用到最后一个元素。注意红色边框:

font-size:64px;
line-height:1.2;
margin-top:-14px;

这里 another test and another using multiples of 12 使用负保证金百分比。同样,每个负边距值都是不同的,并且是通过反复试验发现的:

font-size:12px;
line-height:1.2;
margin-top:-.19%;

这是关于 FTE engine 的信息。我读了一个小时,现在我意识到我知道其中的几个词。

PS 抱歉这个问题太长了。显然,我正在努力赢得最长的 post 奖项。此外,我添加了 两个 问题,因为存在实际问题,然后是如果实际问题可以解决则可能没有必要的解决方法问题。我不确定这叫什么,但有人告诉我这是关于 SO 的编程问题的常见问题。此外,添加 Firefox 标记,因为它在 Firefox 中是 运行,并且 Firefox 开发人员之一可能会看到它并知道这一切是如何工作的。

2019 年更新:
我在某处有另一个问题 posted 关于这个问题,但公认的修复适用于特定字体,但不适用于所有字体。

IIUC 文本字符的上边缘称为字形,称为大写高度,字形周围容器的高度称为 em 高度。每种字体的大写高度都不同,因为字体具有不同的样式并且由不同的作者创建。

IIUC 浏览器不根据 em 或字体大小定位,并且不考虑大写高度。

我对浏览器提出的 功能请求 是支持将段落或标签文本的第一行对齐到大写高度,以便文本齐平到顶部边缘。那可能是负文本边距。这将使浏览器准确地重现许多设计工具所支持的内容。

// something like any of these: 
align-caps-height: true;  
first-line-position: caps-height;
margin-top: caps-height;

这里的字体间距不是问题,因为文本会均匀缩放。问题是由保证金百分比造成的。边距百分比计算为 宽度 的百分比。因此,正如您所料,保证金百分比与

之间没有关系

方法一

您可以做的是,找出一个块的边距(以像素为单位)。然后让 k = font_size/ margin 代表该块。将 font-size 除以 k 得到其他块的余量。


方法二

尝试使用 transform: translate;em 值,而不是使用百分比保证金:

相关代码

label { /* added properties*/
  transform: translateY(-0.2em);
}

Updated Fiddle 1


方法三

我意识到,虽然有点晚,但 transform 不是必需的。您可以简单地使用 margin-top: -0.2em;

相关代码

label { /* added properties*/
  margin-top: -0.2em;
}

Updated Fiddle 2

#BorderContainer1711  {
 position:absolute;
 left:32px;
 top:60px;
 width:500px;
 height:160px;
 background-color:#FFFFFF;
 background-alpha:1;
 border-width:1px;
 border-style:solid;
 border-color:#00DD00;
 color:#000000;
}

label { /* added properties*/
   margin-top: -0.2em;
}

#Label1551  {
 position:absolute;
 left:46px;
 top:60px;
 color:#000000;
 font-weight:normal;
 font-family:Arial;
 font-size:12px;
}

#Label1613  {
 position:absolute;
 left:123px;
 top:60px;
 width:61px;
 color:#000000;
 font-weight:normal;
 font-family:Arial;
 font-size:24px;
}

#Label937  {
 position:absolute;
 left:220px;
 top:60px;
 color:#000000;
 font-weight:normal;
 font-family:Arial;
 font-size:36px;
}

#Label2125  {
 position:absolute;
 left:342px;
 top:60px;
 color:#000000;
 font-weight:normal;
 font-family:Arial;
 font-size:64px;
}



*, *:before, *:after {
  -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;
}


*, *:before, *:after {
  outline:1px dotted red;
}
 <div id="BorderContainer1711">

 </div>
 <label id="Label1551">[12px]</label>
 <label id="Label1613">[24px]</label>
 <label id="Label937">[36px]</label>
 <label id="Label2125">[64px]<br>nextline</label>