So… the site I’m working on has one of those “increase text size” controls. On this project it’s turned out to be one of those features that shows up in comps and somehow falls through the cracks until later on in the project cycle. Situation normal, really, as it isn’t a big feature. It’s just one of those things that needs to be buttoned up before the site can go live.
Anyway, I was thinking about how to do implement it the other day. I haven’t done one of these in a long time and the only other time I did one it involved crafting separate, albeit small, style sheets for the larger text sizes. I didn’t want to go that way again. Basically, I just didn’t want to write new style sheets- even small ones.
What’s a fella to do?
zoom
So, thinking about it a little bit, I seized upon using the non-standard CSS zoom
property. Supported in Internet Explorer (zoom:1
is often used for a hasLayout toggle) and Webkit browsers, it would represent a simple (1 line!) CSS solution to this problem. It’s also one that I like better aesthetically as the site looks the same, just bigger. I figure there’s a reason all browsers have moved to this behavior when hitting ctrl+
.
The problem was figuring out an equivalent for FireFox and Opera which don’t support zoom
Enter CSS 2D Transform
A little searching and experimenting later I came up with the idea of using CSS Transforms and the scale
value to approximate zoom in browsers that lack support.
Let’s see how I did it.
As you go through the following keep in mind this hasn’t actually gone through testing yet so something weird could yet shake out. I just wrote this code yesterday, so you guys can be my sanity check.
Also, is anyone else doing this?
Here’s the markup. We had this done weeks ago.
<!-- yes, we get the gas face for href="#" I don't like them either. I'll rewrite it to use just LIs, I swear. --> <ul id="font-size"><li class="text">Text Size:</li> <li><a href="#" class="default">default font size</a></li> <li><a href="#" class="larger">larger font size</a></li> <li><a href="#" class="largest">largest font size</a></li> </ul>
The first thing I did was write a small chunk of code that runs on $(document).ready()
(yes, this is a jQuery project.)
//using the jQuery cookie plugin to get a pre-set value; var fontSize=$.cookie('font_size'); //if it exists, set the body.className right now //and... //the user gets their size of choice right away if (fontSize) { $(document.body) .removeClass("largest larger default") .addClass(fontSize); } $("#font-size li a").click( function(e){ var $body = $(document.body), newClass = this.className; //if it doesn't already have the chosen class if (!$body.hasClass(newClass)) { //clear any old ones and add the new one $body .removeClass("largest larger default") .addClass(newClass); } //saving the choice in a cookie $.cookie('font_size',this.className); //and finally, stop the clicks e.preventDefault(); } )
Cool. So far so good. We’ve got classes on the body indicating how big the user wants to see the site.
Before we look at the CSS, there’s one more bit of JavaScript we need to look at as I almost immediately envisioned a problem with the above scenario.
If i was using CSS Transforms to scale the pages in Firefox and then Firefox eventually implemented zoom
, things would get wonky. We don’t want that. I had to future-proof the code a little bit.
So, what I needed was a test for the presence of a valid zoom
CSS property. Turning to Modernizr (since it was already in use on the site) I used the handy Modernizr.addTest method to test for zoom. Here’s the one I cobbled together.
Modernizr.addTest('zoom', function () { //create a div var test = document.createElement('div'); //if there's a valid property in the browser //it will return "" //undefined means the browser doesn't know //what you're talking about if (test.style.zoom === undefined) { delete test; return false; } delete test; return true; });
And finally, we’ve got the style sheet.
/* we add a .default class, so we can reset the page with the mechanism defined above */ body, body.default { font:13px/1.231 arial, helvetica, sans-serif; color:#222; background:url(images/page-bg.jpg) center repeat-y; min-width:960px; overflow-x:hidden; } /* here's our class for browsers without a zoom property, this sets the transform's origin. In this case it defines the point from which our scale will happen. We want it to row from the center and from the top, so 50% and 0 it is. */ .no-zoom body { -o-transform-origin:50% 0; -moz-transform-origin:50% 0; } /* classes for browsers with zoom */ .zoom body.larger { zoom:110%; } .zoom body.largest { zoom:125%; } /* and classes for browsers that don't support zoom */ .no-zoom body.larger { -o-transform: scale(1.1); -moz-transform: scale(1.1); transform: scale(1.1); } .no-zoom body.largest { -o-transform: scale(1.25); -moz-transform: scale(1.25); transform: scale(1.25); }
And that’s that. Here’s a quick demo to see it in action. You can also view source here.
Performance
I did a quick V8 Benchmark comparing scaled/zoomed performance in several browsers to see if there are any issues. The following table shows that there really isn’t much difference. Clearly this isn’t a definitive test as it’s only a small run of tests in one benchmark on one machine, but it was nice that nothing shook out in this first pass. I’m going to look at doing a DOM heavy test as well as something with some animation (maybe even Canvas?)
Browser | no zoom/scale | zoom:1.5 | transform:scale(1.5); |
---|---|---|---|
Chrome 8.0.552.215 | 5587 | 5642 | 5782 |
Firefox 3.6.13 | 594 | NA | 653 |
Internet Explorer 8 |
117
|
120
|
NA |
Internet Explorer Platform Preview version 1.9.8023.6000 |
2243
|
2280
|
2292
|
Safari 5.03 | 2839 | 2874 | 2796 |
Opera 10.63 | 4071 | NA | 4110 |
I kind of like it.
This is pretty slick! Thanks for the concept.
thanks, it was a fun spot in an otherwise dull project.
I need your help David your script I used and it works great. I just used it on images instead and went with default and largest text size.
It works great on all the pages except the tech talk pages. Do you think my custom script is blocking something out?
http://www.besttechnology.org/techdetail/pd1_3_2010.php
Not sure who David is, but I’ll take a look later to see if I can figure out what’s going on.
Sorry about calling you David. I meant to say Rob. Thanks I look forward to your reply.
No worries. It looks like you’ve included a second, much older copy, of jQuery on the page after the zoom scripts. there’s a lot going on on that page, but that’s potentially a problem.
Hi, the zooming works great but there is an issue in all browsers. When you click the zoom button, the font and image sizes increases as expected but the text do not get wrapped to the next line when needed and a horizontal scrollbar is not displayed. So, basically, the user cannot see part of the screen.
Thanks! Works perfect!
There is problem with these solution when absolute position objects attached to the body.
these objects loosing the absolute position OR more accurate the loose his center.
SEE:
http://jsfiddle.net/zachsigal/54oLqrcz/
Zach
See solution for absolute position elements fix:
http://jsfiddle.net/zachsigal/54oLqrcz/6/