1px calculation issue with browsers (sub-pixel pro

2019-01-20 10:28发布

I think this issue is common and picked it up here in SO itself, but could not find how to solve this.

Problem:

When you resize the window, you will notice that the height of the two images will differ by 1px at times (that is expected when browser adjusts the dimesions).

How do I 'fix' this UI issue? I know I can do that by using a flexbox. But I guess there is a better solution. Could you guys jump in?

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>

or even here when I use 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>

Edit: The issue not there in Firefox browser but exists in Chrome.

Note that the issue is not there when I use a 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>

or using floats and inline-blocks:

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>

4条回答
Lonely孤独者°
2楼-- · 2019-01-20 10:51

try this responsive image grid code http://codepen.io/mlegg10/pen/AXZGox change my img src= to whatever your code will be

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>

查看更多
Viruses.
3楼-- · 2019-01-20 10:56

That's because of Sub-Pixel Problems.

Each image takes 50% of the container. For example, if the container is 100px wide, each image will be 50px wide.

But the width of container could be an odd number of pixels, e.g. 101px. Then there are three reasonable possibilities:

  • Make one image 50px wide and the other 51px. Then the images won't be equally wide, even if you specified the same width to both of them.
  • Make both images 50px wide. Then there will be a 1px gap
  • Make both images 51px wide. Then they won't fit, overflowing the container or wrapping to the next line.

Each choice has its downsides, but nowadays browsers seem to prefer the first option. However, in this case, the images have an intrinsic aspect ratio, so different widths will produce different heights, and then the 1px gap is created horizontally instead of vertically.

It seems Firefox detects than, and thus makes the smaller image as tall as the other one, breaking the aspect ratio. Chrome prefers to enforce the aspect ratio.

There is no way to change this. It's completely implementation dependent:

The especially strange part, in all of this, is that there’s really no right, or wrong, here. How this behavior is supposed to play out by the rendering engine isn’t dictated by the CSS specification, having it be left up to the implementation to render as it sees fit.

查看更多
我欲成王,谁敢阻挡
4楼-- · 2019-01-20 10:56

Since chrome doesn't seem to play very well with .5px values.
Here is a javascript solution to make the width always an even number, thus the height will also be even:

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>

查看更多
疯言疯语
5楼-- · 2019-01-20 10:56

Just thought of a different approach to this which might meet your needs... instead of worrying about forcing the image sizes, you can vertically-align everything to the top, and then hide the bottom 1px of the wrapper div by adding a 1px high pseudo-element which is the same color as the background. This will solve the visual aspect of having images 1px off from each other. It will also hide the bottom 1px of the images even if they are properly aligned, but depending on your images, this may not be a big deal at all.

body {width:501px; background:black;}
.wrapper{width: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%;}

fiddle: https://jsfiddle.net/w4ktweuo/1/

查看更多
登录 后发表回答