CSS width unreliable on Android?

Having tested mobile phones for the last seven months or so, I have become pretty well inured to odd, or even disastrous, results. Still, after encountering the following bug on the Android, even I started to doubt my sanity.

I don’t usually spend a blog post on a single browser bug, but this time I break that rule because this is doubtlessly the weirdest bug I found so far, and possibly also the most serious one.

CSS width may be unreliable on the Android — in certain situations.

The story centres on my box-sizing CSS test, which I obviously run in every phone I can get my hands on. In order to test the box-sizing property I have added a few reference boxes to the page. These reference boxes have hard-coded widths of 300, 330, and 310 pixels, respectively. Since this is a box-sizing test I was very careful not to give the reference boxes any padding or border.

The test is supposed to look like this (Android G2 in landscape mode):

The boxes at their proper width

The purple reference box is 300 pixels wide, the blue one 330 pixels, and the green one 310 pixels.

This allows me to determine that the Android supports -webkit-box-sizing. (In this particular case I feel that the -webkit- prefix is nonsense, because the definition of box-sizing isn’t going to change ever again, but let’s leave that discussion for another time.)

The weirdness starts as soon as you orient the G2 to portrait mode:

Android doesn’t understand widths any more in portrait mode

Obviously, the boxes still have the same hard-coded width. Still, all of a sudden the purple reference box with width: 300px is wider than the blue box with width: 330px.

What! The! F!?

(Apologies for the “F” but my profanity allotment for this month has already been used up.)

I can understand a width being slightly off; I don’t test whether the boxes actually take exactly 300 and 330 pixels. If it’s a few more or less, I don’t really care.

But I do expect a 300px-wide box to be less wide than a 330px one.

I mean, that’s not totally unreasonable, is it?

The Android G1 is slightly less odd: here the boxes are exactly equal in size. Still, this is not an ideal situation.

Android WebKit team, I advise you to take a look at your width calculation algorithm again. Something is hideously wrong.

This is the blog of Peter-Paul Koch, mobile platform strategist, consultant, and trainer. You can also follow him on Twitter.
Atom RSS

I’m around at the following conferences:

(Data from Lanyrd)

Categories:

Monthlies:

Comments

Comments are closed.

1 Posted by Joris von Loghausen on 29 September 2009 | Permalink

Funny thing;
I have an Android G1 with cyanogenmod (site is currently down because of the fuzz about packaging propriatery apps), and it behaves exactly the same as your G2 screenshot.

2 Posted by Mario on 29 September 2009 | Permalink

Men you make our lifes easier. So we'd better deactivate css for some browsers?

3 Posted by Matt Brubeck on 29 September 2009 | Permalink

If you turn off the "Auto-fit pages" option (a.k.a. "Please mess with my box widths") in the browser settings, then your test renders identically in landscape and portrait mode.

4 Posted by Matt Brubeck on 29 September 2009 | Permalink

By the way, if I had to guess, I'd say that the reason the 330px box shrinks smaller than the 300px box on some versions is that it triggers the "auto-fit" layout while the 300px box still uses normal layout rules. (Remember, this is on a screen that is 320px wide.)

5 Posted by GreLI on 29 September 2009 | Permalink

It's ironic that Google sponsored and ordered these tests.

And I also think that it is related to something like fit-to-width mode.

6 Posted by ppk on 29 September 2009 | Permalink

The auto-fit is an interesting idea; I hadn't thought of that yet.

Still, the page is much wider than just the middle column, and all other elements are at their correct position, so I'm wondering if there isn't something more complex going on.

And even if the page had been narrow and auto-fit would have kicked in, a 330px element still should have been wider than a 300px one.

7 Posted by Matt Brubeck on 30 September 2009 | Permalink

This is definitely caused by the auto-fit layout ("kLayoutFitColumnToScreen" in the Android WebKit source code). Just try the test with auto-fit disabled and everything is rendered correctly (at least on my Android device).

The auto-fit mode on Android seems to shrink certain elements' width without affecting their positioning, or the positioning of other elements. So if you have a containing block with width: 1000px and text that spans 100% of that width, the container may remain 1000px wide but the text inside it will wrap at the screen width.

As for the 330px element being smaller than the 300px one, I tried to explain one possibility above: Since the 330px element is wider than the 320px screen, it is subject to the (non-standard) auto-fit layout algorithm. But the 300px element does not trigger auto-fit, so it is layed out according to the standard. This is just a guess; I don't know if it's correct.

Now, you might argue that the auto-fit algorithm "should" apply the bare minimum shrinkage, leaving elements exactly 320px wide. But there's no specification governing the auto-fit layout algorithm (it deliberately violates the standard) so it's hard to predict or prescribe exactly how it should work.

8 Posted by David Kaneda on 30 September 2009 | Permalink

Does Android's WebKit accept the tag? I wonder how this would work if you did "initial-scale=1.0;
maximum-scale=1.0; minimum-scale=1.0". Thanks for the great research.

9 Posted by Kai Hendry on 30 September 2009 | Permalink

I think the bug might be related to text wrapped to screen width.

You have a box that is wider than the screen, so it is scaled down to fit on one line.

10 Posted by David Kaneda on 30 September 2009 | Permalink

Ah, sorry, didn't realize tags got stripped - meant the 'meta name="viewport"' tag-

11 Posted by ryan.j on 2 October 2009 | Permalink

Given the choice between a browser which renders 1:1 and has you zoomed out and/or scrolling or over the place to view the page, verses non-compliant rendering which allows you to quickly view the page's content on a mobile device, i'd definitely go with the latter.
Google's implementation needs some tweaking clearly but it's a useful feature of the browser.

the auto-resizing issue on Android devices tends to go away with liquid layouts and judicious use of floats, so the elements get shifted around rather than resized.

12 Posted by Gilles on 13 October 2009 | Permalink

Also I see the point of some concerning the auto-fit it would still be an auto-fit malfunction.

The auto-fit should make sure when it re-size elements that it respect the aspect difference ratio between them all. Meaning that if it has to reduce the size of an element by x all element should be reduce using the same multiplier.

Then you have a properly expected behavior for auto-fit. Or I guess it is more an auto-size :)