浏览器的 1px 计算问题(亚像素问题)

Posted

技术标签:

【中文标题】浏览器的 1px 计算问题(亚像素问题)【英文标题】:1px calculation issue with browsers (sub-pixel problems) 【发布时间】:2017-01-05 16:47:06 【问题描述】:

我认为这个问题很常见,并在 SO 本身中找到了它,但找不到如何解决这个问题。

问题

当您调整窗口大小时,您会注意到两个图像的高度有时会相差 1px(这是浏览器调整尺寸时的预期)。

如何“修复”这个 UI 问题?我知道我可以通过使用flexbox 来做到这一点。但我想有一个更好的解决方案。你们能跳进去吗?

table
  width:100%;
  border-collapse: collapse;

img
  display: block;
  width: 100%;
<table>
  <tr>
    <td><img src="http://placehold.it/100x100"/></td>
    <td><img src="http://placehold.it/100x100"/></td>
  </tr>
</table>

当我使用display: table时,甚至在这里:

.wrapper
  width:100%;
  display: table;

.wrapper div
  display: table-cell;  

img
  display: block;
  width: 100%;
<div class="wrapper">
    <div><img src="http://placehold.it/100x100"/></div>
    <div><img src="http://placehold.it/100x100"/></div>
</div>

编辑: 这个问题在 Firefox 浏览器中不存在,但在 Chrome 中存在。

请注意,当我使用 flexbox 时,问题不存在:

body
  margin: 0;  

.wrapper
  width:100%;
  display: flex;

.wrapper div
  flex: 1;  

img
  display: block;
  width: 100%;
<div class="wrapper">
    <div><img src="http://placehold.it/100x100"/></div>
    <div><img src="http://placehold.it/100x100"/></div>
</div>

或使用浮点数和内联块:

body
  margin: 0;  

.wrapper
  width:100%;
  display: block;

.wrapper div
  display: inline-block;
  float: left;
  width:50%;

.wrapper:after
  content: '';
  display: inline-block;
  clear:both;

img
  display: block;
  width: 100%;
<div class="wrapper">
    <div><img src="http://placehold.it/100x100"/></div>
    <div><img src="http://placehold.it/100x100"/></div>
</div>

【问题讨论】:

表格用于表格数据,您应该使用 flexbox 或其他 css 选项来处理图像 实际上我正在寻找除了我在问题中提到的 flexbox 之外的解决方案 flex 是您的 html 代码描述的最佳选择 @yousefsami padding 不起作用-尝试调整浏览器大小 img width: calc(100% + 2px); ? 【参考方案1】:

只是想到了一种可能满足您需求的不同方法...而不是担心强制图像大小,您可以将所有内容垂直对齐到顶部,然后通过添加隐藏包装器 div 的底部 1px一个 1px 高的伪元素,与背景颜色相同。这将解决图像彼此相距 1px 的视觉问题。即使图像正确对齐,它也会隐藏图像的底部 1px,但根据您的图像,这可能根本不是什么大问题。

body width:501px; background:black;
.wrapperwidth:100%; display:table; position:relative;
.wrapper:after content:""; position:absolute; bottom:0; left:0; height:1px; width:100%; background:black;
.wrapper div display:table-cell; vertical-align:top;
img display: block; width:100%;

小提琴:https://jsfiddle.net/w4ktweuo/1/

【讨论】:

你是个天才。在玩了几个小时之后,我终于添加了一个 :before 和 width:100%;height:100%;border:1px solid white;,它与元素重叠并隐藏了任何不一致的子像素渲染。【参考方案2】:

因为 chrome 在 0.5px 值下似乎不能很好地发挥作用。 这是一个使宽度始终为偶数的javascript解决方案,因此高度也将是偶数:

https://jsfiddle.net/hhmsqtz6/1/

$(document).ready(function() 
  resizeToEven();
);

$(window).resize(function() 
  resizeToEven();
);

function resizeToEven() 
  $('tbody').width(function(i, w) 
    var parentwidth = $('tbody').parent().width();
    return (parentwidth - parentwidth % 2);
  );
table, tbody, tr 
  width: 100% !important;
  border-collapse: collapse;
  display: flex; /* I had to made them flex, other display wasn't working */


img 
  display: block;
  width: 100%;
  height: auto;


td 
  padding: 0; /* put padding, to remove the gap */
  
  /* set the width, because when right clicking it gets all messed up (at least it did, in my tests) */
  width: 50%;


html 
  background: black;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
  <tbody>
    <tr>
      <td><img src="http://placehold.it/100x100" /></td>
      <td><img src="http://placehold.it/100x100" /></td>
    </tr>
  </tbody>
</table>

【讨论】:

【参考方案3】:

试试这个响应式图像网格代码http://codepen.io/mlegg10/pen/AXZGox 将我的 img src= 更改为您的代码

img 
  width: 100%;
  height: auto;

/*  SECTIONS  */
.section 
	clear: both;
	padding: 0px;
	margin: 0px;


/*  COLUMN SETUP  */
.col 
	display: block;
	float:left;
	margin: 1% 0 1% 1.6%;

.col:first-child  margin-left: 0; 

/*  GROUPING  */
.group:before,
.group:after  content:""; display:table; 
.group:after  clear:both;
.group  zoom:1; /* For IE 6/7 */ 

/*  GRID OF TWO  */
.span_2_of_2 
	width: 100%;

.span_1_of_2 
	width: 49.2%;


/*  GO FULL WIDTH AT LESS THAN 480 PIXELS */

@media only screen and (max-width: 480px) 
	.col  
		margin: 1% 0 1% 0%;
	


@media only screen and (max-width: 480px) 
	.span_2_of_2, .span_1_of_2  width: 100%; 
<div class="section group">
	<div class="col span_1_of_2">
	<img src="http://www.irishtimes.com/polopoly_fs/1.2614603.1461003507!/image/image.jpg_gen/derivatives/box_620_330/image.jpg">
	</div>
	<div class="col span_1_of_2">
	<img src="http://www.irishtimes.com/polopoly_fs/1.2614603.1461003507!/image/image.jpg_gen/derivatives/box_620_330/image.jpg">
	</div>
</div>

【讨论】:

全屏查看codepen,然后慢慢缩小尺寸,观察它如何保持纵横比,然后将图像堆叠在窄屏中 我经常使用那个网格系统。看看这个页面就可以自定义了responsivegridsystem.com/calculator【参考方案4】:

那是因为Sub-Pixel Problems。

每个图像占用容器的 50%。例如,如果容器是 100px 宽,则每个图像将是 50px 宽。

但容器的宽度可能是奇数个像素,例如101 像素。那么有三种合理的可能性:

将一张图片设为 50 像素宽,另一张设为 51 像素。然后,即使您为它们指定了相同的宽度,图像的宽度也不会相同。 将两张图片设为 50 像素宽。那么会有1px的差距 将两张图片设为 51 像素宽。然后它们就装不下,溢出容器或包装到下一行。

每种选择都有其缺点,但如今的浏览器似乎更喜欢第一种选择。但是,在这种情况下,图像具有固有的纵横比,因此不同的宽度会产生不同的高度,然后会在水平方向而不是垂直方向创建 1px 的间隙。

似乎 Firefox 检测到了比,因此使较小的图像与另一个图像一样高,从而破坏了纵横比。 Chrome 更喜欢强制执行纵横比。

没有办法改变这一点。它完全依赖于实现:

在所有这一切中,特别奇怪的是,真的没有 对或错,在这里。这种行为应该如何发挥作用 渲染引擎不受 CSS 规范的限制,具有 它留给实现来按照它认为合适的方式呈现。

【讨论】:

感谢您的精彩解释 :) 所以我猜 flexboxes 打破了纵横比?除此之外还有其他选择吗? @kukkuz 由于规范没有指定在这些情况下应该发生什么,你不能依赖任何东西。您可以尝试不同的方法并使用适用于大多数浏览器的方法,但未来或过去的版本可能会有所不同。

以上是关于浏览器的 1px 计算问题(亚像素问题)的主要内容,如果未能解决你的问题,请参考以下文章

主流浏览器的亚像素精度现状如何?

移动端1px像素解决方式,从1px像素问题剖析像素及viewport

FF25 和 IE10 中的内联 SVG 上的 1 像素(或更少?亚像素?)边框,而不是 Chrome

野生动物园在亚像素计算上四舍五入

移动web知识

移动端入门