safari rounding down on subpixel calculations
Asked Answered
N

6

13

i have a container that takes up 829px on a row, and has a background-image of the same size.

i have a div within that container that calculates its width based on the 829px container. on safari, the divs width comes out to be something like 173.8px, but since safari/webkit round down, its truncated and becomes 173px in width.

this 829px container has 3 divs inline on the same row. the first div, 1px is lost, the second, 2px is lost, and by the third, 3 pixels are lost, so the third div is shifted left by three pixels. on an ipad, thats 6 pixels lost.

i've tried to search for subpixel rendering problems, and ive read john resigs article and some other SO questions but i couldnt find a solution.

on google, i found an article: http://www.pixafy.com/blog/2013/05/css-subpixel-rendering/#more-310 i tried to apply it to my situation, but i cannot get away with not setting a width thats calculated on the containers 829px.

what can i do?

Neanderthal answered 30/5, 2013 at 15:14 Comment(5)
Use 33.333333% for width assuming a triple column layout, if margins or paddings are present, calculate those as % also, and subtract them from the width above, if a border is present, use box-sizing: border-box. (also fixes padding calculations).Effortful
yeah i could do that, 1pixel will still be lost in the last div though, if i use .33333*829= 276.33px, .33*3=1pixel, so the last div will be shifted left by 2 pixels on an ipad.Neanderthal
I do believe using the percentage unit causes the width to be calculated differently which should solve your problem. Here's a demonstration: jsfiddle.net/pZg4dEffortful
hmm i dont understand, im already using it as a percentage of the width, because webkit rounds down on percentages.Neanderthal
Wait, you are using a percentage width for your child divs and you are seeing this still? I've never had this issue =\Effortful
B
9

There isn't a whole lot you can do about how different browsers render subpixels, sadly. It'd be great if we could choose how the rounding should be handled through CSS, but nope.

Simply using pixels rather then percentages would solve the problem but that's obviously not what you want. I guess you could get around with static pixels if you change the values (possible to a percentage value) through media queries.

Whenever I find myself in a similar scenario I float the last child to the right. A few additional pixels between the last and second last elements don't usually hurt as much as a few additional pixels between the last element and its parent.

Bergson answered 31/5, 2013 at 13:6 Comment(0)
S
3

These days you could use flexbox (pure CSS) to handle this.

From the source linked above:

The main idea behind the flex layout is to give the container the ability to alter its items' width/height (and order) to best fill the available space (mostly to accommodate to all kind of display devices and screen sizes). A flex container expands items to fill available free space, or shrinks them to prevent overflow.

Scrod answered 30/11, 2015 at 1:45 Comment(0)
U
1

I've recently encountered this issue using the whilst using the Bootstrap framework. After trawling the net I found this link http://cruft.io/posts/percentage-calculations-in-ie/ and did some device testing. iOS7 Safari seems to round down to the nearest whole number, whilst iOS8 (Which has subpixel rendering on by default) seems to round up slightly to a max. of 15 decimal places. This also seems to be the same on OSX 10.10 (Yosemite)

As Nils K mentions in his/her answer, either use a pixel width layout, or try to adapt the layout to make sure it's wide/narrow enough to fit a whole pixel into the space

Upend answered 4/2, 2015 at 16:18 Comment(0)
W
0

If you can't do float: right on the last element in the 'row' because of background colors being revealed, etc, you could use the following trick to really hackily hide the background (note it's SASS code):

.safari .parent_element { // CHANGE
  position: relative;

  &:after {
    content: ''
    position: absolute;
    height: 100%;
    width: 3px;
    top: 0;
    left: calc(100% - 2px); // Or sometimes 'right: 2px;' will work
    background-color: $pageBackground; // Change
  }
}

The safari class is added to <html> using a Modernizr test:

Modernizr.addTest('safari', function() {
  var uagent = navigator.userAgent.toLowerCase();

  return /safari/.test(uagent) && !/chrome/.test(uagent);
});

The only reason I've ever used this test is to overcome Safari's subpixel rendering with a background gradient running between grid items that have a percentage width. I'm not advocating for it's widespread use! However, it's an effective last resort.

Wylde answered 3/7, 2014 at 19:31 Comment(0)
T
0

If this happens to be in relation to a slider where you have an odd set of images (e.g. 3 vertical sliders), one minor hack is to increase the middle images' width to 101%.

.middle-slider img { width: 101%; }

When it comes to this mishandling by browsers, this is only one mildly acceptable solution in the pile of hacks out there and certainly suffices for most use cases.

Tutto answered 27/3, 2015 at 10:30 Comment(0)
K
-2

I just faced a similar issue and I wrote about how I solved it here: http://maxlapides.com/fixing-subpixel-layout-rendering-in-safari/

Basically, I came up with some JavaScript that recalculates the widths of the items so they span the full width of the container.

Kentkenta answered 27/12, 2013 at 17:51 Comment(2)
Please post the code directly in your answer, for posterity. Link-only answers are unsuitable for StackOverflow since they may vanish at any time.Repartition
And yes, the content on link is gone.Kep

© 2022 - 2024 — McMap. All rights reserved.