jcubic
jcubic

Reputation: 66490

How to calculate number of characters of monospace font that fit into div

I have code like this:

div {
    font-family: monospace;
    font-size: 12px;
    line-height: 14px;
}

$(function() {
    var div = $('div');
    var space = $('<span>&nbsp;</span>').appendTo(div);
    var num_chars = div.width() / space.width();
    var chars = '';
    for (var i=0; i<num_chars; ++i) {
        chars += 'd';
    }
    div.html(chars);
    space.remove();
});

but number of characters is way to small to fill the width of the div. Anyone know how to calculate the number of characters that will fill one line of a div?

Upvotes: 3

Views: 3222

Answers (4)

jcubic
jcubic

Reputation: 66490

My solution that works was using getBoundingClientRect to get real float width of one character and then just use width of the container divided by width of the character:

function get_char_size(div) {
    var temp = $('<span>&nbsp;</span>').appendTo(div);
    var rect = temp.find('span')[0].getBoundingClientRect();
    var result = {
        width: rect.width,
        height: rect.height
    };
    temp.remove();
    return result;
}
function get_num_chars(div, char_size) {
    var width = div.width();
    return Math.floor(width / char_size.width);
}

var container = $('.container');
var size = get_char_size(container);
var chars_per_line = get_num_chars(container, size);

there are two functions because if you don't change font size you can calculate char size only once and second function can use each time you resize the container.

Upvotes: 0

Jukka K. Korpela
Jukka K. Korpela

Reputation: 201568

The problem with the simple approach is that although the advance width of a character is constant in a monospace font, it is generally not an integer number of pixels. It is defined in a much more fine-grained manner in the font file, typically using a unit that is one thousandth of the font size. Browsers deal with this in different ways. The code in the question behaves differently in different browsers.

For consistent results, set up an inline element, insert it inside the div element, and add characters to it until its width exceeds the width of the container; then just remove the last character. This is rather easy in plain JavaScript:

var foo = document.getElementById('foo');
var len = foo.offsetWidth;
var span = document.createElement('span');
foo.appendChild(span);
span.innerHTML = '';
for(var i = 0; span.offsetWidth <= len; i++) 
  span.innerHTML += 'd';
span.innerHTML = span.innerHTML.substring(0, span.innerHTML.length - 1);
span, div {
    font-family: monospace;
    font-size: 12px; /* kept this, though it is irrelevant */
    /* line-height: 14px; omitted here as irrelevant */
}
<div id=foo></div>

Upvotes: 1

Rick Hitchcock
Rick Hitchcock

Reputation: 35670

Here's a general method, which uses getClientRects() to determine when the contents overflow to a new line. normalize() seems to be needed for getClientRects() to function properly.

I'm using word-wrap: break-word to avoid the need for multiple spans.

You can also simplify the for loop by using the Array().join() method I use:

var space = $('<span>').appendTo('div'),
    num_chars;

do {
  space.append('M');
  space[0].normalize();
} while (space[0].getClientRects().length === 1);

num_chars = space.text().length;
$('div').html(Array(num_chars).join('d'));
div {
  font-family: monospace;
  font-size: 12px;
  width: 400px;
  border: 1px solid black;
}

span {
  word-wrap: break-word;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div></div>

Upvotes: 1

Rafael
Rafael

Reputation: 7746

How to Calculate CPL

enter image description here

Use JS to get the width of the div where 75 would become a variable as well as your fontsize and container width. But this is the formula.

  • 75 = Desired CPL
  • 16 = Fontsize
  • 2.28 = Char Constant - In your case this will be the monospace font's char const
  • 526.3158 = PX of container.

Make a function to manipulate this formula to get your answer.

Read more >

Upvotes: 3

Related Questions