Balance text in web pages

Today we'll set aside LabVIEW for a change and try something with JavaScript. Consider these two headings, which one do you think is better?

Hopefully you will find the second one more appealing to the eye, as me, since the title lines are nearly balanced. If you are formatting a publication by yourself this is easily achieved adjusting the text by hand, but in a web page is difficult.

In fact this was proposed as a CSS standard by Adobe some years ago, as text-wrap: balance property, but W3C didn't adopt it and no web browser that I know of implements it. So we'll have to do it ourselves, and with vanilla JavaScript no less so no external library is needed.

The code

The concept behind our function is to "shrink" left and right borders around the heading just until the text needs another line, and stop there. So basically:

1) Find number of words and lines in the heading.

2) If balancing can be applied, start shrinking borders.

3) Still the same lines? Shrink a little more.

4) Already another line? Go back one step and it's done.


function balance(elemento) //text-wrap: balance;
{
   //Off with the margins
   elemento.style.paddingLeft = 'inherit';
   var w = 1;
   padea(elemento,w);
   var h = elemento.offsetHeight;

   var altura = parseInt(document.defaultView.getComputedStyle(elemento,null).getPropertyValue('line-height')); //May return "normal", so:
   if(isNaN(altura))
      altura = parseInt(document.defaultView.getComputedStyle(elemento,null).getPropertyValue('font-size'));

   var n_lines = elemento.offsetHeight / altura;
   var n_words = elemento.innerHTML.trim().split(' ').length;
  
   if((n_words > n_lines) && (n_lines > 1)) //More words than lines, and more than one line? {
      do{
         w++;
         elemento.style.paddingLeft = w+'px';
         elemento.style.paddingRight = w+'px';
      }
      while(elemento.offsetHeight == h)

      elemento.style.paddingLeft = (w-1)+'px';
      elemento.style.paddingRight = (w-1)+'px';
   }
}

Any modern browser will do the calculations in the blink of an eye.

Implementation

Now it's time to apply our function to the desired elements. The easiest way is defining a general function (let's say balanceAll) that searches for all the occurrences in the page and call the balance function on them.

The specific way of doing it depends on how you decide to mark these headings to be balanced. If it's by CSS class, you can do document.querySelectorAll('.classname'); and if it's by tag, then use document.getElementsByTagName('tagname');

Then you need to call it. My advice is to add a couple of events to the BODY tag: onload, so it will be fired when the page is loaded, and onresize, since a change in the page width could affect our balancing and it's necessary to recalculate it:


<body onload="javascript:balanceAll();" onresize=\"javascript:balanceAll();\">

And that's all. Your particular requirements may vary (what if the heading is not centered but left or right-aligned?), but I'm sure you'll find your way from here 😉.

Comentarios

Entradas populares de este blog

SNMP library for LabVIEW

Base64 Encoding

Retrieve CPU temperature