28

Here is the project this is for: http://phlak.github.com/jColorClock/. As you can see, right now the text size is just set to a static size. I'd like the text to always be ~90% of the width of the window but to also scale the vertical size accordingly. Is there a relatively easy way of doing this?

PHLAK
  • 22,023
  • 18
  • 49
  • 52

6 Answers6

48

Hell yeah!

Set your <body> font size when the window is resized with a little javascript. (I've used jQuery for convenience here:

$( document ).ready( function() {
            var $body = $('body'); //Cache this for performance

            var setBodyScale = function() {
                var scaleSource = $body.width(),
                    scaleFactor = 0.35,                     
                    maxScale = 600,
                    minScale = 30; //Tweak these values to taste

                var fontSize = scaleSource * scaleFactor; //Multiply the width of the body by the scaling factor:

                if (fontSize > maxScale) fontSize = maxScale;
                if (fontSize < minScale) fontSize = minScale; //Enforce the minimum and maximums

                $('body').css('font-size', fontSize + '%');
            }

            $(window).resize(function(){
                setBodyScale();
            });

            //Fire it when the page first loads:
            setBodyScale();
        });

Because your font size is set in em's (perfect) adjusting the percentage font-size of the body element acts as a universal 'text zoom'. This will scale any text set in em's - if you want to be more specific, you could set the percentage font-size on a <div> that surrounds just the elements you want to scale.

Here's a quick example: http://www.spookandpuff.com/examples/dynamicTextSize.html

Ben Hull
  • 7,524
  • 3
  • 36
  • 56
  • Would you please explain why you use a font-size of 2em for the h1 tag and why the scale factor is 35%? Thanks! – trusktr Oct 20 '11 at 02:08
  • The font-size of 2em is arbitrary - you can use any starting size you like. Remember, how many pixels 2em is depends on the font-size of the body (which is set as a percentage by the script). The scale factor scales the font height based on the width of the body - you can adjust this value to taste - I just picked it based on trial and error. – Ben Hull Oct 20 '11 at 02:19
  • @Beejamin - When i set font size for body in css then this technique doesn't work – Jitendra Vyas Nov 10 '11 at 04:40
  • The technique relies on the javascript being able to set the font-size property on the body: if your CSS sets the body size, some conflict will happen. Can you post a link to your code? It should be easy to adapt so it still works. – Ben Hull Nov 10 '11 at 11:01
  • @Beejamin Thanks for sharing a lovely code. Just wanted to know how can I use this in multiple elements like `

    ,

    L,

    ` and `

    `. Please dont mind, I am absolutely zero in Javascript. Please Help. I want to use this in my site theme.

    – Vikram Rao Mar 12 '12 at 12:11
  • @Vikram - this code works by setting the font-size of the body element - so, by default, it will affect everything in the page. If you need to only affect certain elements, you can create a jQuery selector to select them, like so: – Ben Hull Mar 12 '12 at 23:27
  • 1
    Change the line `var $body = $('body')` to something like `var $zoomElements = $('h1, h2, h3, p')`, then change the line `$('body').css('font-size', fontSize + '%');` to `$zoomElements.css('font-size', fontSize + '%');` - that will apply the font-size to all of the elements you select. That will be a bit of a weird effect though! – Ben Hull Mar 12 '12 at 23:29
  • @beejamin Is there a way to get this to work with the new rem unit? I'm messing around with it on my site, but so far it's just making a mess. – Kendra Jan 29 '13 at 15:39
  • I think I figured it out...change $('body') to $('html')! It's working on my test site so far. – Kendra Jan 29 '13 at 17:14
  • Hi Kendra, as far as I understand it, it doesn't make much sense to to scale something sized in rem's, unless you're scaling the whole document. As you worked out, a rem (Root Em) is relative to the root element of the page (, not ). So, the only way to scale things that have a size in rems is to change the font-size of the element, which will affect everything in both ems and rems. Can you link me to your site? I'm intrigued! – Ben Hull Jan 29 '13 at 23:53
12

New units were added in CSS3 that will allow you to do this. Sitepoint has a good overview. You definitely want to provide a fallback for older browsers, but this is by far the simplest solution:

font-size: 35vmin;
Stephen M. Harris
  • 7,163
  • 3
  • 38
  • 44
5

Same as Beejamin's excellent answer, with a couple tweaks.

  1. The math was adjusted so that you can set the "default width" at which no scaling will occur. This makes it easier to design to a given width with exact font-sizes.

  2. The font-size is now set on the html element freeing up the body element to hold a font-size in the css.

$(function() {

  // At this width, no scaling occurs. Above/below will scale appropriately.
  var defaultWidth = 1280;

  // This controls how fast the font-size scales. If 1, will scale at the same 
  // rate as the window (i.e. when the window is 50% of the default width, the 
  // font-size will be scaled 50%). If I want the font to not shrink as rapidly 
  // when the page gets smaller, I can set this to a smaller number (e.g. at 0.5,
  // when the window is 50% of default width, the font-size will be scaled 75%).
  var scaleFactor = 0.5;

  // choose a maximum and minimum scale factor (e.g. 4 is 400% and 0.5 is 50%)
  var maxScale = 4;
  var minScale = 0.5;

  var $html = $("html");

  var setHtmlScale = function() {

    var scale = 1 + scaleFactor * ($html.width() - defaultWidth) / defaultWidth;
    if (scale > maxScale) {
      scale = maxScale;
    }
    else if (scale < minScale) {
      scale = minScale;
    }
    $html.css('font-size', scale * 100 + '%');
  };

  $(window).resize(function() {
    setHtmlScale();
  });

  setHtmlScale();
});
Raine Revere
  • 30,985
  • 5
  • 40
  • 52
5

Another option for when you don't need as much precision (say, a couple sizes for different devices) is to use media queries.

sbirch
  • 871
  • 1
  • 10
  • 18
0

If you use jQuery you might want to try FitText. It lets you scale text to the width of the element really easily.

The other option is FlowType.JS which works in a similar way.

Ben
  • 4,301
  • 6
  • 37
  • 61
0
  • With consistent cross browser compatibility
  • Without breaking or disrupting the browser's zoom accessibility.
  • Without altering style attributes.
  • without blurring fonts.
  • Without browser sniffing.
  • Works on OSX maximize and restore.
  • With callbacks to detect browser's zoom level.

Try Mimetic.js

frontsideup
  • 2,833
  • 1
  • 21
  • 23