The problem
If you want your text to be resizable in all major browsers, and smaller than the default, you’re probably using em units with values less than 1 in your style sheet, e.g.
p {font-size:0.7em}
As long as you’re careful you've probably got it to work. But then someone complains that they browse the web with IE for Windows set to a text size of ‘Smaller’ and your site is unreadable. You take a look, squint, and despair. You do similar tests on a Mac and in Netscape 6 and despair further. You’re all set to join the pixels-are-the-only-way club.
The solution
This problem bothered me, and I needed a workaround for sites I was developing for myself and in my day job. Using JavaScript I found a solution that, if applied with care, helps make many sites readable no matter what the text size setting.
To see it in action, open up this test page, then make your text size smaller (head for ‘View’-‘Text Size’ in most browsers). Much of the text on the screen should become tiny, possibly unreadable.
To activate the fix, refresh the page. You won’t necessarily get the text back to precisely the size it was originally, but it should be an improvement and keep everything readable.
How it works
Note: the function and sample page use XHTML (served as text/html); the function will still work with HTML 4, but purists may want to switch <br /> to <br> in the function’s document.writeln.
Note that the function below won't work for XHTML pages served as application/xhtml+xml; it should be relatively straightforward to create an alternative version using DOM methods instead of document.writeln though.
To use this fix, simply insert a function call just after the body tag:
…
<body>
<script type="text/javascript"><!--
emsTweak();
//--></script>
…
It can go at the bottom of the page instead, but the user may momentarily see the page with font sizes unadjusted just before the fix kicks in.
The function can be placed either in the head of the page or in an external .js file:
function emsTweak()
{
if ((document.createElement) && (document.createTextNode))
{
document.writeln('<div id="emsTest" style="position:absolute; visibility:hidden; font-family:arial,helvetica,sans-serif"> <br /> <br /> <br /> <br /> <br /></div>');
var scaling=100;
if ((navigator.platform=="Win32") && (navigator.appName=="Microsoft Internet Explorer")) scaling=105;
var h=999;
if (document.getElementById('emsTest').clientHeight) h=parseInt(document.getElementById('emsTest').clientHeight);
else if (document.getElementById('emsTest').offsetHeight) h=parseInt(document.getElementById('emsTest').offsetHeight);
if (h<85) document.body.style.fontSize=Math.round(scaling*90/h)+"%";
}
}
The fix only works in modern, DOM-capable browsers; detection is taken care of by the first if statement. So far it’s been tested in Win IE5/5.5/6, Mac IE5 and Netscape 6.
A hidden div containing a few lines of text is written into the page. Its height is then measured, and if it’s too small the font size applied to the body tag is increased to compensate. An extra 5% is added for Win IE just to nudge it into being more accurate (you may not find this necessary).
All font sizes within the page must be in ems. You may get it working without problems simply by leaving the body tag without any font size set, but it’s more likely you’ll need to set it to 100%, along with font-size:100% for table, td and th if they have no existing font size, e.g. with the following in the style sheet:
body,table,td,th {font-size:100%}
See below for an explanation of this seemingly needless CSS.
Bugs, quirks and workarounds
OK, now for the bad news. It isn’t always possible to get this fix to work properly in all browsers for a particular site. The problems arise from strange and inconsistent behaviour in various browsers.
Tables are a real headache. If text within table cells is also within another tag which handles its formatting, e.g.
…
body, table, td, th {font-size:100%}
td {}
p {font-size:0.8em}
…
<td>
<p>Goodbye cruel world</p>
</td>
…
then as long as the font-size:100% bodge is there it all works OK. Without it Win IE fails to resize any text within tables; with it text is resized by a lesser amount when the ‘Text Size’ setting is altered (smaller text isn’t so small, larger not so large). I haven’t a clue why this is.
If text is instead formatted by the td/th (not wrapped in a paragraph) then it seems to stubbornly refuse to resize at all in Mac IE and I've not yet found a workaround (I’ve had a report that wrapping the text in a span gets around this problem). Nested tables can get yet more complicated.
Summary
This fix should be suitable and work OK if…
- The site uses ems for font sizing, with one or more pieces of text set to <1em.
- You insert the function call just after the
bodytag. - You insert the function into the head or external
.jsfile. - In your style sheet you apply
font-size:100%to thebody, and totable/td/thif required, and ensure your use of tables allows the fix to resize the text. - You’re serving pages as
text/html, or have modified the code.
It won’t work for every site or browser, and relies on JavaScript being enabled, but it’s allowed me to use ems rather than pixels for a few sites already. If you discover any improvements or additional workarounds let me know and I’ll see if I can improve the code.
The original version of this article was published over at The Noodle Incident.
Please note: although updated since then, it hasn’t been tested/updated recently to confirm compatibility with the latest browsers.
Although this script is still a useful safeguard for sites making extensive use of small text, in many cases it’s sufficient to just apply html, body, table {font-size:100%} . This slightly restricts resizing in Windows Internet Explorer, often keeping small text legible at the ‘Smaller’ setting.
