Click here to Skip to main content
15,886,578 members
Articles / Web Development / HTML

Dynamic Font Size Using HTML and JavaScript

Rate me:
Please Sign up or sign in to vote.
4.50/5 (5 votes)
8 Dec 2010CPOL5 min read 76.1K   690   15   18
Describes a method to build web pages that provide the ability for the user to change the font size dynamically.
Dynamic Font Size

Introduction

Many web pages can benefit from an ability for the user to change the font size dynamically. This article describes a method to build web pages that provide that functionality using HTML and JavaScript.

Background

Quite often, I find myself using the Ctrl-Plus shortcut (in Internet Explorer) to increase the size of a web page font. Unfortunately, that shortcut increases the size of all web page components (e.g., figures, text boxes, etc.), some of which I do not want increased.

Providing the ability to increase the font size of only selected portions of the web page text requires some relatively advanced JavaScript interaction with the Document Object Model that underlies all web pages. But once mastered, developing the method is relatively straightforward.

Using the Code

The pertinent directory structure of my website is:

GGGustafson
    CSS
      CSS.css
    Images
      favicon.ico
      Lenna.png
      Melitta_teapot.png
      Utah_teapot.png
      ValidXHTML10.png
    Scripts
      control_font_size.js
      cookies.js
      next_page.js
    Default.html

Note that I am hosting my site on Microsoft Office Live (MSOL). MSOL expects web pages to be ASPX or HTML pages. For this article, I will be using an HTML page in the DynamicFontSize downloadable source. However, if the reader uses Visual Studio to build web site pages, choose ASPX pages. Once a new page is defined, you may, if desired, delete the aspx.cs and designer.cs pages that are automatically generated by Visual Studio. You may also change the web page extension from .aspx to .html (replying "Yes" in the following dialog box).

Rename Dialog Box

The variable_font Class

To limit text font sizing to specific HTML elements, we need a mechanism to identify those text elements that we want to allow to be resized. I chose to assign a class named variable_font to each element that was to participate in resizing.

First, in the CSS file, define a selector for variable_font.

CSS
.variable_font
{
    font-size:13pt;
}

This rule assigns the default font size for all elements to which the class applies. Note that the value chosen here should be the same as that chosen for the DEFAULT_FONT_SIZE global variable declared at the top of the control_font_size script.

Then assign the class to each element that will participate in the text font sizing. For example:

HTML
<p class="variable_font" ></p>

This class may be applied to any element that allows a font size attribute (e.g., input, p, td, span, etc.).

Initialization

On window load, the initialize_font_size function must be invoked. For our purposes, I'll simply attach it as the body onload event handler.

HTML
<body onload="initialize_font_size('CSS.css', '.variable_font');">

The initialize_font_size function is found in the control_font_size script:

JavaScript
// ********************************************* initialize_font_size

/// <summary>
///     initializes the variable 'variable_font_rule' to point to the 
///     rule that controls the font size for all elements that are 
///     declared as "class='selector'" in the cascading style sheet 
///     named 'css_sheet_name'; reads a cookie to determine the 
///     current font size; sets all such elements to the default font 
///     size, either read from the cookie or specified by the global 
///     variable DEFAULT_FONT_SIZE
/// </summary>
///
/// <param name="css_sheet_name">
///     a string containing the name of the cascading style sheet 
///     file name, including the extension
/// </param>
///
/// <param name="selector">
///     a the string containing the selector (class name), found in 
///     the specified cascading style sheet; it must include the 
///     selector prefix (i.e., '.' for classes)
/// </param>
///

function initialize_font_size ( css_sheet_name,
                                selector )
{

  if ( document.styleSheets && css_sheet_name && selector )
    {
    var done = false;
    var found = false;
    var i = 0;
    var sheet_rules;
    var sheets = document.styleSheets;
    var the_rules = new Array();

    css_sheet_name = css_sheet_name.toLowerCase ( );

    i = 0;
    done = ( i >= sheets.length );
    while ( ! ( done || found ) )
      {
      var sheet_name = sheets [ i ].href.substring ( 
                         sheets [ i ].href.lastIndexOf ( '/' ) + 1 ).
                           toLowerCase ( );
      if ( sheet_name == css_sheet_name )
        {
        the_rules = sheets [ i ].cssRules || sheets [ i ].rules;
        found = true;
        }
      else
        {
        i++;
        done = ( i >= sheets.length );
        }    
      }

    if ( found )
      {
      found = false;
      
      i = 0;
      done = ( i >= the_rules.length );
      while ( ! ( done || found ) )
        {
        found = ( the_rules [ i ].selectorText.toLowerCase ( ) == 
                  selector.toLowerCase ( ) );
        if ( found )
          {
          variable_font_rule = the_rules [ i ];
          } 
        else
          {
          i++;
          done = ( i >= the_rules.length );
          }    
        }
      }

    if ( variable_font_rule )
      {
      var cookie = read_cookie ( COOKIE_NAME );
      var font_size = DEFAULT_FONT_SIZE;

      if ( cookie )
        {
        font_size = parseInt ( cookie, 10 );
        }
      variable_font_rule.style.fontSize = ( font_size ) + "px";
      create_cookie ( COOKIE_NAME, font_size.toString ( ), 0 );
      }
    }
}

If the document includes at least one CSS style sheet and the two required arguments are provided, the initialize_font_size script:

  • Initializes the global variable variable_font_rule to point to the CSS rule that controls the font size for all elements that are declared as "class='selector'" in the cascading style sheet named 'css_sheet_name' (note that the invoker supplies the actual values for 'css_sheet_name' and 'selector').
  • If the global variable variable_font_rule is successfully initialized (i.e., is not undefined or null), reads a cookie named COOKIE_NAME to determine the new font size. If the cookie does not exist, the new font size is set to the value specified by the global variable DEFAULT_FONT_SIZE.
  • Sets the font sizes of all affected web page elements to the new font size by simply setting the style.fontSize of variable_font_rule to the new font size.
  • Writes the new font size to the cookie named COOKIE_NAME.

The string containing the name of the cascading style sheet file name must include the extension, and the string containing the selector (class name) found in the specified cascading style sheet must include the selector prefix (i.e., '.' for classes).

Mouse Click Resizing

I think that the easiest way to indicate to a user that text resizing is available is to present a visual clue on the web page. To that end, following NPR as a guide, the phrase 'text size' followed by differently sized letter 'A's is used. Additionally, a title that appears when the mouse hovers over the letter is included to make the action taken on a mouse click more obvious.

The HTML that triggers mouse click text sizing (shown to the right in the figure that appears at the top of this article) is encapsulated in a <div>.

HTML
<div class="textsize">
    text size 
    <a class="small" 
       href="javascript:void(0);" 
       onclick="reduce_font_size()" 
       title="Reduce font size">
      A
    </a> 
    <a class="big"
       href="javascript:void(0);" 
       onclick="restore_font_size()"
       title="Restore default font size">
      A
    </a> 
    <a class="bigger" 
       href="javascript:void(0);" 
       onclick="increase_font_size()"
       title="Increase font size">
      A
    </a>
</div>

This font sizing implementation requires three functions, reduce_font_size, restore_font_size, and increase_font_size, all found in the control_font_size script file. All three require that initialize_font_size has been successfully invoked, that is, the global variable variable_font_rule has been successfully initialized. Also, each of these functions requires cookie support found in the cookies script file.

JavaScript
// ************************************************* reduce_font_size

/// <summary>
///     reduces, by one point, the font size of elements that are 
///     declared as "class='variable_font'"


function reduce_font_size ( )
{
  
  if ( variable_font_rule )
    {
    var cookie = read_cookie ( COOKIE_NAME );
    var font_size = DEFAULT_FONT_SIZE;
  
    if ( cookie )
      {
      font_size = parseInt ( cookie, 10 );
      }
  
    if ( font_size > MINIMUM_FONT_SIZE )
      {
      font_size--;
      variable_font_rule.style.fontSize = ( font_size ) + "px";
      create_cookie ( COOKIE_NAME, font_size.toString ( ), 0 );
      }
    }
}

// ************************************************ restore_font_size

/// <summary>
///     restores the font size of elements that are declared as 
///     "class='variable_font'" to the default font size

function restore_font_size ( )
{

  if ( variable_font_rule )
    {
    var font_size = DEFAULT_FONT_SIZE;
  
    variable_font_rule.style.fontSize = ( font_size ) + "px";
    create_cookie ( COOKIE_NAME, font_size.toString ( ), 0 );
    }
}
  
// *********************************************** increase_font_size

/// <summary>
///     increases, by one point, the font size of elements that are 
///     declared as "class='variable_font'"

function increase_font_size ( )
{

  if ( variable_font_rule )
    {
    var cookie = read_cookie ( COOKIE_NAME );
    var font_size = DEFAULT_FONT_SIZE;
  
    if ( cookie )
      {
      font_size = parseInt ( cookie, 10 );
      }
  
    if ( font_size < MAXIMUM_FONT_SIZE )
      {
      font_size++;
      variable_font_rule.style.fontSize = ( font_size ) + "px";
      create_cookie ( COOKIE_NAME, font_size.toString ( ), 0 );
      }
    }
}

The global constants used in the control_font_size script are:

JavaScript
var COOKIE_NAME = "SAVED_VARIABLE_FONT_SIZE";
var DEFAULT_FONT_SIZE = 13;
var MAXIMUM_FONT_SIZE = 24;
var MINIMUM_FONT_SIZE = 8;

The cookies script provides support for the font sizing scripts. A cookie is set to preserve the user's desired font size from web page load to web page load.

JavaScript
// http://www.quirksmode.org/js/cookies.html

// **************************************************** create_cookie

/// <synopsis>
///     create_cookie ( name, value, days );
/// </synopsis>
///
/// <summary>
///     creates a cookie with the specified name, value, and 
///     expiration
/// </summary>
///
/// <param name="name">
///     a string containing the name of the cookie. if a cookie 
///     with the same name exists, it will be overwritten.
/// </param>
///
/// <param name="value">
///     a string containing the value to be assigned to the 
///     cookie
/// </param>
///
/// <param name="days">
///     the cookie expiration, specified in days
/// </param>
///
/// <example>
///     When calling createCookie() you have to give it three 
///     three pieces of information: the name and value of the 
///     cookie and the number of days it is to remain active. 
///     For example, to set a cookie named 'mycookie' to the value 
///     'mycookievalue' and have it active for 7 days, use
///  
///         create_cookie ( 'mycookie', 'mycookievalue', 7 );
/// 
///     If you want the cookie to exist as a session cookie, that is 
///     the cookie is trashed when the user closes the browser, 
///     set the number of days to 0. 
///
///     If you set the number of days to a negative number, the 
///     cookie is trashed immediately.
/// <example>

function create_cookie ( name, value, days ) 
{
  var expires = "";

  if ( days ) 
    {
    var date = new Date ( );

    date.setTime ( date.getTime ( ) + 
                 ( days * 24 * 60 * 60 * 1000 ) );
    expires = "; expires=" + date.toGMTString ( );
    }

  document.cookie = name + "=" + value + expires + "; path=/";
}

// ****************************************************** read_cookie

/// <synopsis>
///     var cookie = read_cookie ( name );
///     if ( cookie )
///       {
///       // do something with the cookie value
///       }
/// </synopsis>
///
/// <summary>
///     reads the value of a cookie
/// </summary>
///
/// <param name="name">
///     a string containing the name of the cookie to be read
/// </param>
///
/// <returns>
///     if the cookie exists, a string containing the value of 
///     the cookie; otherwise, null
/// </returns>

function read_cookie ( name ) 
{
  var cookie = null;
  
  if ( document.cookie.length > 0 )
    {
    var cookies = document.cookie.split ( ';' );
    var name_with_equal = name + "=";

    for ( var i = 0; ( i < cookies.length ); i++ ) 
      {
      var a_cookie = cookies [ i ];

      a_cookie = a_cookie.replace ( /^\s*/, "" );
      if ( a_cookie.indexOf ( name_with_equal ) === 0 )
        {
        cookie = a_cookie.substring ( name_with_equal.length, 
                                      a_cookie.length );
        break;
        }
      }
    }

  return ( cookie );
}

// ***************************************************** erase_cookie

/// <synopsis>
///     erase_cookie ( name );
/// </synopsis>
///
/// <summary>
///     remove the specified cookie
/// </summary>
///
/// <param name="name">
///     a string containing the name of the cookie to be removed
/// </param>

function erase_cookie ( name )
{
  
  create_cookie ( name, "", -1 );
}

The <script></script> blocks that I include to implement dynamic font sizing are:

HTML
<script type="text/javascript" 
  defer="defer" 
  src="Scripts/control_font_size.js"></script>
<script type="text/javascript" 
  defer="defer" 
  src="Scripts/cookies.js"></script>
<script type="text/javascript" 
      defer="defer" 
      src="Scripts/next_page.js"></script>

I place the <script></script> blocks before the </body> tag. I add defer="defer" to the <script> include blocks to ensure that the HTML loads completely before the scripts are loaded. Note that the "defer" attribute of the <script> tag is currently implemented only by Internet Explorer. I expect other browsers to implement this standard attribute in the future. Of course, all of the scripts can be combined into one script file. Then that single script file can be included.

Keyboard Font Sizing

The user may be provided font sizing keyboard shortcuts:

  • '+' - increases font size
  • '-' - decreases font size
  • ' ' - restores font size to default

The shortcuts are processed by the on_keyup event handler found in the control_font_size script file. Again, cookies are used to "remember" the last font size set by the user.

JavaScript
// ********************************************************* on_keyup

/// <summary>
///     event handler that responds to keyup events by determining 
///     what key was released and invoking the appropriate font size 
///     function
///
///       '+' - increase font size
///       '-' - decrease font size
///       ' ' - restore font size to default

function on_keyup ( e )
{
  var code = (window.event) ? event.keyCode : e.keyCode;

  switch ( code )
    {
    case 109 :
    case 189 : // '-'
      reduce_font_size ( );
      break;
    
    case 107 :
    case 187 : // '+'
      increase_font_size ( );
      break;
    
    case 32 :  // ' '
      restore_font_size ( );
      break;
    
    default :  // don't handle it in this module
    
      break;
    }
}

This event handler is registered by attaching it to the document.onkeyup event. In the control_font_size script file, this is accomplished by the statement:

JavaScript
document.onkeyup=on_keyup;

The expiration date of the cookie is set to zero so that the cookie exists only for the duration of the session. The cookies script was developed from JavaScript found at Peter-Paul Koch's cookies web page.

References

Cookie functions contain source code for the cookies script.

Browsers Tested

Internet Explorer Firefox Google Chrome Safari Opera Incompatible

Opera operates somewhat strangely, so I am unwilling to include it as a successfully tested browser.

History

  • 11/15/2010 - Revised article to address reader's comments, to correct typographic and logic errors, and to test the paradigm on common browsers
  • 12/6/2010 - Minor revisions to document; added browser versions of browsers used for testing

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
In 1964, I was in the US Coast Guard when I wrote my first program. It was written in RPG (note no suffixing numbers). Programs and data were entered using punched cards. Turnaround was about 3 hours. So much for the "good old days!"

In 1970, when assigned to Washington DC, I started my MS in Mechanical Engineering. I specialized in Transportation. Untold hours in statistical theory and practice were required, forcing me to use the university computer and learn the FORTRAN language, still using punched cards!

In 1973, I was employed by the Norfolk VA Police Department as a crime analyst for the High Intensity Target program. There, I was still using punched cards!

In 1973, I joined Computer Sciences Corporation (CSC). There, for the first time, I was introduced to a terminal with the ability to edit, compile, link, and test my programs on-line. CSC also gave me the opportunity to discuss technical issues with some of the brightest minds I've encountered during my career.

In 1975, I moved to San Diego to head up an IR&D project, BIODAB. I returned to school (UCSD) and took up Software Engineering at the graduate level. After BIODAB, I headed up a team that fixed a stalled project. I then headed up one of the two most satisfying projects of my career, the Automated Flight Operations Center at Ft. Irwin, CA.

I left Anteon Corporation (the successor to CSC on a major contract) and moved to Pensacola, FL. For a small company I built their firewall, given free to the company's customers. An opportunity to build an air traffic controller trainer arose. This was the other most satisfying project of my career.

Today, I consider myself capable.

Comments and Discussions

 
QuestionAdd extra styles to the resize list Pin
Member 83717803-Nov-11 2:53
Member 83717803-Nov-11 2:53 
AnswerRe: Add extra styles to the resize list Pin
gggustafson3-Nov-11 3:07
mvagggustafson3-Nov-11 3:07 
GeneralRe: Add extra styles to the resize list Pin
Member 837178017-Nov-11 6:16
Member 837178017-Nov-11 6:16 
GeneralRe: Add extra styles to the resize list Pin
Member 837178023-Nov-11 2:57
Member 837178023-Nov-11 2:57 
GeneralMy vote of 5 Pin
Bob@work9-Dec-10 11:04
Bob@work9-Dec-10 11:04 
GeneralRe: My vote of 5 Pin
gggustafson3-Nov-11 3:09
mvagggustafson3-Nov-11 3:09 
GeneralNIce font sizer! Pin
patje9128-Oct-10 22:12
patje9128-Oct-10 22:12 
AnswerRe: NIce font sizer! Pin
gggustafson30-Oct-10 8:17
mvagggustafson30-Oct-10 8:17 
GeneralRe: NIce font sizer! Pin
patje9131-Oct-10 21:49
patje9131-Oct-10 21:49 
GeneralRe: NIce font sizer! Pin
gggustafson16-Nov-10 4:26
mvagggustafson16-Nov-10 4:26 
GeneralRe: NIce font sizer! Pin
patje9117-Nov-10 0:37
patje9117-Nov-10 0:37 
GeneralRe: NIce font sizer! Pin
gggustafson17-Nov-10 6:28
mvagggustafson17-Nov-10 6:28 
Generaldefer Pin
Seishin#10-Oct-10 21:48
Seishin#10-Oct-10 21:48 
AnswerRe: defer Pin
gggustafson11-Oct-10 1:34
mvagggustafson11-Oct-10 1:34 
Generalinteresting approach Pin
HaBiX7-Oct-10 0:09
HaBiX7-Oct-10 0:09 
AnswerRe: interesting approach Pin
gggustafson7-Oct-10 5:44
mvagggustafson7-Oct-10 5:44 
GeneralMy vote of 5 Pin
JackDanyelZ006-Oct-10 19:05
JackDanyelZ006-Oct-10 19:05 
GeneralRe: My vote of 5 Pin
gggustafson1-Nov-10 17:24
mvagggustafson1-Nov-10 17:24 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.