CSS 行高问题 - 无法获得准确的行数

CSS line height problem - Can't get an exact number of lines

我找到了关于这个主题的更早的 post,但对于很多人来说,最受欢迎的答案和其他任何答案都没有用。多年以后,那也包括我。

我正在尝试使 div 恰好 19 行高(最终我将达到 19.5 行,因此当有更多文本要滚动到时,您总是会看到恰好半行,但是我首先尝试 19。)当我调整我的浏览器 window 大小时,我看到了文本的各种小数部分:这正是我试图防止的问题。下面,显示大约 19 和大约半行:

这是我正在使用的 CSS,上面显示的外部 div 和内部较暗的 div:

#marquee-dialog > div {
  font-size: 3vh;
  line-height: 3.6vh;
  position: absolute;
  margin: auto;
  top: 0; left: 0; bottom: 0; right: 0;
  width: 80vw;
  height: 80vh;
  padding: 1em;
  background-color: white; /* Changed via JavaScript later */
  color: black;
}

#marquee-big-text {
  font-size: 3vh;
  line-height: 3.6vh;
  max-height: 22.8em;
  overflow: auto;
}

我将行高设置为字体大小的 1.2 倍,max-height 设置为 19 * 1.2 = 22.8 em。 (我也尝试过 68.4vh,并设置 heightmax-height 一起,或代替 max-height,但没有任何区别。)这看起来确实应该出现 19 行,正如在浮点精度允许的情况下。

当我检查 web 控制台时,div 的高度正好或几乎正好是行高的 19 倍,几乎正好是 em 大小的 22.8 倍,我可以通过检查外div.

的填充大小来检查

内部 div 有 0 个内边距、0 个边距和 0 个边框,以消除数字。

根据我看到的所有数值,我得到了 19 行。但是渲染仍然渲染了一点。超出部分出现在 Chrome、Firefox 和 Safari 中。

我一定是遗漏了什么明显的东西?

更新

我试过了,使用从网络控制台获取的精确像素值:

#marquee-big-text {
  font-size: 3vh;
  line-height: 31.968px; /* 3.6vh; */
  max-height: 607.392px; /* 22.8em; */
  overflow: auto;
}

我仍然遇到同样的问题,尽管这些是 19 行的接近精确值。

更新 2

我从屏幕截图中取了一些尺寸。基于从基线到基线的测量,呈现的每个文本行 为 62 像素高。整个 div 是 1212 像素高。根据这些测量值,大约 19.55 行应该适合 space,这解释了我所看到的。如果要接近 19 行,基线到基线的测量值应该约为 63.79 像素,每行几乎多 2 个像素。

这看起来几乎像是渲染舍入误差,但奇怪的是,如果它是舍入的,那么浏览器与浏览器之间的舍入是一致的。

更新 3

这是一个工作示例:

https://codepen.io/kshetline/pen/NWNGOWL

有趣的是,在这个简化的示例中,问题仍然出现在 Chrome 和 Safari 中,但 Firefox 总能解决问题。

您可能需要将 Codepen 视图切换到这个方向:

...看到问题了。该错误仅在相当大的字体大小时出现,并且当我调整浏览器的大小时 window 在快速回到 19 行之前,多余的部分永远不会超过半行。

越来越像字体大小舍入错误。我猜这与渲染优化有关,避免缓存过多字体大小差异的大字体位图。

这不是我希望得到的答案,但我可以用 JavaScript 解决问题。看来我必须强制使用整数像素大小才能可靠地进行精确的行计数。

const middiv = document.querySelector('.outer > div');
const inner = document.querySelector('.inner');
let lastLineHeight = 0;

function checkFont() {
  const style = document.defaultView.getComputedStyle(middiv, null);
  const exactHeight = parseFloat(style.getPropertyValue('line-height'));
  const roundedHeight = Math.floor(exactHeight);

  if (lastLineHeight !== roundedHeight) {
    inner.style.lineHeight = roundedHeight + 'px';
    inner.style.maxHeight = (roundedHeight * 19) + 'px';
    lastLineHeight = roundedHeight;
  }
}

window.addEventListener('resize', checkFont);
checkFont();

这里有一个 Codepen 来演示这个:https://codepen.io/kshetline/pen/vYGLjBo