38
votes

I need to display user entered text into a fixed size div. What i want is for the font size to be automatically adjusted so that the text fills the box as much as possible.

I'd probably want to start with a maximum font size and while the text is too big to fit the container, shrink the font size until it fits and the font must be displayed as a single line. Is it possible to do this using only css and html.

9
No, it's not possible to do it with CSS only.robertp
can someone provide me with a solution using jsuser2613399

9 Answers

30
votes

Say you have this:

<div id="outer" style="width:200px; height:20px; border:1px solid red;">
    <div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer mollis dui felis, vel vehicula tortor cursus nec</div>
</div>

Then you can do something like:

$(document).ready(function () {
    resize_to_fit();
});

function resize_to_fit(){
    var fontsize = $('div#outer div').css('font-size');
    $('div#outer div').css('fontSize', parseFloat(fontsize) - 1);

    if($('div#outer div').height() >= $('div#outer').height()){
        resize_to_fit();
    }
}

Working Sample

$(document).ready(function() {
  resize_to_fit();
});

function resize_to_fit() {
  var fontsize = $('div#outer div').css('font-size');
  $('div#outer div').css('fontSize', parseFloat(fontsize) - 1);

  if ($('div#outer div').height() >= $('div#outer').height()) {
    resize_to_fit();
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="outer" style="width:200px; height:20px; border:1px solid red;">
  <div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer mollis dui felis, vel vehicula tortor cursus nec</div>
</div>
7
votes

Based on the logic of the top answer here, I created a no-jQuery version,

const input = document.querySelector('input');
const output = document.querySelector('.output');
const outputContainer = document.querySelector('.container');

function resize_to_fit() {
  let fontSize = window.getComputedStyle(output).fontSize;
  output.style.fontSize = (parseFloat(fontSize) - 1) + 'px';
  
  if(output.clientHeight >= outputContainer.clientHeight){
    resize_to_fit();
  }
}

function processInput() { 
  output.innerHTML =this.value;
  output.style.fontSize = '100px'; // Default font size
  resize_to_fit();
}

input.addEventListener('input', processInput);
<input type="text" placeholder="Add text input here" style="margin: 10px; width:50%;">

<div id="outer" class="container" 
style="width:80%; height:100px; border:2px solid red; font-size:20px;">
  
<div class="output" style="word-break: break-all; word-wrap: break-word;">
</div>

</div>
3
votes

Getting the size in pixels of a string of text is a hard thing to do and depends a lot on the browser and the user's settings, so it will probably be hard to come up with a solution that works in all cases.

By "display user entered text" do you mean the user is typing into a textbox? If so, you can attach a keypress listener that checks the length of the value of the text, then adjusts the font-size accordingly. Here's an example, though you will probably need to change the lengths and font-sizes to meet your needs:

Working Demo

$('#text').on('keypress', function(e) {
    var that = $(this),
        textLength = that.val().length
    ;

    if(textLength > 30) {
        that.css('font-size', '5px');
    } else if(textLength > 20) {
        that.css('font-size', '10px');
    } else if(textLength > 10) {
        that.css('font-size', '15px');
    }
});
3
votes

If by text length you mean character count, there is this article which points to a short jquery snippet Change Font Size dynamically based on Character count

http://jsfiddle.net/jfbrLjt2/

 $('.text').each(function(){
 var el= $(this);
   var textLength = el.html().length;
    if (textLength > 20) {
        el.css('font-size', '0.8em');
    }
});
1
votes
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        #div1{
            width: 200px;
            height: 200px;
            font-size: 32px;
            line-height: 1.2em;
        }
    </style>
    <script type="text/javascript" src="js/jquery-1.9.1.min.js"></script>
    <script>
        $(function(){
            n = 1;
            while(n==1){
                n = 0
                if ($('#div1 .holder').outerHeight()>$('#div1').outerHeight()){
                    var fz = parseInt($('#div1').css('font-size'));
                    $('#div1').css({'font-size' : fz-1});
                    n = 1
                } else {n = 0}
            }
        });
    </script>
</head>
<body>
    <div id="div1">
        <div class="holder">I need to display user entered text into a fixed size div. What i want is for the font size to be automatically adjusted so that the text fills the box as much as possible.
I'd probably want to start with a maximum font size and while the text is too big to fit the container, shrink the font size until it fits and the font must be displayed as a single line. Is it possible to do this using only css and html.</div>
    </div>
</body>
</html>
1
votes

Using very little Javascript, you can assign a CSS class with the length of the string, eg: text-length-5 or text-length-20

Then use exclusively CSS to target different font-size according to those class names.

It probably won't work for every case, but it did very well for mine, where the max length was about 10-12 chars.

If you have 100+ or 1000+ chars you can also make a function that receives the length and returns a CSS class, then style base on those ranges.


HTML:

<div class="box">ABC</div>
<div class="box">ABCDE</div>

Javascript (jQuery, but the same idea can be applied to React, or vanilla JS)

$(".box").each((i, el)=> {
  const length = $(el).text().length;
  $(el).addClass("text-length-"+length);
})

CSS:

.box {
  font-size: 16px;
}
.box.text-length-4,
.box.text-length-5,
.box.text-length-6 {
  font-size: 12px;
}
0
votes

Whoever wants a dynamic function that depends on the width of the element (based on putvande answer):

        $(document).ready(function () {
            var arrEl = ['div1', 'div2', 'div3'];
            resize_to_fit(arrEl);
        });

        function resize_to_fit(arr){
            for (var el in arr) {
                var jEl = $('.' + arr[el] + ' span');
                var fontsize = jEl.css('font-size');
                jEl.css('fontSize', parseFloat(fontsize) - 1);
                if (jEl.width() >= $('.' + arr[el]).width()){
                    resize_to_fit([arr[el]]);
                }        
            }
        }

and the HTML:

<div class="div1">
    <span>Lorem Ipsum</span>
</div>
<br/>
<div class="div2">
    <span>Lorem Ipsum 2</span>
</div>
<br />
<div class="div3">
    <span>Lorem Ipsum 3</span>
</div>

whith CSS:

.div1, .div2, .div3 {
    width: 207px;
    white-space: nowrap;
}

Notice you only set font-size to span inside, and not to the outer div.

0
votes

Thanks putvande for letting me know the general method. Here is an improved version.

  1. Get rid of the callback hell.
  2. Fixed some bugs may cause page hang.

Same HTML:

<div id="outer" style="width:200px; height:20px; border:1px solid red;">
    <div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer mollis dui felis, vel vehicula tortor cursus nec</div>
</div>

Here is the function:

resize_to_fit($('#outer'), $('#outer div'));

function resize_to_fit(outer, inner) {
    while(inner.height() > outer.height()) {
        var fontsize = parseInt(inner.css('font-size')) - 1;
        inner.css('font-size', fontsize);
        // some browsers(chrome) the min font return value is 12px
        if(fontsize <= 1 || parseInt(inner.css('font-size')) >= fontsize+1)
            break;
    }
}
0
votes

You can try this one, it's working 100% for me.

  function resize(){
    const isOverflown = ({ clientWidth, scrollWidth, clientHeight, scrollHeight}) => scrollWidth > clientWidth || scrollHeight > clientHeight

    const resizeText = ({ element, elements, minSize = 10, maxSize = 512, step = 1, unit = 'px' }) => {
      (elements || [element]).forEach(el => {
        let i = minSize
        let overflow = false

            const parent = el.parentNode

        while (!overflow && i < maxSize) {
            el.style.fontSize = `${i}${unit}`
            overflow = isOverflown(parent)
            el.style.lineHeight = ((el.style.fontSize).slice(0, -2))*1.2+"px"
          if (!overflow) i += step
        }

        el.style.fontSize = (`${i - step - 1}${unit}`)
      })
    }

    resizeText({
      elements: document.querySelectorAll('.text'),
      step: 0.5
    })
  }
  
    if (document.readyState === 'complete') {
    resize();
  } else {
    window.onload = resize();
  }
<div id="outer" style="width:200px; height:80px; border:1px solid red;">
    <div class="text">Lorem ipsum</div>
</div>

<div id="outer" style="width:200px; height:80px; border:1px solid red;">
    <div class="text">Lorem ipsum dolor sit amet, consectetur adipiscing 
    elit. Integer mollis dui felis, vel vehicula tortor cursus nec.</div>
</div>