Fit text perfectly inside a div (height and width) without affecting the size of the div

50,270

Solution 1

Here's the same answer, but in Javascript

var autoSizeText;

autoSizeText = function() {
  var el, elements, _i, _len, _results;
  elements = $('.resize');
  console.log(elements);
  if (elements.length < 0) {
    return;
  }
  _results = [];
  for (_i = 0, _len = elements.length; _i < _len; _i++) {
    el = elements[_i];
    _results.push((function(el) {
      var resizeText, _results1;
      resizeText = function() {
        var elNewFontSize;
        elNewFontSize = (parseInt($(el).css('font-size').slice(0, -2)) - 1) + 'px';
        return $(el).css('font-size', elNewFontSize);
      };
      _results1 = [];
      while (el.scrollHeight > el.offsetHeight) {
        _results1.push(resizeText());
      }
       return _results1;
    })(el));
  }
  return _results;
};

$(document).ready(function() {
  return autoSizeText();
});

By the way...if you ever need to convert coffeescript to javascript, just go to js2coffee.org

Solution 2

I was wanting something similar myself recently:

<div class='container'>
    <div class='no-resize'>This text won't be resized and will go out of the div.</div>
    <div class='resize'>This text will be resized and wont go out of the div.</div>
</div>

And

.no-resize, .resize {
    width: 100px;
    height: 50px;
    border: 1px solid #000;
    color: #000;
    float: left;
    margin-left: 10px;
    font-size: 15px
}

Fiddler at jsfiddle.net/mn4rr/1/.

Solution 3

I don't have enough reputation to comment on the accepted answer so I made an answer. If height has a css3 transition on it the autoSizeText() and $.resizeText answers above have issues. I made a short jquery plugin to fix this.

$.fn.resizeText = function (options) {

    var settings = $.extend({ maxfont: 40, minfont: 4 }, options);

    var style = $('<style>').html('.nodelays ' +
    '{ ' +
        '-moz-transition: none !important; ' +
        '-webkit-transition: none !important;' +
        '-o-transition: none !important; ' +
        'transition: none !important;' +
    '}');

    function shrink(el, fontsize, minfontsize)
    {
        if (fontsize < minfontsize) return;

        el.style.fontSize = fontsize + 'px';

        if (el.scrollHeight > el.offsetHeight) shrink(el, fontsize - 1, minfontsize);
    }

    $('head').append(style);

    $(this).each(function(index, el)
    {
        var element = $(el);

        element.addClass('nodelays');

        shrink(el, settings.maxfont, settings.minfont);

        element.removeClass('nodelays');
    });

    style.remove();
}

To use this plugin you only need to call

 $(selector).resizeText();

I hope this saves someone else some time troubleshooting. I wasted a good 20 minutes scratching my head wondering why the code above was causing an infinite loop on my page.

Solution 4

I solved this by making a jQuery plugin, it's here: http://jsfiddle.net/c9YNz/2/ (Updated to deal with resizing windows)

The code for the plugin just shrinks the text down to 0.01em size and then grows it to fit, here's the plugin code:

$.fn.resizeText = function () {
    var width = $(this).innerWidth();
    var height = $(this).innerHeight();
    var html =  $(this).html();
    var newElem = $("<div>", {
        html: html,
        style: "display: inline-block;overflow:hidden;font-size:0.1em;padding:0;margin:0;border:0;outline:0"
    });

    $(this).html(newElem);
    $.resizeText.increaseSize(10, 0.1, newElem, width, height);

    $(window).resize(function () {
        if ($.resizeText.interval)
            clearTimeout($.resizeText.interval)

        $.resizeText.interval = setTimeout(function () {
            elem.html(elem.find("div.createdResizeObject").first().html());
            elem.resizeText();
        }, 300);
    });
}

$.resizeText = {
    increaseSize: function (increment, start, newElem, width, height) {
        var fontSize = start;

        while (newElem.outerWidth() <= width && newElem.outerHeight() <= height) {
            fontSize += increment;
            newElem.css("font-size", fontSize + "em");
        }

        if (newElem.outerWidth() > width || newElem.outerHeight() > height) {
            fontSize -= increment;
            newElem.css("font-size", fontSize + "em");
            if (increment > 0.1) {
                $.resizeText.increaseSize(increment / 10, fontSize, newElem, width, height);
            }
        }
    }
};

Then if you have this html:

<div class="resizeText" style="width:1200px;height:400px;">
Insert text from slipsum here.
</div>

You call it just like this:

$(document).ready(function () {
    $(".resizeText").resizeText();
});

It's not the best way to do it, but it's enough for you to be going on with, I would imagine (plus it works).

Solution 5

Here's a slightly modified version of the given answers.

Requirements :

  1. The class containing text has the "resize" class.
  2. it contains height and width (%, px, whatever...)

What changes in this version ?

  1. I added resizing ( by binding the event resize to the function) autoSizeText. This is far from ideal, but if we don't resize a lot, it should be ok.
  2. In previous versions, text is only getting smaller. Now it tries to find the biggest font without going outside the div.

Note:

I don't claim the code is production ready. But if you find something you can enhance, please share it with the community.

var autoSizeText = function () {
    var el, elements, _i, _len;
    elements = $('.resize');
    if (elements.length < 0) {
        return;
    }
    for (_i = 0, _len = elements.length; _i < _len; _i++) {
        el = elements[_i];
        dichoFit = function (el) {

            diminishText = function () {
                var elNewFontSize;
                elNewFontSize = (parseInt($(el).css('font-size').slice(0, -2)) - 1) + 'px';

                return $(el).css('font-size', elNewFontSize);
            };
            augmentText = function () {
                var elNewFontSize;
                elNewFontSize = (parseInt($(el).css('font-size').slice(0, -2)) + 1) + 'px';

                return $(el).css('font-size', elNewFontSize);
            };


            diminishText();
            while (el.scrollHeight < el.offsetHeight) {
                augmentText();
            }
            augmentText();
            while (el.scrollHeight > el.offsetHeight) {
                diminishText();
            }

        }
        dichoFit(el);
    }
};

$(document).ready(function () {
    autoSizeText();
    $(window).resize(function resizeText(){
        autoSizeText()
    })
});
.sizable{
 width: 50vw;
 height: 50vh;
 border: 2px solid darkred;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

  <div class='sizable resize'>
  I am a sizable div and I have explicit width and height.
</div>
Share:
50,270

Related videos on Youtube

Ben Clarke
Author by

Ben Clarke

Updated on January 14, 2020

Comments

  • Ben Clarke
    Ben Clarke over 4 years

    I apologise in advance as I know this question has come up many times before but I just can't seem to find the right solution (and believe me I've tried a few!)

    Basically it's the old "Fit text perfectly inside a div without affecting the size of the div". And unless I'm a complete numpty, I believe CSS has no way of doing this. So what I mean basically is rather than doing something like:

    #someDiv {
    font-size: 12px;
    }
    

    or...

    #someDiv {
    font-size: 1em;
    }
    

    ...I want to be able to do something like this:

    #someDiv {
    font-size: fluid;
    }
    

    ...meaning that whatever text this div contains, scale it to fit perfectly from left to right and top to bottom with no overflow or whitespace.

    After trawling through countless websites looking for this CSS solution, I've now accepted that CSS isn't capable of this ...so, enter jQuery.

    I've found several jQuery solutions online but they will only scale the text to fit the width, but I want it to scale to the height as well. So effectively I want to say to jQuery:

    "jQuery, find $(this) div and whatever text is inside it I want you to scale it so that it fills the entire height and width of the div as tightly as possible".

    In case I haven't explained myself very well, I've attached a graphic explaining the problem I'm facing and the solution I'm looking for.

    Any help would be much appreciated. Thank you.

    enter image description here

    • Yannick Y
      Yannick Y almost 10 years
      In the case of an overflow, does that mean you would need a scrollbar, or you would resize the text to fit?
    • Maverick
      Maverick almost 10 years
      @YannickY he clearly means to resize the text to fill but not overflow the content div. This is doable, but off the top of my head I can't think of a nice way. If I have time, I'll answer this later for you :).
    • Ben Clarke
      Ben Clarke almost 10 years
      No, scrollbars are part of what I'm trying to avoid. I basically want the text to be as big or small as necessary to fit a given div. No scrollbars. No overflow. No whitespace. Just pure text from top to bottom and left to right. Thanks.
    • Adam Merrifield
      Adam Merrifield almost 10 years
      Is there a minimum or maximum size? is the only thing that's effected the font-size? What about line-height or letter-spacing? What happens if I hit enter after only typing one word? Do you just get rid of enters and only allow inline text? What I'm trying to say is there are SO many different options and things you have to think about in this situation. But if you can give a solid answer for these questions and some more you will be able to do something close to what you want with javascript.
    • Yannick Y
      Yannick Y almost 10 years
      Just wanted to make sure, because then if you have too many characters, Im assuming you will reduce the font size? Then wouldnt the font size be too small at some point?
    • Yannick Y
      Yannick Y almost 10 years
      Im just thinking of logic in regards to the extreme cases, either a few words or too many words (when it comes to resizing the text)
    • Ben Clarke
      Ben Clarke almost 10 years
      Hi @AdamMerrifield. I'm not sure what you mean regarding hitting enter or only typing one word? I'm not referring to a Textbox or some sort of input field. This is static text in div containers. And yes, line-height needs to be considered so this is part of the problem I'm hoping to solve. Thanks
    • Ben Clarke
      Ben Clarke almost 10 years
      Hi @YannickY. I understand what you're saying regarding the font becoming too small at some point. But in the project where I'll be using this solution I know roughly how long the paragraph of text will be so therefore I know that it will never become too small to the point of being unreadable. Thanks
    • Yannick Y
      Yannick Y almost 10 years
      Ok, wanted to clarify those constraints.
    • Chris Heath
      Chris Heath almost 10 years
      Possible duplicate of this
  • Ben Clarke
    Ben Clarke almost 10 years
    Wow, looks good! Really good! Thank you. This could be the solution I'm looking for. But unfortunately (for me anyway) it's written in CoffeeScript which I have no clue about. Would you happen to know how I'd write this in jQuery? Thanks again.
  • Thomas McNaught
    Thomas McNaught almost 10 years
    I used js2coffee.org, so obviously got the same result as joshboley, however I wasn't able to get it to run the same way in the jsfiddle. You may be able to.
  • Roko C. Buljan
    Roko C. Buljan almost 10 years
    "Here's the same answer, but in Javascript" :) wow so we don't have to download the jQuery library! great! Btw... "px" is not needed in jQuery.
  • Ben Clarke
    Ben Clarke almost 10 years
    Looks like this seems to be doing a decent enough job --> http://jsfiddle.net/LrCFY/3/ It might not be perfect but it should do the job for now. Thanks everyone!
  • Ben Clarke
    Ben Clarke almost 10 years
    Thanks. But when I changed the size of the container to a percentage value (important to me for responsive design) it seemed to break it and the text overflowed outside the container? --> http://jsfiddle.net/c9YNz/. This way seems to be slightly more full-proof in my opinion --> http://jsfiddle.net/LrCFY/3/
  • Maverick
    Maverick almost 10 years
    @BenClarke It works for me with percentages (including the fiddle you linked), which browser are you using (I didn't do extensive tests)? I just did a quick test in the latest versions of Chrome, IE and Firefox and it worked ok. Curious to know why it didn't work for you.
  • Ben Clarke
    Ben Clarke almost 10 years
    I'm using the latest Chrome. That's strange then? Here's a screenshot --> Screenshot
  • Maverick
    Maverick almost 10 years
    You might need to click "Run" again. I would guess that this was caused by a window resize (or a CSS edit without clicking "Run"). I'll update the fiddle to resize with the window.
  • Maverick
    Maverick almost 10 years
    @BenClarke Here you go: jsfiddle.net/c9YNz/2 (I also updated the original answer.
  • Maverick
    Maverick almost 10 years
    @RokoC.Buljan javasacript is the language, jQuery is merely a library (an awesome one). The answer this is copied from is in coffee script is a different language.
  • Maverick
    Maverick almost 10 years
    The problem with this solution is that it requires you to manually set the maximum font size in advance in CSS and then it shrinks to fit. IMO that doens't match what was asked for: eg: grow/shrink to fit. I also think using pixels for sizing means you will rarely match closely and using em values would be better.
  • Ben Clarke
    Ben Clarke almost 10 years
    It wasn't caused by a window resize or a CSS edit without clicking Run as it's still happening, even in your updated jsfiddle. See screenshot here. But for some reason when I increase the width from 30% to 50% it works again. See screenshot here. Very strange. Thanks for the effort though.
  • Ben Clarke
    Ben Clarke almost 10 years
    Good points @MrN00b — I totally agree. But unfortunately it's the closest answer I've found that actually works.
  • Maverick
    Maverick almost 10 years
    Very odd, for me it works for every percentage I tried. How peculiar.
  • brasofilo
    brasofilo almost 10 years
    You received a system message about links to JSFiddle, why not comply?
  • Shaakir
    Shaakir over 7 years
    Thanks Kelt. the accepted answer did not work for me. saw no change in text size. your worked well... +1
  • geekTechnique
    geekTechnique almost 5 years
    This is a phenomenal answer that seems to improve greatly on other answers here. However, it seems that the script fails if I restore the window from a maximized state. I have to start resizing the window for the script to activate. Do you know if there is a way this can be modded to achieve that?
  • Nguyên Ngô Duy
    Nguyên Ngô Duy about 4 years
    add some style for perfect work: {overflow-y:scroll; width:100%; max-height:20px; overflow-wrap: break-word;}