5

I have a lot of h2 headings in one of my websites. While most of those headings are "balanced" (this is a word I made up, since I have no better way to explain this), some are not balanced and look awful.

This is an example, which should make it clear:

enter image description here

(Arrow shows the orphan word).

As you can see in the image above, the first heading has an orphan word with a long first line, while the second heading is more proportionate.

Is there a way to achieve this effect without having to add <br> tags in my headings?

I know that I could just resize the heading container using a width attribute, but the problem doesn't go away since what I'm trying to avoid is those orphan words.

I'm not even sure if there's a solution to this, but it's something I've been wondering for some time.

  • 1
    While the duplicate solves the problem of "orphaned" words, the question of "balancing" the element makes this a more interesting question, because the last line may have multiple words but still be much shorter than the previous line. I would vote to reopen this question. – Rick Hitchcock Mar 27 '15 at 20:13
  • 1
    Yes, this is actually a different question, since what I want is not only to remove the orphans, but to balance the whole heading. Please re-open this question if possible. Thanks for the info by the way Rick. – Joaquin De La Sierra Mar 27 '15 at 21:04

2 Answers2

1

A possible approach would be to decrease a header's width until its number of lines increases. The width before the number of lines is increased is then the final width of the header. That should make it look "balanced".

Check this working fiddle that contains the code below.

// "Balance" a jQuery element
function balance($elem) {    
    var originalWidth = $elem.width(),
        originalHeight = $elem.height(),
        currentWidth = originalWidth,
        currentHeight = originalHeight;

    // Decrement width until number of lines increases or
    // width becomes 0
    while (currentHeight == originalHeight && currentWidth > 0) {
        $elem.width(currentWidth - 1);
        currentWidth = $elem.width();
        currentHeight = $elem.height();
    }

    if (currentWidth == 0) {
        // Reset width
        $elem.width('');
    } else {
        // Restore width so that number of lines is maintained
        $elem.width(currentWidth + 1);
    }
}
nunocastromartins
  • 577
  • 1
  • 5
  • 11
0

The code below works on a jQuery collection.

For each element in the collection, the width is changed in order to minimize the difference between the widest and skinniest client rectangle (using getClientRects).

The code ensures that the number of client rects does not change. This prevents the element from growing wider or taller.

getClientRects returns a single rectangle for block-level elements. For that reason, the code appends a span to the element to hold its HTML content, and the logic is based on that span's client rects. (The span is then removed.)

function balance(el) {
  el.each(function() {
    var temp= $('<br><span>'+$(this).html()+'</span>').appendTo(this),
        sp= $(this).find('span')[0],
        num= sp.getClientRects().length;

    for(var w=$(this).width(), i=10, best=10, delta=9999 ; i <= w ; i++) {
      $(this).width(i);

      var cr=sp.getClientRects();
      if(cr.length > num) continue;

      for(var min=9999, max=0, j=0 ; j < cr.length; j++) {
        min= Math.min(min, cr[j].width);
        max= Math.max(max, cr[j].width);
      }
      if(max-min < delta) {
        delta= max-min;
        best= i;
      }
    }
    $(this).width(best);
    temp.remove();
  });
};

Working Fiddle

Rick Hitchcock
  • 35,202
  • 5
  • 48
  • 79
  • You should be careful when the element has only one word or you'll end up with a width that is smaller than the word itself. Test your fiddle with a header with one word only (e.g. `

    Header

    `).
    – nunocastromartins Mar 28 '15 at 03:44
  • Excellent point. During the night, I realized that I was over-complicating the problem, because all that's needed is to reduce the width until the height increases. But you beat me to it! You should get the credit, because I can't imagine a cleaner method. – Rick Hitchcock Mar 28 '15 at 10:26