How to deal with line-height while coding a pixel perfect design - html

Here is a screenshot of the example design I made up:
There is a 10px space between the bottom of the letters and the red line. I'm trying to replicate this with the following code:
font: normal 40px arial;
border-bottom: 3px solid red;
padding-bottom: 10px;
Technically, this code should give me exactly what I want. But it doesn't. Here is a screenshot of it in action in Chrome:
Because of the line height, there's extra space between the text and the border. Here's an inspected screenshot on Chrome:
When I take my time and measure the space under the letters that's being caused by line height, I can see it's a 9px of empty area. So, to get 10px of space between the text and the border I need to change my code to:
padding-bottom: 1px;
A solution to this might be adding a line-height property with amount of the text's exact height in the design file. But then, it'll mess up if the text includes multiple lines.
What is the best approach here to accomplish the pixel perfect design conversion?

In HTML, there is no way to specify the spacing between the text baseline and the border. To understand this, see this picture:
The height of HTML text always includes both the ascender area and the descender area, even in cases when there are no letters with a descender or an ascender. Therefore the real distance between the bottom of the text and the border in your example is not 10px.
To get the correct distance from the bottom of text in pixels, change the text so that it contains a letter with a descender (e.g. Hellp, Worly") and measure the space between the bottoms of descenders and the red line.
Alternatively, if you are trying to recreate a picture and can't change the text, measure the ratio text height / point size of the used font using a drawing application (e.g. Inkscape), then calculate the distance as follows:
css distance = baseline distance - (point size * (1 - ratio))

The basic spacing below and above a character (glyph) is defined by the font designer. For example, in Arial, there is space below and above an ordinary uppercase letter like “H” even when text is set solid (line-height: 1). When line-height is larger than 1, there is additional spacing below and above. Even for line-height smaller than 1 (i.e., with “negative leading”), there can be some spacing. And any padding that you set adds to that.
If you know the exact text that appears in the content (and it will never change) and if you rely on the specific font to be always available (which is very probable, but not certain, for the Arial font), then you can run some experiments and iterate until you find a suitable line-height value. In this specific case, line-height: 0.82 would remove the spacing above common capital letters A–Z (but any diacritic marks on them, as in É or Å, will be cut off) and would reduce the spacing below the baseline (but if letters have descenders as in “j” or “þ”, they will then be partly cut off).
Pixel-perfectness may still be disturbed by font rendering differences (like anti-aliasing or not) across browsers.

Related

Font-size and the size (height) of links around text

font-size sets the font height.
Font height is measured or specified by the height of a line, which is
the full height required to display the gamut of characters, including
those that dip below the line, like j, and raised elements (accents on
capitals, for instance) like Ê.
See How is font size calculated?
So a font with long descenders and ascenders will look smaller than a font with the same font-size with short descenders and ascenders.
If the line-height is set to 1em, the line-height is presumably the same as the font-size. So a font-size: 50px with a line-height: 1em will have a line-height of 50px.
So why then are links around text bigger (have a greater height) than the font and a line-height of 1em?
See https://jsfiddle.net/fkv4qunm/
This screen grab shows text with a line-height of 1em with a green background. And links with a pink background. The height of the links is greater than the line-height / font-size. (And there is no padding or margins on the links)
UPDATE
If the font-size is the complete height of all the fonts glyphs, ascenders and descenders, then what is determining the height of the links?
UPDATE 2
But from relooking at the screen grab the green line-height of 1em isn't containing the complete height of all the fonts glyphs – I think the 'j' would get cropped. This suggests that font-height isn't setting the height required to display all the characters (accents on capitals etc). But the size of the pink link is determined by the this height. So I'm now confused what font-size is measuring.
It is because anchor tag <a> is an inline element, inline elements size (width & height) is depended on the content size if you change your CSS code to this:
a {
display:block;
width:200px;
background-color: pink;
text-decoration: none;}
You will see the height of the <a> element will be the same as <li> element.
So, if you want to use an inline element inside of a block-level element you should change the size manually or use properties that can convert the type of the element.
In an inline formatting context, boxes are laid out horizontally, one
after the other, beginning at the top of a containing block.
Horizontal margins, borders, and padding are respected between these
boxes. The boxes may be aligned vertically in different ways: their
bottoms or tops may be aligned, or the baselines of text within them
may be aligned. The rectangular area that contains the boxes that form
a line is called a line box.
The height of a line box is determined by the rules given in the
section on line height calculations.
Many thanks to Alireza and FluffyKitten. I believe this is the answer:
Font-height is determined differently for different fonts. It is not always the height from the lowest glyph to the highest glyph (for example from the lowest part of the ascender 'p' to the highest part of an accent on a capital letter 'À').
https://www.w3.org/TR/CSS21/visudet.html#line-height
CSS assumes that every font has font metrics that specify a
characteristic height above the baseline and a depth below it. In this
section we use A to mean that height (for a given font at a given
size) and D the depth. We also define AD = A + D, the distance from
the top to the bottom. (See the note below for how to find A and D for
TrueType and OpenType fonts.) Note that these are metrics of the font
as a whole and need not correspond to the ascender and descender of
any individual glyph.
These two screen grabs show how two different fonts deal with font-size differently. First example is Elena. Second example is Times New Roman.
The first one has more vertical space above and below the letters. Whereas the font-size of the second font is closely determined by the lowest ascender and tallest descender.
Interesting point
If the line-height is set to 1 or 1em (making the line-height the same height as the font-size) then many letters bleed out of the font-size / line-height. Which is weird. See below. This is font-size 50px line-height: 50px and the descenders aren't included in the height of the font or line-height!!
However, the height of the inline <a> link continues to contain all the fonts glyphs. i.e. the height on an inline element is determined not by font-size (or line-height) but by the in-built font metrics.
It seems to me that there should be a consistent way to measure CSS font-size (from the lowest to highest glyph?). At the moment different fonts are using different in-built metrics and it's a mess.

Workarounds for avoiding inconsistent line height with fractional pixels in Firefox

Situation: I want to display some text (or font icon) within a fixed height box. I can assume this will always fit on one line, so can simply use line-height to control the centering.
This works perfectly and shows two such boxes under each other:
<div class="box">a</div>
<div class="box">a</div>
.box {line-height:32px;width:32px;text-align:center;background:red;margin-bottom:5px;font-family:Arial,Helvetica,sans-serif;}
https://jsfiddle.net/zj55racg/1/
Now, change the 5px vertical margin to 1.5px:
https://jsfiddle.net/jwg2ok3f/
In Chrome, I get the same nice-looking result. In Firefox however, the second box has the text visibly lower relative to the red box and does not look nicely centered at all.
Now while you would never use fractional pixel margins directly in the CSS, there is invariably text with a percentage line height, or responsive images, etc, throughout the page that results in fractional pixels being introduced. This means half the buttons throughout my page look nice; the other half look quite bad - the different is very noticeable.
Are there any ways the rendering can be worked around?
Image of what I see in case others can't replicate - the second a is a whole pixel lower in the red box than the first.

Fit text exactly without spacing

In CSS/HTML, using a simple text within a div with no margin/padding with a given font-size (assume 36px) and a given line-height of 36px will not fit exactly, there's always some spacing at the top of the line. Reducing the line-height for 20% (i.e. in this case 29.8) seems the result in the desired effect.
Why is this, is there any browser thing I am missing? I'd assume having a line-height equal to font-size should actually NOT add any spacing around a line at all?
Update: The effect I am actually getting is called "half-leading". Howevever, I assumed that when setting the line-height equal to the font-size, no leading may occur at all as the browsers' calculated half leading should result in 0px.
Update 2: Just found this in the CSS-Spec: http://www.w3.org/TR/CSS2/visudet.html#line-height
However, I am still confused considering how to avoid having added ascender/descender at all?
Responding to your update #2:
Since ascender/descender height is calculated for each font, there are fonts that don't have ascenders/descenders, like all caps monospace. It would need to be a font that doesn't include any characters with a/d; just applying text-transform: capitalize wouldn't work.
A roundabout solution, but as you've stated it is a "feature not a bug".

Why does Verdana font result in a different space size before text depending on font?

In the following HTML/CSS example
http://jsfiddle.net/Hmwvv/
we can notice a leading space with size proportional to font's size. How can I remove this effect in order to have different sized texts in different div elements aligned ?
There is a small amount of white space around each glyph, this is intentional so that the letters don't overlap. You can see this by selecting one letter.
To solve your problem, introduce a small negative text-indent.
#big {
text-indent: -5px;
}
Demo
The leading space is part of the character rendering, as you can see e.g. by setting `div:first-letter { background: green }. It would violate normal typographic rules to tweak it.
But if you really want to align the leftmost strokes of letter “M” in different sizes in a heading and in the first line of a paragraph after it, then setting margin-left: 0.3em on the paragraph would seem to be the best option. This applies Verdana and those specific characters are used. (If e.g. the first letter of the heading is “J”, the situation is very different.)

Space around text in header elements

I have been inspecting a header element using firebug, and have noticed that the header container does not hug its contained text, even though I have no padding set.
<h2>test</h2>
http://jsfiddle.net/BTwk6/
The top and bottom spacing is greater than that on the left and right, the result of this is that my h2 does not sit squarely in its containing box.
Is this normal? Is there anyway to have the h2 box hug its text?
Thanks
Yes, it is normal, and things are supposed to be that way. If you e.g. set a border on a heading element, you will see that characters in the heading text will normally not touch the border.
There are two reasons to this. First, the height of a font is a design concept and does not (normally) correspond to the height of any letter; there is empty space above even capital letters as well as below the baseline of text. Descenders like that of “j” or “g” may, in some designs, reach the bottom of the font, and diacritic marks like that of “Ê” may reach the top, or even go beyond it.
Second, there is normally some leading above and below a line, typically a total of 15–20% of the font height. The default depends on the font (and on the browser). In practice, this is meant improve readability and to prevent characters from touching characters on the previous or next line.
The leading is indirectly set by setting line-height, since line-height sets the total height that is the sum of font height (font size) and leading. By setting line-height: 1, you set leading to zero; this is called “setting solid” in typography, and it can be suitable for isolated lines, like a one-line heading. But there is still spacing caused by the first reason mentioned, the spacing that has been “built in” into the font. You can even set line-height to a smaller value, like 0.85, making the leading negative. Beware that this may cause vertical truncation of characters if the font used differs from the one you suggest on your page.
Try adjusting the line-height property as well, by default different fonts have different spaces above and below them. You may not be able to entirely fix this. For example, the word
Tempura
Is a whole lot taller than the word
mum
But the word 'mum' will still have to have the same height above and below the line as 'Tempura'.
by default a h2 element has a margin of 19px top an bottom. Try to reset it
Try to reset margin and padding :
h2{margin:0;padding:0}
replace 0 with your own values ...
mimiz