Introducing Responsive Web Typography With FlowType.JS

Advertisement

It’s our great pleasure to support active members of the Web design and development community. Today, we’re proud to present FlowType.JS that allows a perfect character count per line at any screen width. This article is yet another special of our series of various tools, libraries and techniques that we’ve published here on Smashing Magazine: LiveStyle1, PrefixFree2, Foundation3, Sisyphus.js4, GuideGuide5, Gridpak6, JS Bin7, CSSComb8 and Jelly Navigation Menu9. — Ed.

While working on an image-heavy site for Simple Focus, a couple of our designers, John Wilson10 and Casey Zumwalt11, noticed how images always scaled perfectly. Pull the corner of the browser window and the images expand to fill the space. Push back the corner, they shrink and fall into place. The line length of hypertext, on the other hand, changes based on its parent element’s width, which has a negative effect on readability.

“Wouldn’t it be nice,” John asked, “if text worked more like images?” Casey assured him that it could, with a jQuery plugin, if only they could figure out the math.

Fluid Type12
“In a fluid layout, browser width and typographic measure are linked: the wider the viewport, the more characters per line.” – Trent Walton13

Simple Focus14 is mainly a design firm, so like most programming ideas we have, we didn’t do anything with it. Then, a few weeks later, John was rereading Trent Walton’s article about fluid type15 and was inspired to try and figure it out.

An hour later, we had a working prototype and were kicking the tires internally. Within two weeks, FlowType.JS was fully-developed and ready to be sent into the world.

Here’s the process of how we got there:

Technically Speaking

FlowType.JS16, when boiled down, is nothing more than some clever math wrapped in a jQuery plugin, with some options for controlling font sizes to accomplish a certain line length.

Let’s take a deeper look into the code to better understand what’s going on:

The Basic Math

As you will see below, it’s pretty simple stuff. First, we need to measure the width of an element in order to set a base number, which will be the key to the rest of the equation. Then we divide that base by a number that resolves to a reasonable font-size. For example, if an element measures at 1000px and we divided it by 50, we end up with 20px, which is a reasonable font-size.

Line-height is another simple equation based off the font-size. Let’s say we choose a line-height of 1.45 times the font-size for readability. This equation is easy: font-size multiplied by 1.45 equals the recommended line-height.

The Prototype

An initial prototype shows us the idea actually works:

var $width = $window.width(),
    $fontSize = $width / 50,
    $lineHeight = $fontSize * 1.45;

$(window).ready( function() {
  $('element').css({
    'font-size':$fontSize + 'px',
    'line-height':$lineHeight + 'px'
  });
}

$(window).resize( function() {
  $('element').css({
    'font-size':$fontSize + 'px',
    'line-height':$lineHeight + 'px'
  });
});

If you were paying attention, you may have noticed that there’s one major problem with the code: the math is based off of the window’s width, not the element’s width. This causes problems with breakpoints where elements resize to a larger dimension and the text gets smaller while the width of the element became wider.

Improved Code

Revising the code to measure the element’s width instead of the window’s fixed this problem. During this simple update, we also decided to start including options for maximum and minimum thresholds for font-sizes and element width, since a very narrow column would cause the font-size to become too small to read. Read more about these thresholds17.

Sharing the revised code here would make this article entirely too long as it includes several ‘if’ statements as well as duplicate code. Inefficient to say the least. With that said, at least it had options and worked well. But we’re focused on design, remember? So we wanted to get a little advice from some friends before we put something out there that could make us look like noobs.

A Little Help from Friends

Almost ready to launch, FlowType.JS was reviewed by several peers. Dave Rupert18 suggested we make sure it performs well by creating a demo page with several instances and lots of text. We put that together and held our breath, and fortunately it worked very well.

Then we asked Giovanni DiFeterici19 for his feedback. Giovanni surprised us by refactoring and condensing all the ‘if’ statements into two lines of code. In the end, the compressed version of FlowType.JS can be as low as 450 bytes. We also got advice from plenty of other generous friends on everything all the way down to spell checking the demo site.

The Final Code

The final code is phenomenally simple. A few options and variables set simultaneously, a base function called changes where all the magic happens, and two simple calls for changes. One sets the font-size on load and another to recalculate on window resize.

Take a look at the code here:

(function($) {
   $.fn.flowtype = function(options) {

      var settings = $.extend({
         maximum   : 9999,
         minimum   : 1,
         maxFont   : 9999,
         minFont   : 1,
         fontRatio : 35,
         lineRatio : 1.45
      }, options),

      changes = function(el) {
         var $el = $(el),
            elw = $el.width(),
            width = elw > settings.maximum ? settings.maximum : elw  settings.maxFont ? settings.maxFont : fontBase < settings.minFont ? settings.minFont : fontBase;

         $el.css({
            'font-size'   : fontSize + 'px',
            'line-height' : fontSize * settings.lineRatio + 'px'
         });
      };

      return this.each(function() {

         var that = this;
         $(window).resize(function(){changes(that);});

         changes(this);
      });
   };
}(jQuery));

How It Works and Fallback

As you can see, the code applies the newly calculated numbers as inline CSS to the element that is selected. Because this new CSS is inline, it overwrites whatever you have set in your linked stylesheets, creating a natural fallback in case a user has JavaScript disabled.

FlowType.JS Screenshot20

You’ll want to configure the settings based on the font choices you make since the math works out differently based on the size of the font you choose.

Implementation

FlowType.JS was built as a jQuery plugin, so getting started is easy. All you need to do is call FlowType.JS and configure a few settings based on your design.

$('body').flowtype({
 minimum   : 500,
 maximum   : 1200,
 minFont   : 12,
 maxFont   : 40,
 fontRatio : 30,
 lineRatio : 1.45
});

Full instructions are on our demo site21. If jQuery isn’t your thing, one Github community member has already ported it22 to native JavaScript.

Nothing Is Ever Finished

We have more ideas for ways to improve the plugin, but we are treating it as an experiment first and foremost. It solves a common problem in Responsive Design where line-length and line-height aren’t ideal between break points. Regardless, there have been some questions raised about FlowType.JS by many smart developers and designers.

One question that we’ve been asked is centered on typographical theory: should a design start with font-size or element width when optimizing text for legibility? I think the best answer is that it’s a judgement call, that reading the text in your design is the best way to determine what’s most legible. We’ve simply written a tool to help you accomplish what you want with your designs.

Another is about accessibility: doesn’t this tool disable text zoom, thus making sites less accessible? We’re aware of this behavior, but users are able to zoom beyond 200% and see font size increase. For now, simply remember to take your audience into consideration when designing with FlowType.JS.

Remember, like any utility, it’s not a cure-all for the challenges of Web design. We’re just trying to contribute a small idea to the Web design and development community and welcome feedback over at Github.

(il, ea)

Footnotes

  1. 1 http://www.smashingmagazine.com/2013/08/08/release-livestyle-css-live-reload/
  2. 2 http://www.smashingmagazine.com/2011/10/12/prefixfree-break-free-from-css-prefix-hell/
  3. 3 http://www.smashingmagazine.com/2011/10/25/rapid-prototyping-for-any-device-with-foundation/
  4. 4 http://www.smashingmagazine.com/2011/12/05/sisyphus-js-client-side-drafts-and-more/
  5. 5 http://www.smashingmagazine.com/2012/01/03/guideguide-free-plugin-for-dealing-with-grids-in-photoshop/
  6. 6 http://www.smashingmagazine.com/2012/03/19/gridpak-the-responsive-grid-generator/
  7. 7 http://www.smashingmagazine.com/2012/07/23/js-bin-built-for-sharing-education-and-real-time/
  8. 8 http://www.smashingmagazine.com/2012/10/02/csscomb-tool-sort-css-properties/
  9. 9 http://www.smashingmagazine.com/2013/08/15/jelly-navigation-menu-canvas-paperjs/
  10. 10 https://twitter.com/jhnwlsn
  11. 11 https://twitter.com/zumwalt
  12. 12 http://trentwalton.com/2012/06/19/fluid-type/
  13. 13 http://trentwalton.com/2012/06/19/fluid-type/
  14. 14 http://simplefocus.com/
  15. 15 http://trentwalton.com/2012/06/19/fluid-type/
  16. 16 http://simplefocus.com/flowtype/
  17. 17 http://simplefocus.com/flowtype/#options
  18. 18 http://daverupert.com/
  19. 19 http://www.gdifeterici.com/
  20. 20 http://simplefocus.com/flowtype/
  21. 21 http://simplefocus.com/flowtype/#getting-started
  22. 22 https://github.com/simplefocus/FlowType.JS/pull/5

↑ Back to topShare on Twitter

JD runs Simple Focus, a user experience brand firm with offices in Memphis, TN and Portland, OR. A nationally-recognized speaker about web design and user experience, he has written a book, CSS for Print Designers, and serves on the Editorial Review Board for Smashing Magazine.

Advertising

Note: Our rating-system has caused errors, so it's disabled at the moment. It will be back the moment the problem has been resolved. We're very sorry. Happy Holidays!

  1. 1

    A valuable feature would be variable fontRatio parameter, automatically calculated in minFontRatio, maxFontRation range. The narrower the item, the lower the value of the fontRatio parameter. As a result, we get (for example): 45 characters per line in 500px-wide element and 75 characters per line in 1200px-wide element. Setting both parameters to the same value, mimics the current configuration.

  2. 3

    Nicely done. Combined with dynamic image resizing I can keep a coherent layout with smooth scaling within self declared boundaries. This is one of the things I always liked about Flash. Very glad to see it coming to HTML, especially if it can be used and adjusted so easily.

    Thanks a lot!

  3. 4

    I don’t doubt this plugin works great and does as advertised but I just can’t help but be concerned about plugins like this being stacked on top of each other…that’s a lot of Javascript to do little more than make your text the right size. Just seems like overkill. I guess I just can’t see a project where the text size matters so much that JS is the only way to solve the problem. There’s a fine line between using JS when it makes sense and when it’s just hiding bad decisions. I look at the code example above and seem many lines of JS that only adds more to maintenance down the road.

    • 5

      Yeah, I kinda of agree, I cannot imagine a scenario where using this instead of percentages would be beneficial but maybe I’m missing something?

    • 6

      Unsure why you think this plugin is “hiding a bad decision”. There’s no alternative in CSS to do something like this, and it /does/ improve readability. It also saves time so you don’t have to fine tune the font size on every single responsive breakpoint you do.

      Also, have a look at the JS itself: https://github.com/simplefocus/FlowType.JS/blob/master/flowtype.js

      It’s a little over 1kb, which is negligible. Minified with UglifyJS it’s 438 bytes. So that’s not a lot of JavaScript at all.

      • 7

        I don’t think its the javascript (JS) file sizes that some people refer to. Its more to do with the more JS you add to your page.

        Each bit of JS adds more work for the DOM and JS interpreter and browser. Some people don’t have high end computers, and all this client side post-processing adds to the general overhead.

        I’ve never been a lover of just adding different pre/post-processors, JS etc. All I see is adding more work and strain to the browser stack.

  4. 8

    You actually made things a tiny bit harder on yourself by needlessly calculating the line height. The preferred value for line-height is unitless. More info:

    http://meyerweb.com/eric/thoughts/2006/02/08/unitless-line-heights/

    Also I have to agree with the above commenter. If you can’t handle this reasonably with CSS, my guess is your layout is the thing that’s broken.

  5. 9

    Glad to see the often overlooked line-width issue center stage. Personally, I just set sensible (roughly judged according to characters per line) min-width and max-width in ems for fluid elements in my CSS. As screen size grows, I can just bump up the base font-size % to scale everything on the page in harmony.

    On your demo, I only got the font size to grow once I reached 300 % zoom level (on Chrome). That’s a LOT of zoom. When trying to zoom, I suspect users would be likely to think the text is not going to change, and give up trying before reaching the threshold.

    +1 for Maciej Czub’s suggestion.

    • 10

      Henrik,

      Unless I’m misunderstanding, I believe the point of the demo was to use the slider bar to grow the container and subsequently the font-size responds, not to use the browser zoom.

      *Edit: Nevermind, I see now you are pointing out how this script negatively affects the browsers native zoom function by affecting how it handles zooming in with regard to font size.

  6. 11

    Excuse my ignorance but how is this different from http://fittextjs.com

  7. 13

    i had tried flowtype.js on my existing site. But its not working anyway i had followed step by step instruction. Can you share me idea about implementing on existing site.
    Thanks

  8. 14

    Has anyone ever computed the number of different “views” or combinations a web dev has to try to accommodate? It has to be almost infinite. I read this article and thought to myself “why the hell did I choose this as a profession?!” :-)

  9. 15

    Or just do it with css.

    body{
    font-size:16px; /* stone age browser fallback */
    font-size:2vw; /* magic */
    }

    And use em for everything else.

    • 16

      Viewport sizing doesn’t currently seem to work when rotating an iPhone or iPad between portrait and landscape. Probably it should but currently it does’t. Anyway, viewport sizing is also probably something that should only be used on containers alongside media queries. FlowType could still be used inside those containers.

  10. 17

    I think SASS could handle this kinda math quite well.

  11. 18

    This is great. We need tools like this for our everyday work since everything is based on different screen sizes now.. Now I have to remember how to use jQuery again since I’ve moved away from it with html5.

  12. 19

    Leaving behind the question of the fitness of the solution to the problem, I think there is still a small problem :
    In non fixed-width fonts, the width of a character isn’t fixed (thanks Captain Obvious), so the maths to compute the number of characters per line is inaccurate, making the result non-prefect.

    This comment is of course assuming that perfection is the goal, despite the fact that your current solution is good enough for most of the use cases.

    Edit: After some thought, I think that the CSS3 rules like transform (with scale value) can be another solution… but maybe a bit overkill.

  13. 20

    I agree with Raldenhoven in that it doesn’t make much sense to apply the calculations to each individual element. Rather, set the base font size on the body element and use a relative sizing measurement (rem, em, ex, etc) for derivative font styles. However, vw/vh does not enjoy great browser support, so for backward compatibility, I would advise still using Javascript to do the initial calculation for the font size attached to the body. I would also advise having a minimum font size for smaller mobile devices, either through a media query or Javascript.

    I have done something very similar to what I am describing on dragoneyedesign.com, except I am actually using the window height to calculate a reasonable ‘ex’ measurement for the typography on the page. However, this method could work equally with the window width and using derivative ‘em’ measurements.

    Bottom line: I think this is a good idea, but it is overkill. The typography should all be relative to the page’s base font size. That base font can be controlled by some minimal Javascript, or by just using vw/vh if you are only targeting more recent browsers.

  14. 21

    I’m sorry, but I don’t understand the need of smaller fonts on smaller screens.
    If what matters is the user experience if the font is smaller the text won’t be readable on those small screens.

  15. 22

    I want to ask the same – as nobody really got to this point yet just the commenter before me… as I have learned on smaller mobile devices a bigger font size is needed because of the higher resolution of those devices. Wouldn’t this JavaScript alone lead to unreadable text on those devices?

    I see no real advantage about this JavaScript as you can achieve the same with media queries in css – which I would prefer with view on saving as many JavaScript as possible.

    Additionally this is not accessible: when a user can not read standard sized text of 16px very well and sets a higher font size in his browser it is better to use this by setting font-size to 100% in html/ body tag. With this JavaScript his setting is not respected anymore and the webdeveloper thinks he knows better which font size the user needs.

    So I disagree – this JavaScript is a little “Ohhh”-effect on a website but not really more.

  16. 23

    This is great. However, wouldn’t you want bigger text on smaller devices to maintain readability. The demo (http://simplefocus.com/flowtype/) shows the text shrinking as the window shrinks which would create a readability issue for mobile phones.

  17. 24

    Good idea. But how to implement for many browser device has no (old mobile device) or support js ?

  18. 25

    Is it just me, or does it seem less usable to have your text shrink down to a harder to read font-size on small screens? If anything we want fonts to be larger and more legible on those screens. Tweaking your font-size as needed via media queries seems like a better user experience solution.

    But this plugin is still pretty damn cool, just for doing what it does.

  19. 26
  20. 27

    Great Article & developement. This was the biggest issue in responsive layout. Thanks a lot.

Leave a Comment

Yay! You've decided to leave a comment. That's fantastic! Please keep in mind that comments are moderated and rel="nofollow" is in use. So, please do not use a spammy keyword or a domain as your name, or else it will be deleted. Let's have a personal and meaningful conversation instead. Thanks for dropping by!

↑ Back to top