8

I come to you with a tricky question:

Imagine you have the following basic structure:

<div><p>hello</p></div>

Now assume that div has display:block; and width:200px;. Using javascript, how would you check what font-size gives you a 'hello' as big as possible without horizontal overflow (in the case of one word) or jumping to a 2nd line in case of a sentence or group of words?

I can't think of a way to measure the space occupied by text so that it can then be checked against that of the parent container, let alone checking if an element is overflowing or linejumping.

If there is a way, I'm sure this is the right place to ask.

peterm
  • 91,357
  • 15
  • 148
  • 157
Capagris
  • 3,811
  • 5
  • 30
  • 44

5 Answers5

4

Take a look at FitText

It is open source on github as well.

If you are interested in typography you might want to check out their other project called Lettering.js

CTS_AE
  • 12,987
  • 8
  • 62
  • 63
  • I look at their code but what is it exactly they do to check the width of a text element so that it can be compared against its parent element's width? Can Jquery/js measure an element's width based on its font-size just like it would measure a fixed width display block div or whatever? Moreover, can it measure in fixed PX (based on user settings, a % based value?) Last but not least, does it work when the container has a % based value? – Capagris Mar 15 '13 at 01:41
  • [Github - FitText.js](https://github.com/davatron5000/FitText.js) contains all the paramaters you can pass to it and how you can use it As for how they do it: [Source Code](https://github.com/davatron5000/FitText.js/blob/master/jquery.fittext.js) Here's an expanded part of what is actually doing the main work. This part is wrapped in a function call that gets called for the on resize event. They are also pulling in some of their fancy parameter variables, or using defaults. [Expanded Coded](http://pastebin.com/nEuFFkSU) – CTS_AE Mar 15 '13 at 18:49
  • does it allow for vertical limit-checking? I don't think so – Capagris Mar 22 '13 at 19:58
2

There may be a method that's not as crazy, but this should be as precise as possible. Essentially, you have a div that you use to measure its width and incrementally increase the text content until it exceeds the width of the target div. Then, change the target div's <p>'s font size to the measuring div's minus 1:

http://jsfiddle.net/ExplosionPIlls/VUfAw/

var $measurer = $("<div>").css({
    position: 'fixed',
    top: '100%'
}).attr('id', 'measurer');
$measurer.append($("<p>").text($("p").text()));
$measurer.appendTo("body");

while ($measurer.width() <= $("#content").width()) {
    $("#measurer p").css('font-size', '+=1px');
    console.log($("#measurer").width());
}
$("#measurer p").css('font-size', '-=1px');
$("#content p").css('font-size', $("#measurer p").css('font-size'));
$measurer.remove();
Explosion Pills
  • 188,624
  • 52
  • 326
  • 405
  • This changes the height of the element from 20px to 54px changing the line height. – Travis J Mar 15 '13 at 01:27
  • @TravisJ how would you increase the font size without increasing the height? – Explosion Pills Mar 15 '13 at 01:33
  • The font size can be increased only so much before affecting the height (in this example I only found 3px of room for change because of the default line height on a paragraph element). If the height is not an issue, the font size can get to be very large but it will begin to offset a lot of other elements. – Travis J Mar 15 '13 at 01:36
  • Let's assume two scenarios: a) height doesn't matter...but what about linejumping when you have more than one word, or even a paragraph? b) height does matter...how do you make it so that it only grows as big as the height allows? c) for paragraph application purposes, the width would no longer be an issue but rather, the height, you'd want the

    text for example to resize itself based on the parent's height regardless of the width

    – Capagris Mar 15 '13 at 01:44
  • @Sotkra you can perform the same measurement with height if you give `$measurer` a set width. My example uses two words and shows that it does not wrap even though the width is maintained; that was what I thought was the goal. – Explosion Pills Mar 15 '13 at 01:49
  • ok, sorry for the delay in my response: how would you suggest tweaking the above code to make it easy to implement on a wide scale? – Capagris Mar 22 '13 at 19:57
  • @Sotkra what do you mean by a wide scale exactly? This should be fine, but you can parameterize the selectors for `p` and `#content`. – Explosion Pills Mar 22 '13 at 20:00
1

Quick and dirty

fiddle

Set p's style to display: inline then run this

var dWidth = $("div").width();
var pWidth = $("p").width();
var starting = 1;
while (pWidth < dWidth) {
    $("p").css("font-size",starting+"em");
    pWidth = $("p").width();
    starting = starting + .1;
}
SomeShinyObject
  • 7,581
  • 6
  • 39
  • 59
  • would you care to elaborate on the advantages/disadvantages of your method against the others previously posted? – Capagris Mar 15 '13 at 01:49
  • @Sotkra: It uses em vs. px or pt. It requires minimal css alteration from the original requirement. It doesn't involve a new library that you have to learn how to use. – SomeShinyObject Mar 15 '13 at 01:54
  • Can we discuss this over chat? I have plenty of questions which would overflow this comments section. – Capagris Mar 15 '13 at 01:59
  • ? I meant us talking over chat or skype or whatever – Capagris Mar 15 '13 at 02:08
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/26210/discussion-between-christopher-and-sotkra) – SomeShinyObject Mar 15 '13 at 02:13
0

Try this:

Auto-size dynamic text to fill fixed size container

(function($) {
    $.fn.textfill = function(options) {
        var fontSize = options.maxFontPixels;
        var ourText = $('span:visible:first', this);
        var maxHeight = $(this).height();
        var maxWidth = $(this).width();
        var textHeight;
        var textWidth;
        do {
            ourText.css('font-size', fontSize);
            textHeight = ourText.height();
            textWidth = ourText.width();
            fontSize = fontSize - 1;
        } while ((textHeight > maxHeight || textWidth > maxWidth) && fontSize > 3);
        return this;
    }
})(jQuery);

$(document).ready(function() {
    $('.jtextfill').textfill({ maxFontPixels: 36 });
});

<div class='jtextfill' style='width:100px;height:50px;'>
    <span>My Text Here</span>
</div>
Community
  • 1
  • 1
Alex
  • 2,651
  • 2
  • 25
  • 45
  • the geekymonkey plugin is currently disabled due to jquery's plugin page undergoing a revamp. Is the above code the latest version or the old-original? – Capagris Mar 15 '13 at 01:48
0

new jsFiddle Demo (updated 3/22/13)

I would just keep increasing the font size until the clientWidth or clientHeight changed. However, this becomes unreliable when using the actual element itself. To handle that situation, it is possible to create a span on the fly and then monitor the span's dimensions in order to properly retain the actual element's original sizes.

js

var adjuster = document.getElementById("adjust");
adjuster.onclick = function(){
 var p = document.getElementById("p");
 var text = p.innerText;
 var s = document.createElement("span");
 s.innerText = text;
 p.innerHTML = "";
 p.appendChild(s);
 var h = p.clientHeight;
 var w = p.clientWidth;
 var size = 10;
 while(true){
  size++;
  s.style.fontSize = size + "px";
  if($(s).height() > h || $(s).width() > w){
   size-=2;//rollback to no height change
   s.style.fontSize = size + "px";
   break;
  }
 }
 p.style.fontSize = s.style.fontSize;
 p.removeChild(s);
 p.innerText = text;
};
Travis J
  • 81,153
  • 41
  • 202
  • 273
  • @AaronBlenkush - Did you click the button to see it in action? What platform are you using. – Travis J Mar 15 '13 at 01:26
  • I clicked the button and I don't see any change. I'm on the latest normal version of Chrome (Version 26.0.1410.33 beta-m). – Aaron Blenkush Mar 15 '13 at 01:31
  • @AaronBlenkush - Sorry you didn't notice the font changing, would you prefer that I put in alerts to show the exact change? Without changing the position of the element, there is only a slight change, I believe with the constraints of the question it is only 3 px (from 14px or 1em on average, to 17px). – Travis J Mar 15 '13 at 01:33
  • modifying the height to allow the text's font-size to go bigger before forcing/changing height or width...yielded no result – Capagris Mar 22 '13 at 19:54
  • @Sotkra - that is because there was a fundamental flaw in the way that my design approached reading the height and width. Unfortunately, the width was not properly being recognized because overflow allowed it to approach infinity (as in lock up). However! I have fixed this flaw, and now have this rather cool demo: http://jsfiddle.net/vHGBF/1/ . I will post an update. – Travis J Mar 22 '13 at 20:20