views:

87

answers:

3

Hi folks,

How do I auto resize the font-size of a <td> if the content goes into second line? I know how to increase/decrease font size using CSS and jquery but how to automatically make the font-size smaller if a particular or all the td's with a specific class name text gets longer then one line.

<div style="overflow: hidden;" id="parentDiv" class="scroll">

 

 <div id="4" >
  <table id="t4" class="Table">
    <tbody>
      <tr>
        <td id="b4" class="bY"><table id="inner1" width="100%" cellpadding="3">
            <tbody>
              <tr>
                <td class="code" id="code4" width="172"></td>
                <td class="Num" id="Num4" width="50"></td>
                <td colspan="2" class="Name" id="Name"></td>
              </tr>
              <tr>
                <td class="code" width="172">&nbsp;</td>
                <td>&nbsp;</td>
                <td class="serial" width="110"></td>
                <td class="serial" width="322"></td>
              </tr>
            </tbody>
          </table></td>
      </tr>
    </tbody>
  </table>
</div>

+1  A: 

You want .filter(). For most elements this should work:

$(".myClass").filter(function()
{
    var el = $(this);
    el.css("white-space", "nowrap");
    var lineHeight = el.height();
    el.css("white-space", "");
    return el.height() > lineHeight;
}).css("font-size", "10pt");

Dealing with tables, all the cells in a row have the same height, so check the value of a child element. Eg, wrap everything in a div. However, if you must act on a <td> directly:

$(function()
{
    $(".myClass td").filter(function()
    {
        var el = $(this);
        el.closest("tr").andSelf().css("white-space", "nowrap");
        var lineHeight = el.height();
        el.css("white-space", "normal");
        var textWraps = el.height() > lineHeight;
        el.closest("tr").andSelf().css("white-space", "");
        return textWraps;
    }).css("font-size", "10pt");
});
gilly3
Hi Gilly, How would this code know that content is moving into the second line?
t3ch
Assuming that the height of one line of text is 20px, if the height of the div is greater than 20px, the text has wrapped. Do you need this to work even if you don't know the height of one line of text?
gilly3
Yes gilly, the most basic req is, no matter what the height is, as soon as the text goes to second line, the font needs to get smaller in order to restrict the content in one line. Current td width is 172 if thats of any help.
t3ch
Thanks for this solution Gilly :) but it would be a pain to do it cell to cell for the entire row :(
t3ch
I don't know if it's any more simple, but if you force the cell to display only one-line of text (`white-space: nowrap`), then check the length of the text-element against the length of the cell, would that make it any easier? Or is it one of those six-of-one/half-a-dozen-of-another situations?
David Thomas
Hey David, give me one minute and I will try your solution.
t3ch
David, tried your suggestion, it works but it pushes the content of next td towards right of the screen.
t3ch
@David - good call. That's simpler.@t3ch - Do you mean that you have straight text inside your table cells, with no containing elements? And you can't change that?
gilly3
@ gilly, David, just to make things simpler for any other person trying for the same problem, I posted the HTML code fragment. I want to make this functionality work for td's with class = code
t3ch
A: 
var newFontSize = 8
if $('td').filter(function() {
    return $(this).height() >  20 
}).css("font-size", newFontSize);

Play with the height > 20 and newFontsize to get what you want.

Roadie57
Thanks folks, I didnt get one thing in here. We are comparing the height with 20? How would the code know that content is going to shift into the second line?
t3ch
20 is arbitrary. You should determine the height of one line, and replace 20 with the actual height of a line. Do you want this two work anywhere, without having to know the height of a line in advance?
gilly3
Sorry didnt look at it in detail. So you are comparing current height ($this.height()) with height????
t3ch
Test to find out what value height jumps to when lines are wrapped.
Roadie57
so heres another question, these td's are generated dynamically and they have different parent div's, so one td's content can be in one line, where as others can be in 2 lines. How to find out those specific td's where content is in 2 lines.
t3ch
That's what the filter function is an attempt to do. But I think it will actually return any other tds in the same row that got taller due to overlength text. but it should not affect tds other than those that height was affected. If you know class or id then add that to the $('td') selection item
Roadie57
@Roadie57 - Each td in a row will have the same height. If only one cell has wrapping text, you don't want to decrease the font of all the other cells in that row.
gilly3
A: 

There isn't a straightforward way to get the width (in pixels) of text content. You can however get a reasonable estimate by multiplying the number of characters by the average pixel width of each character - this will vary depending on the font, and works best for fixed-width fonts like Courier. This also assumes that all the content is simple text without additional formatting.

Most fonts have a character width less than the height, so assuming width = height will definitely work.

Example:

var fontSize = parseInt($('.my-td-class').css('font-size')); // get default font size

function updateFont() {
  var e = $('#some-element');
  while (e.text().length * fontSize > e.width()) {
    fontSize *= 0.8;  // reduce to 80%
    e.css('font-size', fontSize + 'px');
  }
}

Edit: Based on the other answers, you could apply this technique to the height as well. Just make sure that the width/height comparison reflects the current font size and not any hard-coded value.

casablanca
Hi casablanca, will this technique work if I have my font defined in em? Current size is 1em, if content goes to second line, I want to make it 0.8em.
t3ch
@t3ch: I've updated the code so that it gets the default font size when the page is loaded, and scales to 80% whenever the line doesn't fit.
casablanca
@casablanca, thanks. I am confused on one thing. Will this code work on all the td's with a particular class? (I mean to say, it will check through all the td's? if the height is more than one line then make the font smaller, else leave it alone.)
t3ch
Yes, you can run the function any way you want, separately for each `td` if you wish. For example, you could do `$('.some-class').each( ... )` and call the function within `each`.
casablanca