Webkit is not calculating the width of the element incorrectly, resulting in a break in my layout

I have a rather complicated problem with layouts that only occurs in Webkit browsers. Take a look at this screenshot:

enter image description here

Let me first explain what I am trying to do here. The purpose of this layout is to show a grid of images, each cell of the cell will be square. The layout is responsive, so there could be 3 images per line at different viewport widths instead of 2.

Technically, the markup is a list of numbers, and there is a link inside each shape, and inside the link, the actual image. Pseudo-markup:

<ul>
<li><figure><a href=""><img src="" width="0" height="0" /></a></figure></li>
<li><figure><a href=""><img src="" width="0" height="0" /></a></figure></li>
</ul>

      

As you can see, the inner image has no width. This is intentional because the width is set on the li element that I am using as the container for the image. In the example viewport, as shown in the screenshot, the width of the li element is set to 50%.

Next, at runtime, I hide the img element alltogether and set its src path as the background image in the "a" element. The purpose of this is to correctly center the image regardless of image size or aspect ratio.

Basic Note: I am using box size: border-box for all elements.

Now, during this execution routine, I also dynamically calculate the height of the "li" element to ensure that it is square. Let's assume for a moment that the example screenshot has a viewport width of 400 pixels. Since all "li" elements are 50% wide, they should be 200px wide. Knowing this, I simply set the height of this "li" element to 200px, making it a square container:

// applied to all "li"s in the list
$(this).height($(this).width());

      

This works fine in every browser I tested except Webkit browsers (Chrome, Safari). When I set the width of an "a" (or li) element before setting it, CSS width and width, non-web browsers will report the same width for every "a" element. When I look at the console in webkit browsers there are differences in their widths. One "a" element can be 200px and the other 191px. The actual values ​​and whether or not it happens at all depends on the width of the browser's viewport, so it seems.

Either way, the result is the ugly whitespace you see in the screenshot. It so happened that due to the fact that the webkit unexpectedly reported different widths for these "a" containers (although they are all set to 50%), the height will also have variations, causing spaces.

So the big question is, why does webkit report incorrect and different widths for "a" elements that are all set to 50% of the same parent, while other browsers don't?

Theories so far

Here are a few things that have been researched so far:

I use inline-block for li elements, which is known to cause extra "space". I solved this by removing the space from the markup. Inline-block is not a problem anyway, because when I change the "li" elements to floats, the webkit browsers still have different widths if they shouldn't.

Another theory has to do with the order in which things are loaded, where it might require some pretense of deferring my temporary image rendering routine to the window.load event. Unfortunately, the result is exactly the same.

I also know the difference between .width () and .css ("width") in jQuery (I'm using 1.8.2). It doesn't make any difference as I am outputting to both the console and Webkit is getting both values ​​wrong.

Mixing

Sorry for the detailed explanation, so summary: I set the width to 50% (or 33.3333%, depending on the viewport width) on the list items, and then fetch the actual pixel width at runtime. For some cryptic reason, webkit browsers report different widths, even though all list items have the same percentage width.

Finally, here is a direct link to the problem:

[removed due to release issue and live code change]

To reproduce the problem, you need to use a webkit browser and resize the window to approximately the size of my example screen. This seems to be happening with an arbitrary viewport width.

+3


source to share


3 answers


It seems to me that it has something to do with whether the pixel width in the viewport is divisible by 2 or 3. In cases where the width is 50% and $ (document) .width () / 2 = 0 then there is no problem, but when $ (document) .width () / 2 = 1, space appears.

So instead of calculating the height for each, perhaps you can calculate it once and use it every time, i.e. change imageLayout () to:



var aHeight = $('.photos li figure > a')[0].width();
$('.photos li figure > a').each(function(index) {
    console.log('w: ' + $(this).width() + " css w: " + $(this).css("width"));
    console.log('pw: ' + $(this).parent().parent().width() + " css pw: " + $(this).parent().parent().css("width"));
    $(this).height(aHeight);


    if ($(this).attr('data-loaded') != "1") {
        var imgcaption = $(this).parent().find('figcaption a');
        imgcaption.html('<em class="icon-bolt"></em> loading...');
    }

});

      

+6


source


Have you checked if li or ul elements have defaults in webkit browsers? Try setting all ul or li at the top of your stylesheet to 0px for margin and padding.



li { margin:0px; padding:0px;} ul{ margin:0px; padding:0px}

      

+1


source


I've had this problem before and there is definitely something wrong with browsers.

Example: http://jsfiddle.net/gSWkd/2/

(Firefox: excellent / Chrome: first 2 entries 112, other entries 111)

Maybe grab the width / height from the first image and apply to others?

Something like this: http://jsfiddle.net/gSWkd/4/

HTML:

<div class="why">
    <div class="heresWhy red"></div>
    <div class="heresWhy blue"></div>
    <div class="heresWhy red"></div>
    <div class="heresWhy blue"></div>
    <div class="heresWhy red"></div>
    <div class="heresWhy blue"></div>
    <div class="heresWhy red"></div>
    <div class="heresWhy blue"></div>
    <div class="heresWhy red"></div>
    <div class="heresWhy blue"></div>
</div>

      

CSS

.why {
    width: 223px;
    height: 223px;
}
.heresWhy {
    width: 50%;
    height: 50%;
    float: left;
}
.heresWhy.red {
    background: red;
}
.heresWhy.blue {
    background: blue;
}

      

Js

// Apply 50% W/H to the first image
$('.why div:first-child').width('50%');
$('.why div:first-child').height('50%');

// Get W/H from the first image
var rightSize = $('.why div:first-child').width() - 1;

// Apply W/H to other images
$('.why div').each(function(){
    $(this).width(rightSize);
    $(this).height(rightSize);
});

// Check W/H
$('.why div').each(function(){
  $(this).html($(this).width()); // Show div width
  $(this).html($(this).height()); // Show div width3
})

      

+1


source







All Articles