最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Calculate font-size required for text to fill desired space - Stack Overflow

programmeradmin0浏览0评论

How to calculate the font-size required for a text element to fill desired space? For example:

txt = "this text should fill the div precisely"
el = $("<div/>")
    .html(txt)
    .width(200)
    .css({
        fontFamily: "arial",
        fontSize: font_size_to_fit(txt,"arial",200)
    });

Edit: I am asking for a function that calculates the size based in a straighforward mathematical formula. It can be an approximation. The solution proposed on the question above is not correct because it involves an interactive DOM manipulation which is too heavy to be placed in a bottleneck area.

How to calculate the font-size required for a text element to fill desired space? For example:

txt = "this text should fill the div precisely"
el = $("<div/>")
    .html(txt)
    .width(200)
    .css({
        fontFamily: "arial",
        fontSize: font_size_to_fit(txt,"arial",200)
    });

Edit: I am asking for a function that calculates the size based in a straighforward mathematical formula. It can be an approximation. The solution proposed on the question above is not correct because it involves an interactive DOM manipulation which is too heavy to be placed in a bottleneck area.

Share Improve this question edited Aug 2, 2013 at 14:54 MaiaVictor asked Aug 2, 2013 at 14:48 MaiaVictorMaiaVictor 53.1k47 gold badges157 silver badges301 bronze badges 7
  • Make the text in another div/container and check the width until it matches. – NoLifeKing Commented Aug 2, 2013 at 14:50
  • This is a trickier problem than it looks at first, because most browsers enforce a minimum font size. So if you use a loop to continually shrink the font, you also have to test to see if the actual font size is the same as the font size you just specified. If it's not, you've reached the minimum and need to cancel your loop. – Blazemonger Commented Aug 2, 2013 at 14:51
  • I appreciate the input but this is a different situation. On that question it is asked for a method to dynamically fit a text in an element - which is what the solution does, using a while. I am asking for a function that will calculate the required width. My function will be placed in a bottleneck area so it must be a fast mathematical formula, not an iterative DOM manipulation. – MaiaVictor Commented Aug 2, 2013 at 14:52
  • Can you use a monospace font? – James Montagne Commented Aug 2, 2013 at 15:00
  • 1 I think that marking this as a duplicate is missing the ment the OP made. @Viclib is looking for a formula or some other reasonable time algorithm that doesn't simply try many sizes as done in most of the suggestions in this or the remended question. – Scott Sauyet Commented Aug 2, 2013 at 17:05
 |  Show 2 more ments

4 Answers 4

Reset to default 3

I've never tried this, and perhaps it's crazy, but instead of all the (unfortunately unhelpful) suggestions to approach this by changing sizes over and over until the text fits, perhaps you could try just two very different font sizes (using no-wrap, of course) such as 10 and 100 and then interpolate or extrapolate your expected value assuming that the relationship should be nearly linear? I don't know if doing two layouts like this is too expensive for your bottleneck. If so, I'm not sure what hope you really have, as fonts can be tricky. But this might work.

Update: I've created a Fiddle using this technique. It seems to work reasonably well. The relevant code is:

var font_size_to_fit = (function() {
    var $test = $("<span/>").appendTo("body").css({
        visibility: "hidden", 
        border: 0, 
        padding: 0, 
        whiteSpace: "pre"
    });
    var minFont = 10, maxFont = 100; 
    return function(txt, fontFamily, size) {
        $test.appendTo("body").css({fontFamily: fontFamily}).text(txt);
        $test.css({fontSize: maxFont + "px"});
        var maxWidth = $test.width();
        $test.css({fontSize: minFont + "px"});
        var minWidth = $test.width();
        var width = (size - minWidth) * (maxFont - minFont) / 
            (maxWidth - minWidth) + minFont;
        $test.detach();
        return width + "px";
    };
}());

This would probably also need some error-checking to ensure we have no division by zero, which would occur when minWidth == maxWidth, most likely when the text supplied is empty. That's left as an exercise for the reader.

Another update: This broke at some point. I updated the Fiddle to include this:

        return (width - .1) + "px";

This fixes an error noted in the ments. But I have no idea what has changed to make it break in between.

FitText.js is a great jQuery plugin for this.

It will resize fluidly (as the element changes size it will modify the font-size, not just on document ready or load), allows for min and max font sizes, and has some other options to allow you to tweak its behavior.

function font_size_to_fit(text, fontFamily, divSize) {
  var tester = $("<div/>")
  .appendTo("body")
  .css({
    position: "absolute",
    left: "-9999px",
    fontFamily: fontFamily })
  .html(text);

  var width;
  var fontSize = 72;
  do {
    tester.css("fontSize", fontSize);
    fontSize -= 1;
    width = tester.width();
  } while (!(width <= divSize && width >= divSize * .98));
  return fontSize;
}

Maybe something like that? (Note: Doesn't address potential browser minimum font-sizes, didn't want to make the loop too plex.)

(Edited once to fix some potential bugs)

Working Demo

var x = 1;
var y = 20; //staring font-size
txt = "this text should fill the div precisely";
$('#element').html(txt).width(200).height(30).css('font-family', 'arial');
while (x == 1) {
    var element = document.querySelector('#element');
    if ((element.offsetHeight < element.scrollHeight) || (element.offsetWidth < element.scrollWidth)) {
        element.style.background = "yellow";
        element.style.fontSize = parseInt(y) + 'px';
        y--;
    } else {
        x = 0;
        element.style.background = "blue";
    }
}
发布评论

评论列表(0)

  1. 暂无评论