18

I have a span inside of a div and the div must remain 200px wide and the text must fit on one line within the div. The text within the span is dynamically generated so I can't possibly know which content will break to a new line and which will not.

<div style="width:200px">
  <span style="font-size:12px;">This sentence is too large to fit within the div.</span>
</div>

If I use the CSS property white-space:nowrap; the words will spill to the outside of the div, which of course, we don't want.

How would I reduce the font-size (or zoom) based on if the line breaks or not? I would prefer a CSS answer, but I understand if that is outside of CSS's abilities.

captainsac
  • 2,484
  • 3
  • 27
  • 48
ExcellentSP
  • 1,529
  • 4
  • 15
  • 39
  • 1
    What is the reason for wanting to make it all on one line? – Shan Robertson Feb 12 '15 at 18:48
  • 1
    You may want to have a look at a third party lib such as fittext http://fittextjs.com/. As an alternative, you can use `overflow: hidden; text-overflow: ellipsis` to force the text have ellipsis and not spill outside the div http://www.w3schools.com/cssref/css3_pr_text-overflow.asp – floribon Feb 12 '15 at 18:51
  • http://stackoverflow.com/questions/687998/auto-size-dynamic-text-to-fill-fixed-size-container – A. Wolff Feb 12 '15 at 18:54
  • It needs to be on one line so it doesn't mess with the design of the page @ShanRobertson. – ExcellentSP Feb 12 '15 at 19:18
  • All of the text must be fully visible as this is critical information for the users @floribon. And a plugin just won't do, the page already takes more time than I want it to to load, so I don't want to make any calls to anymore libraries. – ExcellentSP Feb 12 '15 at 19:18

4 Answers4

14

One fairly nasty way: loop decreasing the overflowing span until its less that the div width;

var divWidth = $("#theDiv").width();
var text = $("#text");
var fontSize = 12;

while (text.width() > divWidth)
  text.css("font-size", fontSize -= 0.5);

text.css("display", "inline");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="theDiv" style="width:200px; border:1px solid red;">
  <span id="text" style="display:none;white-space:nowrap;">This sentence is too large to fit within the div.</span>
</div>
Unmitigated
  • 76,500
  • 11
  • 62
  • 80
Alex K.
  • 171,639
  • 30
  • 264
  • 288
5

I would suggest reading up on CSS viewport units. That is probably as close to a good solution as you'll find in pure CSS.

1vw = 1% of viewport width
1vh = 1% of viewport height
1vmin = 1vw or 1vh, whichever is smaller
1vmax = 1vw or 1vh, whichever is larger

http://css-tricks.com/viewport-sized-typography/

hopkins-matt
  • 2,763
  • 2
  • 15
  • 23
  • 2
    But that's relative to viewport, not specific element. Not sure it is or not what would expect OP – A. Wolff Feb 12 '15 at 18:52
  • True, but that is the only dynamically resizing CSS unit. If he sets a static viewport width, he may be able to account for a large percentage of the content possibilities. A JS solution would accommodate the edge cases. http://stackoverflow.com/questions/14431411/pure-css-to-make-font-size-responsive-based-on-dynamic-amount-of-characters – hopkins-matt Feb 12 '15 at 19:03
  • This site is responsive, and it needs to be as backwards compatible as possible. – ExcellentSP Feb 12 '15 at 19:22
1

A very specific case- if you have fixed div size and are using Angular.js:

  1. define a function that will test if there is a word that will be wrapped (because you know how many characters a line can take) and return a string to specify a css class that has a smaller font size:

    $scope.longWordSubstepTitleResize = function(title){
        var longestWord = title.split(' ').reduce(function(longest, currentWord) {
            return currentWord.length > longest.length ? currentWord : longest;
        }, "");
        if (longestWord.length>13){
            return "long-word-title";
        }else{
            return;
        }
    
    }
    
  2. In your template, add a css class that will call this function you defined and so your class, "long-word-title", can be applied where needed:

    <div class="noselect sub-step-title {{longWordSubstepTitleResize(title)}}">
    
  3. Add css rule for smaller text to your stylesheet

Michael Discenza
  • 3,240
  • 7
  • 30
  • 41
0

try this and add text to see the result

<HTML>
<HEAD>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script type="text/javascript">
  $(document).ready(function(){
    var count = $("span").text().length;
    var y = 1000/count ;
    $('span').css('font-size',y);

  });


</script>
</HEAD>
<BODY>
   <div style="width:200px; border:1px solid black;">
<span style="font-size:12px;">This sentence is too large to fit within the div</span>
</div>
Tahmasb
  • 41
  • 7