Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

1px calculation issue with browsers (sub-pixel problems)

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>
like image 629
kukkuz Avatar asked Aug 29 '16 15:08

kukkuz


3 Answers

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.

like image 156
Oriol Avatar answered Nov 13 '22 10:11

Oriol


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>
like image 28
mlegg Avatar answered Nov 13 '22 11:11

mlegg


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/

like image 21
andi Avatar answered Nov 13 '22 09:11

andi