浏览器如何处理高度和宽度的非整数值?

38

当浏览器为元素指定非整数值的宽度和高度时,它们如何处理?

具体来说:

  • 非整数值在什么阶段被四舍五入?是向最近的整数四舍五入还是直接截断?
  • 当容器的子元素具有非整数维度时,是否会出现子元素长度或高度之和不等于父元素内部宽度/高度的情况?
  • 提供的非整数尺寸与基于百分比的尺寸的非整数结果是否有所不同?
  • 那么填充和边距的非整数值呢?
  • 编辑:浏览器执行此四舍五入操作,还是操作系统执行?如果是操作系统,是否会出现浏览器“认为”项目比其绘制区域大的情况,并且是否会导致父容器大小的问题?

1
为什么您认为它们是由浏览器四舍五入的呢? - Denys Séguret
您是否希望非整数值附带另一个度量单位?那么,当然不能直接将其舍入为整数。不过,最终您无法显示小于1px的任何内容,尽管子像素可能可用于指示下一个像素的颜色渐变。 - Markus Deibel
我相信浏览器在渲染层面上不应该将位置四舍五入为整数(如果他们不想这样做的话)。但是我找不到任何规范说明,只有与浏览器不精确的子像素相关的错误报告... - Denys Séguret
@dystroy - 我也找不到确定的参考资料。我认为答案是“浏览器肯定可以处理浮点数,但它们何时/如何这样做是不一致的”……我很想删除我的答案。 - Tim M.
相关:https://dev59.com/tmUp5IYBdhLWcg3wZG8c - bfavaretto
显示剩余2条评论
1个回答

62

断言

浏览器设计用于处理浮点数和小于一个像素的值。


要查看一个简单示例,演示浏览器在计算中使用浮点数,请创建一个 3% 宽度元素并在 Chrome 开发者工具中查看其调整大小时的计算属性。

你应该会看到像这样的东西:

enter image description here

"35.296875" 无法通过将一个像素映射到物理显示 (CRT、传统 LCD) 上的显示设备精确呈现。但是,新的高密度显示器使用与 1-1 不同的比率,这个分数值可以在概念上用于提供更高程度的精度。

即使在低密度显示器上,分数值也可以为子像素渲染提供提示,后者使用像素的红、绿和蓝色分量,使对象的边缘看起来比整个像素值平滑。

但是浏览器对这种数字的处理方式并不是非常可预测的。你不能(目前)要求浏览器使一个框宽度为 31.5px,并期望得到一致或甚至有意义的结果。一些浏览器会截断小数值,而另一些则四舍五入。

子像素渲染通常用于文本,在大多数/所有浏览器中运行得相当不错,但是每个浏览器都以不同的方式实现了这个功能,开发人员几乎无法影响其工作方式。

何时

非整数值在继承链中的哪个阶段被舍入?

大多数/所有的计算都是使用浮点数执行,任何舍入可能会在过程中或甚至在浏览器控制之外发生。例如,浏览器可以将其抗锯齿委托给操作系统组件(例如 IE9 委托给 Windows Direct2D 和 DirectWrite)。

CSS 转换可能会与操作系统和/或硬件加速密切集成。这是我认为高度可能的另一种情况,即浮点值由浏览器保留并传递到底层层。

舍入行为/误差

当容器的子元素具有非整数维度时,是否会出现子长度或高度的总和不等于父元素的内部宽度/高度的情况?

我在旧版浏览器(如 IE7)中看到过这种情况,原因是百分比计算,其中 50% + 50% > 100%。通常情况下,这并不是问题,直到您尝试做更复杂的事情。据经验,当尝试将 HTML 元素精确对齐为动画的一部分时,会出现“差一个像素”的错误。

百分比 vs. 其他单位

提供的非整数维度与百分比维度的非整数结果是否有所不同?

它们会四舍五入到最近的整数还是截断它们?

这因浏览器而异。 这篇旧文章 指出它们被截断了,但在 Chrome 24 中,我看到了四舍五入的结果(请注意示例 fiddle)。请注意我之前关于在同一台机器上Chrome和Safari之间差异的评论。

那么填充和边距的非完整值呢?

似乎应用相同的规则(或没有规则)。

标准

关于浮点数处理的标准定义尚未找到。 我能找到的最相关的规范是closest relevant spec,其中提到了canvas像素:

当指定的坐标没有精确地映射到设备坐标空间时,像素舍入的处理方式在此规范中未被定义,但以下情况必须导致呈现不发生可见更改:[...list of conditions...]

再次强调,这是特别涉及canvas的部分,但它确实暗示了:

  • 浏览器绝对与小数像素交互。
  • 实际实现会有所不同。
  • 存在某种标准化。
  • 映射到设备的显示可能会影响计算。

1
在苦苦挣扎一段时间后,我偶然发现了这篇文章,其中介绍了一个文本垂直上下跳动的 bug。我发现这是由于在一个动态元素列表上滚动时,这些元素没有整数填充/边距所导致的。以下是一个简化的代码示例,以演示文本移动:http://plnkr.co/edit/2hDDBNC9y5MGb5ZJO665?p=preview - rds
@rds - 很好的例子。我认为可以说所有浏览器都在某种程度上理解亚像素值(即使在您的示例中,我也可以看到分数填充值),但它们的行为是不可预测或可预测的糟糕。当我尝试在各个浏览器之间实现像素完美对齐时,我通常使用整数像素值来设置字体大小和行高。文本尤其棘手,因为呈现在浏览器甚至浏览器版本之间差异很大。 - Tim M.
如果非整数的px值与%值相加,则结果可能再次成为整数。例如,如果您有一个宽度为101px的容器,然后是一个具有float:left; width:50%; padding-right:0.5px; box-sizing:border-box;的子元素,则子元素将恰好具有50px的宽度。也就是说,如果浏览器表现良好-这就是这个问题所关心的。@TimMedora您或其他人可以确认这一点,适用于Chrome以外的浏览器吗? - donquixote

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接