15

I have a span with CSS:

font-height = 120px; 
height = 120px;
line-height = 120px;

The text within it does not occupy the complete height(120px) of the span. Is there any way to calculate the offset of the text within the span from upper and lower boundaries?

Or is this an way to make the text touch the upper and lower boundaries of the enclosing span tag?

jsFiddle Link for reference.

Manu
  • 609
  • 8
  • 18
  • 4
    I think this is font-specific; `font-size:120px` does not necessary mean a letter will take up full 120px height/width. http://jsfiddle.net/jTpfT/2/ – Passerby Jan 23 '13 at 04:17
  • Right. But is there any way to calculate this offset? – Manu Jan 23 '13 at 05:27
  • I don't think so, unless you're targeting the exact font. – Passerby Jan 23 '13 at 07:50
  • 1
    This is potentially possible with WebGL or the Canvas tag by rendering a canvas and then by doing a looping check of pixel colors; check if row1 contains a non-white pixel, then moving to row2 etc. See http://stackoverflow.com/a/1936084/694325 . I didn't want to add as answer because this is so vague and might not work for you. – Joel Peltonen Jan 28 '13 at 08:18

5 Answers5

6

This visually does it without javascript:

#abc {
    margin: none;
    border: dotted 1px red;
    padding: 0;
    height: 120px;
    font-size:180px;
    line-height:120px;
    display:inline-block;
}

I think you need to use display:inline-block; and adjust the font size according to the actual font you use.

JsFiddle here

frenchie
  • 51,731
  • 109
  • 304
  • 510
  • This is the answer. Also, web typography is far from perfect. And even desktop typography has similar quirks. So this is a good solution, but don’t think it will mean every font on every browser will behave as expected. – Giacomo1968 Jan 28 '13 at 18:08
  • 1
    @JakeGould: true, I think if what's important is the actual rendering then the other way of doing it, which I think would be less optimal, would be to use an image and handle the problem in Photoshop. But I prefer doing it in HTML/CSS! – frenchie Jan 28 '13 at 18:10
  • How do you think this offset can be calculated? ie: 120px for 180px? – Manu Jan 30 '13 at 07:10
  • I don't think it can; I don't think that's the way to do it. Unless your user can change the font, you shouldn't need to. Keep it simple. And if indeed the font changes because you've got to handle multiple devices then determine what the values are for each of these scenario and use some jQuery to set the font size. For instance, set height:120px; font-size:180px; line-height:120px; for desktop and set height:XYZpx; font-size:XYZpx; line-height:XYZpx for mobile. In any case, you shouldn't be calculating these values at runtime because typography isn't reliable in terms of actual dimensions. – frenchie Jan 30 '13 at 18:39
  • You are right that web typography is not reliable. Each font leaves different offsets for different fonts. Your solution will not serve my purpose. – Manu Jan 31 '13 at 18:06
  • But how many fonts does your design use??? Set the element to a specific web font and you're done! I learned that if what you're trying to do seems really hard to do then you're probably doing it wrong; that's just my experience. – frenchie Jan 31 '13 at 22:09
6

The text is already taking 100% (120px) of the span height, you're forgetting other characters like "j" or "Á".

enter image description here

Try this html:

<span id="abc">jÁ / ABC</span>

and this css

#abc {
    margin: none;
    border: dotted 1px red;
    padding: 0;
    display:inline-block;
    /*****120px*****/
    height: 120px;
    font-size:120px;
    line-height:120px;
}

Test: http://jsfiddle.net/jTpfT/17/

karacas
  • 2,054
  • 1
  • 19
  • 29
  • I agree that the FONT is taking the complete height. But for regular characters, eg: A, the offsets left at both top and bottom are different for different browsers. So either I need a way to make them equal, or find a way to calculate those offsets for different browsers. – Manu Feb 07 '13 at 06:09
  • I make a little script for that, see in another answer. – karacas Feb 07 '13 at 13:30
4

UPDATE

I wrote a little script to automatically readjust the font-size, all you need to do is manually adjust the ratio between the total height of the font-family total size and font-family uppercase size.

Check the script: http://jsfiddle.net/jTpfT/32/


JS:

/**
 * Calculate the ratios by hand and store in this variable form:
 * myfontlowercase + _upper_case_ratio
 */
 var georgia_upper_case_ratio           = 1.44
 var arial_upper_case_ratio             = 1.32
 var times_upper_case_ratio             = 1.48

 /********************************************/

 $(document).ready(function() {
    $(".fitTextHeight").each(function(){
        //Get font family
        var ff = $(this).css('font-family').toLowerCase().split('\'').join('').split(' ').join('');

        //get ratio
        var miRatio = 1;
        try {miRatio = eval(ff+ "_upper_case_ratio"); } catch (e) { }

        //Get boxSize
        var boxSize = Number ($(this).css('height').split('px')[0]);

        //Calculate newSize & apply
        var newCssFontSize =  boxSize  * miRatio
        $(this).css('font-size', newCssFontSize );
        $(this).css('line-height', boxSize + "px" );
    })
});
karacas
  • 2,054
  • 1
  • 19
  • 29
  • There can be a correction. Actually, for a few font-browser combination, the ratio for Arial was not found to be constant. It was different for 120px and different for the rest. – Manu Feb 08 '13 at 13:08
  • Wired, i check and i see always de same ratio, checked in ie8/ff/chrome – karacas Feb 08 '13 at 14:47
3

As far as the browser is concerned the gap you see in your jsFiddle link is not there. The gap is part of the font. For instance if you put a lower case g into your example, then the bottom gap disappears and the span fits the text perfectly.

This means there is no way to automatically resize the text to eliminate the gap as the browser will not know anything about the threshold, hence manual/visual trial and error would be required and that technique would not be very successful across different browsers.

I can only see 1 real solution to this issue, assuming the issue is eliminating that gap. The solution is to use an image.

If you don't want to create the image in photoshop then the image could be created in the frontend on canvas, or in the backend via a library like GD in PHP. By dynamically creating the image you can then loop throw the pixel data to easily remove any whitespace from around the text.

As a side point a font replacement technology like cufon or typeface.js might be able to provide text without the gap with a bit of fine tuning.

Coin_op
  • 10,568
  • 4
  • 35
  • 46
3

The way to do it is to set the line-height relative to the font-size. After that, you need to use display:inline-block. It's not perfect, you'll have to account for the individual fonts you're using. One way to control the variations is to use text-transform:uppercase.

Here's the code:

#abc {
  font-size: 100px;
  line-height: 68.5%;
  border: dotted 1px red;
  text-transform:uppercase;
  display:inline-block;
}

You can change the font-size to any size you like -- it'll still work. If you use a different font, just change the line-height's relative percentages.

John Chan
  • 305
  • 2
  • 7