Adding a text size widget to your site using CSS and Sass

Luke Canvin

A requirement we hear from many of our Government customers is that a sizable number of their users with sight impairment prefer to have a text size widget on-screen when they browse a website.

These accessibility widgets are tough to implement cleanly using HTML and CSS but the advent of CSS preprocessors such as Sass and LESS make the job much easier. In this post we’ll see how we can use Sass to create a text size widget.

What we’re aiming for is the standard row of “A” characters increasing in size to denote changing the text size on the page, like this: Screenshot showing three A characters of increasing size. – you can take a look at one in action on one of our sites.

What we will aim to do is add a class (small/medium/large) to the body element of the page, which we can then refer to in CSS to say: when the body has a class of small then the font-size should be x; when medium then y; large then z.

There are two elements to making the widget work:

  1. JavaScript that adds the widget to the page, records the setting in a cookie, and adds a class to the page body so that our CSS can react to it.
  2. CSS that sets the font-size based on the body class. A Sass mixin makes this much more manageable.

JavaScript

Here’s the code, and we’ll go through it bit-by-bit:

$(document).ready(function () {
    // Add in the widget
    $('#text-size-widget').append('<ul><li class="small"><a href="#" class="selected">A</a></li><li class="medium"><a href="#">A</a></li><li class="large"><a href="#">A</a></li></ul>');
    
    // Read the current text-size from a cookie
    if ($.cookie('TEXT_SIZE')) {
        var cookieTextSize = $.cookie('TEXT_SIZE');
        $('body').addClass(cookieTextSize);
        $('#text-size-widget a').removeClass('selected');
        $('#text-size-widget li.' + cookieTextSize + ' a').addClass('selected');
    }
    
    // Add the resize event handler to the widget's links
    $('#text-size-widget a').click(function () {
        var $el = $(this);
        var textSize = $el.parent().attr('class');
        $('body')
            .removeClass('small medium large')
            .addClass(textSize);
        $('#text-size-widget a').removeClass('selected');
        $el.addClass('selected');
        $.cookie('TEXT_SIZE', textSize, { path: '/', expires: 10000 });
        return false;
    });
});

We’re using jQuery here so the first line sets this script to run when the page is loaded and ready.

We then add in the HTML for the widget, by inserting a list of links into any element on the page with an id of text-size-widget, so you’ll need to have at least one of those in your page. We insert this using JavaScript so that if a user doesn’t have JavaScript enabled they won’t find a non-functioning list of links on their page.

We then check to see if the user has a cookie called TEXT_SIZE, if they do we read it, add the appropriate class to our body element, and refresh which of our “A” links is selected. This makes sure that the user’s choice carries over from page to page on our site.

Finally we set what happens when the user clicks one of the “A” links:

  • We detect which link they clicked and store the small/medium/large class in a variable to use later
  • We remove whatever text size class might be on the body currently and set the new one
  • We update which of the “A” links is selected
  • We store the new text size in the TEXT_SIZE cookie
  • We return false so that the link does not perform its standard functionality (in this case adding “#” to the URL)

That’s the widget, cookie and body classes dealt with, now to tell the CSS how to handle it.

CSS

What we’re looking to end up with is along the lines of:

p { font-size: 10px; }
body.medium p { font-size: 12px; }
body.large p { font-size: 14px; }

Clearly it would be massively frustrating to have to write all three options out every time you wanted to set the font-size of something – this is where our Sass mixin comes in.

Mixins let you extract repetitive code out of your CSS into something that looks a bit like a function (you can even pass in values/settings) and call from your CSS whenever you need it.

Here’s what our mixin looks like:

@mixin font-size($baseFontSize, $mediumMultiplier: 1.2, $largeMultiplier: 1.4) {
    font-size: $baseFontSize + px;
    body.medium &    { font-size: ($baseFontSize * $mediumMultiplier) + px; }
    body.large &    { font-size: ($baseFontSize * $largeMultiplier) + px; }
}

The mixin is called font-size and you pass in the “base” font size (i.e. the size to use for the smallest setting, which is the default), and optionally you can set the multipliers we use to go up to the medium and large sizes.

We’ve then got a bit of Sass code that generates our CSS using the base font size and the multipliers.

Of course if you prefer to use ems or another unit you can replace the px with whatever you want.

To use this mixin all we need to write is:

p {
    @include font-size(10);
}

And when we compile the Sass it will generate exactly what we want. So all we need to do is replace any normal font-size declarations with a call to our new mixin and we’re away!