Skip to content Skip to sidebar Skip to footer

Changing Text Alignment For Each Line In Multi-line Text

In old newspapers, titles of articles would, if they stretched over three lines, often be centered like this (picture): |RACKET KINGPINS | | ARE ROUNDED UP | �

Solution 1:

You can try looping through all the characters, in each loop, select the current character into a range object, from that you can use getBoundingClientRect() method of the range object to get the bottom of the character rect. It's the way we detect the ending character on each line. Here is the signs to detect the ending character:

  1. If we use normal wrapping, all the lines should break at some space character. The special thing is that in this case, the ending space character will have rect (getting from getBoundingClientRect()) with both top and bottom being 0.
  2. If we use wrapping like word-break:break-all, the ending character may be some other character (not the space character). In this case we will detect the next character following the ending character, the next character will have bottom different from the ending character's bottom.

So it's fairly complicated indeed. In fact at first I thought we had only 1 case (the second case) but if we ignore the first case, we will have unexpected result. So firstly we need to check the first case, then the second case. Now detecting the ending character in each line helps us separate the whole text into separate lines. Then we can wrap each line in a div element with appropritate style set (to align the text in each line).

Here is the demo's code:

HTML:

<h3>Original column</h3><divclass='o-column'>racket kingpins are rounded up in bomb killing</div><h3>Column after adjusted</h3><divclass='column'>racket kingpins are rounded up in bomb killing</div>

CSS:

.column, .o-column {
  width:300px;  
  border:1px solid black;
  margin-bottom:5px;
  text-transform:uppercase;
  padding:5px;    
  font-size:30px;
  font-family:'Arial';
  word-wrap:break-word;
}

JS:

console.clear();
var column = document.querySelector('.column');
var ends = [];
varrange = document.createRange();
range.selectNodeContents(column);
var lines = [];
var lastBottom = null;
//if the innerHTML has some \n character, there will be some unexpected//behavior, all the \n characters should be removed first.
column.innerHTML = column.innerHTML.replace(/\n/g,'');
varlen = column.innerHTML.length;
for(var i = 0; i < len; i++){    
  //set range for current characterrange.setStart(column.childNodes[0],i);
  range.setEnd(column.childNodes[0],i+1);
  var rect = range.getBoundingClientRect();    
  if((rect.bottom == 0 && rect.top == 0) ||
    rect.bottom != lastBottom && lastBottom != null || i == len-1){
    var line = document.createElement('div');
    var lineStart = ends.length ? ends[ends.length - 1] + 1 : 0;
    line.innerHTML = column.innerHTML.substring(lineStart, i == len - 1 ? len : i);
    lines.push(line);
    ends.push(rect.bottom ? i - 1 : i);    
  }
  if(rect.bottom != 0) lastBottom = rect.bottom;
  else lastBottom = null;
  if(ends.length > 3) break;
}

var n = lines.length;
//we align each line only if there are less than 4 linesif(n < 4 && n > 0){
  column.innerHTML = "";    
  for(var i = 0; i < n; i++){
    column.appendChild(lines[i]);
  }
  if(n == 1) lines[0].style.textAlign = 'center';
  else {        
    lines[0].style.textAlign = 'left';        
    lines[n-1].style.textAlign = 'right';
    if(n == 3) lines[1].style.textAlign = 'center';
  }
}

Demo.

Solution 2:

Without JavaScript, you can't.

This is one of the limitations of HTML/CSS. If you need printing capabilities where you control exact position and size of text, use PDF.

Without JavaScript, you can't predict if a paragraph will span multiple lines and how much, simply because a user:

  • May not have the same fonts installed,

  • Or may have configured the text to appear bigger in his browser.

You can, instead:

  1. Add manually the line breaks in a way that in most situations, the width of every line will be inferior to the width of the container,

  2. Forbid line breaks (white-space: nowrap;) and:

  3. Align the three lines according to your needs.

With JavaScript, you may determine where to put line breaks by counting the actual number of lines, and then reducing the text character by character, until you get two lines, then one line, finding this way the exact locations where you may insert line breaks.

I consider it hackish enough, but, well, it's just my opinion. You may, on the other hand, care that changes to user configuration (such as text-only zoom like the one which was used in old browsers) once the page is loaded may break the layout.

Solution 3:

You could create a function to explode the string into an array of chars in javascript and then manipulate the array as needed.

You could make he manipulation easier by using a pr-made "word wrap" function on the string prior to exploding it, so that the title will automatically have \n characters inserted appropriately beforehand according to your max width specification.

Then after exploding you just need to wrap the sections in divs by inserting them in the array at the \n break points and use css classes to line them up as needed.

Then implode the array back into a string...

Post a Comment for "Changing Text Alignment For Each Line In Multi-line Text"