I recently ran into some odd font sizing issues when viewing my website on my iPhone and discovered a few interesting tidbits about rendering on mobile browsers along the way.
Recently I found the time to finally get around to some tweaks to my website theme that I’d been meaning to make for some time — primarily these were related to syntax highlighting and code snippets.
Handling code snippets in HTML has some surprising subtleties, one of them being the overflow behaviour. As much as you try to wrap everything at a sensible number of columns, there will always be times when you absolutely need to represent a long line and it’s always rather unsatisfactory to have to explain that the line breaks were just added for readability. As a result, the styling needs a graceful fallback for these inevitable cases.
I considered using white-space: pre-wrap
, which acts like
<pre>
except that it wraps text on overflow as well as explicit line breaks.
One complication, however, is that I sometimes use line numbering for my
longer code snippets:
1 2 3 |
|
To facilitate easy cut and paste this is actually a HTML table with a single
row and the line numbers and file content in their own cells, contained within
nested <pre>
tags1. This is handy, but it does lead to some
odd formatting issues, since there’s nothing explicitly aligning the individual
lines in the two elements except for the fact that they’re using a consistent
font and line width.
One issue I’ve had in the past, for example, is when I used bold text for some
of the syntax highlighting styles — I found that some browsers would adjust
the line height when this happened such that the rows no longer quite lined up
after that point. I tried various line-height
fixes with limited success, but
eventually it was just easiest to avoid bold text in code snippets.
Another issue concerns overflows — if you wrap text in the file content as I suggested earlier then you’d need to also somehow arrange a gap (or repeat) in the line numbering or all the line numbers will be off by one for each wrapped line. There’s no practical way to arrange this except by perhaps putting each code row in its own table row and modifying third party code extensively to do that just didn’t appeal for a quick fix.
Instead, therefore, I opted for using overflow: auto
, which
inserts scrollbars as required, combined with judicious
max-width: 100%
here and there. I was pleasantly surprised
to see this works on any sensible browser2.
However, when I tested the site on my iPhone I discovered a new and puzzling issue: the overflow scrolling was working fine, but for some reason when the text overflowed the font size of the line numbers was oddly reduced and hence no longer aligned with the code.
I realised fairly early on that this was some odd resizing issue due to the
content being too large, and hence presumably an attempt to fit more text into
place getting confused with some of the CSS rules — but no amount of
font-size
, width
, height
or anything else seemed to fix it, even with
!important
littered all over the place.
This threatened to be one of those annoying issues that can be very tough to track down — but luckily for me I stumbled upon the solution fairly quickly. As it turns out, it’s all about how browsers on mobile devices render pages.
The issue with smartphone browsers is that most web content authors didn’t design their content and/or styles to cope with such a small viewport. All kinds of web pages don’t render correctly — the kind of hacks that are required to get cross-browser compatibility almost certainly don’t help, either. As a result of this the browsers use a bit of a trick to get things looking a little more natural.
What they do is render the page to a larger viewport (e.g. 1000 pixels wide) and then scale the page down to fit on the screen. This allows the styles to render more plausibly on most pages, but it does tend to make the text awfully hard to read. This would entail scrolling the screen left/right to read a full line of text which would be a trifle vexing to say the least.
To get around this issue the browsers inflate the text — they scale the font size up so that it becomes legible once again, whilst still leaving all the pixel-oriented sizes intact.
As it turns out, this was happening with my code snippets — but for some
reason a different inflation ratio was applied to the line numbers element
than the code. Once I knew that this was the issue it was quite easy to
fix3 by adding -webkit-text-size-adjust: 100%
to my assorted <pre>
elements — apparently this did the trick as it now
seems to work. Check out that linked page because it’s
got a lot of additional useful details which isn’t Mozilla-specific.
There you are, then — who knew rendering pages on mobile was such a subtle business? Actually, given the usual state of all but the simplest CSS tasks I’m quite surprised it was as straightforward as it was.
I can’t really take either credit or blame for this, it’s part of the functionality provided by the Pygments package that I use for syntax highlighting. The documentation indicates that it’s optional, but I think it’s useful. ↩
sensible, adj.: Any popular web browser which isn’t IE. ↩
Perhaps not fix optimally, but at least fix. Work around. Hack. Whatever you want to call it. ↩