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

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.

Related

Why is there space between line boxes, not due to half leading?

In the code example below, you will see white-space between the vertically flowing spanss. The white space is between each line box.
I want to start out by stating that this has nothing to do with gaps between inline-block boxes or even a result of half leading, which is added on top and bottom of an inline level box when calculating minimum line height.
From the CSS2.1 spec:
The height of the inline box encloses all glyphs and their
half-leading on each side and is thus exactly 'line-height'.
And:
The minimum height (of a line box) consists of a minimum height above the baseline and a minimum depth below it....
Notes:
background-color (as seen in the below example) covers the full line box
Despite that, there is still white-space between each line box
I am not asking for a solution to remove the gap. If I wanted to do that, I would just set display: inline-block on the span
Why is the gap there, with basis in the CSS2.1 specification. What part of the spec explains that spacing?
Example code:
// From CSS spec:
// The height of the inline box encloses all glyphs and their half-leading on each side and is thus exactly 'line-height'. Boxes of child elements do not influence this height.
span {
background-color: red;
line-height: 1;
}
<span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span><br/><span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span>
The background properties applies only to the content area and not the line box. In most of the cases the content area is defined by the height. As we can read in the specification:
The dimensions of the content area of a box — the content width and
content height — depend on several factors: whether the element
generating the box has the 'width' or 'height' property set, whether
the box contains text or other boxes, whether the box is a table, etc.
And here:
This property specifies the content height of boxes.
This property does not apply to non-replaced inline elements. See the
section on computing heights and margins for non-replaced inline
elements for the rules used instead.
And if check the above link we can read:
The 'height' property does not apply. The height of the content area
should be based on the font, but this specification does not specify
how. A UA may, e.g., use the em-box or the maximum ascender and descender of the font.
Here is an illustration to better show youref:
The content area is defined by the browser and in some case it can be the em1 that you see in above figure but not necessarely.
In all the cases and whataver the line-height will be, the content area will only depend on the font properties. So the line-height define the height of the line box AND the content area height is defined by the font properties.
So the real question is: Why by default the line-height doesn't make the line box equal to the content-area?
If check we check the documentation we can see that the default value is set to normal and:
normal
Depends on the user agent. Desktop browsers (including Firefox)
use a default value of roughly 1.2, depending on the element's
font-family.
Then
<number> (unitless)
The used value is this unitless <number> multiplied by the element's own font size.
In some cases, we will have the line box a bit bigger than the content area which explain the gap.1
Now why setting the line-height to 1 doesn't fix the issue?
Simply because you set the line-height of the spans and not the line-height of their container which is not enough. The line-height of the container is still the default one 1.2 which will be considered since it's bigger than 1. In other words, the biggest line-height will win.
Here is some illustration to better understand:
line-height of the body is 2 and only a bigger line-height for span will have an effect:
body {
line-height:2
}
span {
background-color: red;
line-height: 1;
animation:change linear infinite 2s alternate;
}
#keyframes change {
to {line-height:3}
}
<span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span><br/><span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span>
Setting line-height to body is enough as the span will inherit it:
body {
line-height:1; /*line-height is equal to content area*/
}
span {
background-color: red;
}
<span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span><br/><span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span>
1 Worth to note that in some cases and for some particular font, you may not see any gap and you won't even need to set line-height to 1 because the content area may be bigger enough to cover the line box since the calculation of both value are independent.
Here is some examples
span {
background-color: red;
}
div {
margin:5px;
}
<div><span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span><br/><span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span>
</div>
<div style="font-family:cursive"><span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span><br/><span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span>
</div>
<div style="font-family:monospace"><span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span><br/><span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span>
</div>
<div style="font-family:sans-serif"><span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span><br/><span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span>
</div>
We have gaps only for the first and last example.
It's because the parent container's line height does not match the span's - line height affects the children so as span is inline, it is obeying the parent's line height
// From CSS spec:
// The height of the inline box encloses all glyphs and their half-leading on each side and is thus exactly 'line-height'. Boxes of child elements do not influence this height.
div {
line-height: 1;
}
span {
background-color: red;
line-height: 1;
}
<div>
<span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span><br/><span>Some span. As seen, background covers font plus half leading on top/bottom. There is still a gap, which is due to something else.</span>
</div>

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

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.

line-height affecting even no-text blocks

I noticed that line-height seems to affect blocks. Its strange to me, that i never noticed this disturbing effect before.
The problem is that it will affect blocks, even if they do not contain text at all.
I created a JSFiddle to demonstrate the issue. If you set line-height to 0, the grey area will no longer exceed that of the image inside the container.
Why is this happening and is there a clean way to prevent it?
The line-height value affects rendering even in the absence of text, since “'line-height' specifies the minimal height of line boxes within the element. The minimum height consists of a minimum height above the baseline and a minimum depth below it, exactly as if each line box starts with a zero-width inline box with the element's font and line height properties.” (CSS 2.1 about line-height.)
But that’s really not the cause here. Images are by default rendered inline, meaning that they act as big (or maybe small) letters, sitting on the baseline of text. The details are complicated, but by setting line-height considerably smaller than font size, you put baselines closer to each other and the space vanishes.
Another way to remove the disturbing effect is to set display: block on the img element. Then the element will be formatted in a different way.
Yet another way is to set vertical-align: bottom on the img element.

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

css - inline elements ignoring line-height

I'm having trouble figuring out why inline elements ignore line-height in some browsers (Chrome and Firefox ignore it, but IE9 does not).
Here is an example:
<small style="line-height: 1; font-size: 26px;">Hello, World</small>
The expected result is for the element height to be 26px, however, it's being set to 31px. If I set the element's display to block, the height is correctly set to 26px.
Everything I read says it's supposed to be set to the line height, so I can't figure this one out. Here is what I read on W3C:
The height of each inline-level box in the line box is calculated. For replaced elements, inline-block elements, and inline-table elements, this is the height of their margin box; for inline boxes, this is their 'line-height'.
Source: http://www.w3.org/TR/CSS2/visudet.html#line-height
What webkit inspector shows (and what you measured in PhotoShop) is the content area's dimensions.
See http://www.w3.org/TR/CSS2/visudet.html#inline-non-replaced
The height of the content area [of inline elements] should be based on the font, but this specification does not specify how. A UA may, e.g., use the em-box or the maximum ascender and descender of the font...
Different browsers simply use a different approach here. See http://jsfiddle.net/ejqTD/1/ for an illustration of that. Note how webkit renders a higher content area, but line-height is still correct.
The content area exceeds the line box in this case, which is permitted: http://www.w3.org/TR/CSS2/visudet.html#leading
if the height specified by 'line-height' is less than the content height of contained boxes, backgrounds and colors of padding and borders may "bleed" into adjoining line boxes.
It's easy to see if you consider line-heights < 1: http://jsfiddle.net/KKMmK/