See http://jsfiddle.net/6taruf65/1/
The following html appears as 20 pixels tall in Firefox31 and Chrome36 on Windows7. I expected it to be 16 pixels tall.
<style>
* { margin: 0; padding: 0; border: 0; overflow: hidden; vertical-align: baseline; }
</style>
<div style="font-size: 16px;">help 16px</div>
Notice the bottom of the p is cut off when you limit the div's height to 16px. That suggests to me there's unused space above the text. It might be a problem with vertical alignment. But then how would I go about preventing that issue when I want to precisely control the height and alignment of the text?
This is because the default line-height value that is applied by the user agent. Some of web browsers apply a line-height of 1.2em or 1.2 or 120% to the elements while the spec recommends:
We recommend a used value for normal between 1.0 to 1.2.
CSS Level 2 Spec states:
line-height
On a block container element whose content is composed of inline-level
elements, 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.
The accepted values are normal | <number> | <length> | <percentage> | inherit
Hence, you could override the applied value by adding a line-height of 16px or simply a value of 100% or 1em or 1 to the element. (Click on each one to see the demo).
<number> - e.g. line-height: 1 - is the preferred value of line-height as it always refers to the element's font size. Therefore you don't have to specify different values for different font sizes.
For further info about the difference between these values, you could refer to my answer here:
Calculate line-height with font in rem-value
Maybe you need line-height: 16px;
The div size is not 20px because the font-size is larger than 20px when you have letters that hang below the baseline (such a p and q). If you want the div itself to be of height 20px, just set the div css to height: 20px.
JSFiddle
<div style="height: 20px; font-size: 20px; border:1px solid #444;">help 20px (with cut off text)</div>
<br />
<div style="height: 23px; font-size: 20px; border:1px solid #444;">help 20px (without cut off text)</div>
<br />
Related
This question already has answers here:
How does rem differ from em in CSS?
(12 answers)
Closed 2 years ago.
To recap, the em unit means "my parent element's font-size" in the
case of typography. The <li> elements inside the <ul> with a class of
ems take their sizing from their parent. So each successive level of
nesting gets progressively larger, as each has its font size set to
1.3em — 1.3 times its parent's font size.
To recap, the rem unit means "The root element's font-size". (rem
stands for "root em".) The <li> elements inside the <ul> with a class
of rems take their sizing from the root element (<html>). This means
that each successive level of nesting does not keep getting larger.
This is the explanation that Mozilla provides.
I can see that in my places of other people's code, they have padding: 1.5rem. It means that rem and em are not coupled to font-size at all. Is that right ?
Question 1) So, if I set padding:1.5rem on an element, what size will it have ? what does it look at so that it can figure out its own padding size ?
Question 2) What about padding:1.5em ?
Yes, you can use em and rem for any measure of length.
Question 1) So, if I set padding:1.5rem on an element, what size will it have? what does it look at so that it can figure out its own padding size ?
If the padding of an element is 1.5rem, it will have a padding length of 1.5 times the font size of the html element. In the example below, the outer box has a padding of 1.5x or 15px, and the inner box is 2x or 20px.
html{
font-size: 10px;
}
.p,.c{
border: solid 1px #f00;
}
.p{
padding: 1.5rem;
}
.c{
padding: 2rem;
}
<div class='p'>
<div class='c'></div>
</div>
Question 2) What about padding:1.5em ?
An element with 1.5em padding will take 1.5x the font-size of the nearest parent (including self) with a font size set. So if you set the font size of the outer box from the previous example to 8px, it will have 1.5x or 12px of padding, and the inner element will have 2x or 16px padding.
html {
font-size: 10px;
}
.p,
.c {
border: solid 1px #f00;
}
.p {
font-size: 8px;
padding: 1.5em;
}
.c {
padding: 2em;
}
<div class='p'>
<div class='c'></div>
</div>
Answer1: So if you set padding:1.5rem , it will take the size according to root font size of root HTML that is 24px. (1rem is 16px by default)
It will further set the padding space according to given value and multiplies it by the font size of root element(HTML).
Answer2: And it causes same with em , it will multiplies the em's value according to the font size given.
By default it is 12px for 1em. So if you set paddind:1.5em it will add a padding space of 16px.
May this helps.
Note: em to px and rem to px values may vary accordingly.
I thought 'what determines height of content-box' and thought line-height might.
It seems to be the case you can determine it for block elements with line-height.
<p style="background-color: grey; font-size: 16px; line-height: 2em;">Is line-height same as height of p tag?</p>
<div style="background-color: lightsalmon; font-size: 16px; line-height: 2em;">Is line-height same as height of div tag?</div>
<span style="background-color: aquamarine; font-size: 16px; line-height: 2em;">Is line-height same as height of span tag?</span>
Inline elements seems a different story. Would someone be able to elaborate?
For block elements its quite easy but you need to distinguish between two different cases. When we have an IFC (inline formatting context) or BFC (block formatting context). From the specification you can read
If 'height' is 'auto', the height depends on whether the element has any block-level children and whether it has padding or borders:
The element's height is the distance from its top content edge to the first applicable of the following:
the bottom edge of the last line box, if the box establishes a inline formatting context with one or more lines
the bottom edge of the bottom (possibly collapsed) margin of its last in-flow child, if the child's bottom margin does not collapse with the element's bottom margin
the bottom border edge of the last in-flow child whose top margin doesn't collapse with the element's bottom margin
zero, otherwise
Only children in the normal flow are taken into account (i.e., floating boxes and absolutely positioned boxes are ignored, and relatively positioned boxes are considered without their offset)
If we consider an IFC then the line boxes will define our height exactly like your examples where in the div and p you have one line box defined by the line-height.
If we consider a BFC then the (2) and (3) apply. Here, you can see it as a recursive definition because having a BFC means we have other blocks inside and those blocks will follow the same rules (either BFC or IFC and so on). In addition, we consider the margin collapsing rules to get the final height.
If the block is empty then it's zero.
Of course, this consider the case of height:auto. If you explicitely set a height then it's trivial.
For inline elements you can refer to this part of the specification:
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. (The latter would ensure that glyphs with parts above or below the em-box still fall within the content area, but leads to differently sized boxes for different fonts; the former would ensure authors can control background styling relative to the 'line-height', but leads to glyphs painting outside their content area.)
Here is a bit tricky but the rule is simple: you cannot control or set the height of the content area. Only the font properties you will be using will define the final height.
You should also note that the content area is different from the line box.
The vertical padding, border and margin of an inline, non-replaced box start at the top and bottom of the content area, and has nothing to do with the 'line-height'. But only the 'line-height' is used when calculating the height of the line box.
<span style="background-color: aquamarine; font-size: 16px; line-height: 2em;">Is line-height same as height of span tag?</span>
<br>
<span style="background-color: aquamarine; font-size: 16px; line-height: 4em;">Is line-height same as height of span tag?</span>
<br>
<span style="background-color: aquamarine; font-size: 16px; line-height: 8em;">Is line-height same as height of span tag?</span>
If you increase the line-height you will clearly notice that the background won't cover a bigger area but only the line box will be bigger
Some related question to get more details and understand the difference between line box and content area:
Can specific text character change the line height?
Box Model for Inline Elements
Why is there space between line boxes, not due to half leading?
So line-height will indeed define the height of block element and not inline element since the block element height will depend on the height of the line boxes and the height of line boxes are defined with line-height1
Here is an example to show a block element having its height defined by the line box and the content area of the inline element inside will oveflow because they play no role in defining the line boxes:
p {
margin:50px;
font-size:35px;
border:1px solid red;
line-height:0;
}
span {
background:green;
line-height:10px;
}
<p>
<span>some text here and there</span>
</p>
<p>
<span style="font-family:cursive">some text here and there</span>
</p>
In both examples, we have a height equal to 12px for the p (10px of line-height + 2px of border) and our inline element is having a different height in each case because the font is not the same.
1: We should note that in practise it can be more complex and the value of line-height alone isn't enough.
If we read the specficiation we can see that:
On a block container element whose content is composed of inline-level elements, line-height specifies the minimal height of line boxes within the element.
Then
On a non-replaced inline element, line-height specifies the height that is used in the calculation of the line box height.
That's why in the last example I made the line-height of the block element to be 0 so only the line-height of the inline elements inside will define the final height of the linebox
Even the vertical alignment play a role here because if we have multiple elements not aligned the same way and with different line-height, finding the result will be more complex:
p {
margin:50px;
font-size:35px;
border:1px solid red;
line-height:0;
}
span {
background:green;
line-height:1;
}
<p>
<span>AB</span> <span >AB</span>
</p>
<p>
<span>AB</span> <span style="vertical-align:super">AB</span>
</p>
To find the height of a linebox you need to consider 3 factors:
The line-height of the block container (the IFC)
The line-height of the inline elements inside
the vertical alignment of inline elements
Let's not forget that line-height is inherited so if we don't set it explicitely we need to either consider the value of the parent element or the default one.
CSS2.1 Section 10.6.1 specifies:
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.
The vertical padding, border and margin of an inline, non-replaced box start at the top and bottom of the content area, and has nothing to do with the 'line-height'.
Then, the statements that seem contradictory follow in 10.8 Line height calculations:
The height of a line box is determined as follows:
The height of each inline-level box in the line box is calculated. For inline boxes, this is their 'line-height'....
And:
User agent must align glyphs in a non-replaced inline box to each other by their relevant baselines....
The height of the inline box encloses all glyphs and their half-leading on each side and is thus exactly 'line-height'
There is something I am not fully understanding here.
Is the height of inline-level boxes equal to the line-height property set on them (with the minimum being the line-height set on the parent block container element), OR is it just determined by the font height (and UA implementation)?
EDIT
Just to avoid confusion (since there are many posts about this):
I know that an inline-level element's content height is equal to the font it contains (and UA implementation)
I realize the spec does state that in 10.6.1, but in 10.8.1 it states that the height of an inline-level box is equal to its line-height
That seems contradictory to me
My purpose with this post is to discuss the wording in the spec, in order to fully understand what it means and how it ties in with reality
EDIT:
To avoid the "opinion based" close votes, I have changed the title. It is not my opinion that the spec is contradictory, and I am not asking for anyone else's opinion on whether it is contradictory either.
I realize it is not actually contradictory, I was just trying to understand why it is not, given its wording.
Is the height of inline-level boxes equal to the line-height property set on them (with the minimum being the line-height set on the parent block container element),
Yes it is.
OR is it just determined by the font height (and UA implementation)?
No it isn't
CSS is really about boxes, not elements, and you should try not to confuse the two.
So an inline element has associated with it a number of boxes. A content box, padding box, border box and margin box. It also has zero (if display:none), one, or multiple inline boxes. The content box, paddings, borders and margins may be divided among the inline boxes so that the inline content can be spread over more than one line.
The inline box's height is the content height adjusted by the leading. It's the leading that does the magic here. The leading is defined as the line-height of the element minus the content height of that inline box.
Simply rearranging that equation tells us that the height of the inline box depends only on the line-height and not on the content box (or padding, border, margin boxes).
Note that none of the above discusses the line box, which is a different thing again and not a direct property of inline elements or their boxes. The line box is constructed by arranging the inline boxes that occur on the same line such that their vertical alignments fit the rules computed for the elements, including the zero width inline box formed by the strut.
Each line box is bounded by the top of uppermost inline box and the bottom of the lowestmost inline box that that line box contains.
Digression: On why the height of the line box can surprise.
Suppose we have a simple case of a containing block which just contains one short inline element (i.e. short enough that it fits in a single line box). Also suppose that everything is aligned on the baseline. Let's say that the line-height is set on the containing box to 20px, and the inline element inherits that. Also suppose that the font-size (em-square) of the containing block is 16px, and that means that the font metrics compute to an ascent (above the baseline) of 14px and a descent (below the baseline) of 4px.
So the content area for the strut is (14px + 4px =) 18px high. The line-height is 20px, so there is 2px leading, 1px goes above the ascent, and 1px below the descent. So the line-height of the strut is made of 15px above the baseline and 5px below the baseline.
Now, suppose that the font-size of the inline element is set to 0.5em (i.e. half that of the containing block). The content area for the inline element will be an ascent of 7px and a descent of 2px. The line-height is still 20px, so the leading is 20px - (7px + 2px) = 11px, meaning that 5.5px goes above the ascent and 5.5px goes below the descent. This results in the line-height for the inline element is made of 12.5px above the baseline and 7.5px below the baseline.
Since the strut and the inline element are aligned vertically to their baselines, the top of the uppermost inline box (the strut) is 15px above the baseline and the bottom of the the lowermost inline box (the inline element) is 7.5px below the baseline, the actual height of the line box is not 20px but (15px + 7.5px =) 22.5px.
As I explained in this previous question (Why is there space between line boxes, not due to half leading?) we have the content area and the line box.
The content area is defined by the font properties and the UA (like described in your first quote) and the line box is defined by the line-height (like described in your second quote). Here is some example to show different height of content area based on different fonts and to illustrate the difference with the line box:
span {
border-left: 1em solid red;
background: rgba(255, 0, 0, 0.2);
}
.container>div {
margin-bottom: 5px;
border: 1px solid;
line-height: 30px;
}
.container>div:nth-of-type(1) span{
font-family: arial;
font-size: 25px;
}
.container>div:nth-of-type(2) span{
font-family: "open sans";
font-size: 20px;
}
.container>div:nth-of-type(3) span{
font-family: monospace;
font-size: 30px;
}
.container>div:nth-of-type(4) span{
font-family: cursive;
font-size: 22px;
}
<div class="container">
<div>
<span>Hello World</span>
</div>
<div>
<span>Hello World</span>
</div>
<div>
<span>Hello World</span>
</div>
<div>
<span>Hello World</span>
</div>
</div>
As you can see the background and border apply to the content area that is defined by the font-family and font-size. For all the cases, I set the line-height to be equal 30px thus all the line boxes are equal.
We can also notice that the border-left behave differently which indicates that indeed the height of the content area depends on the font and UA.
Here is the same example with some vertical padding/margin/border in order to illustrate how they affect the content area and has nothing to do with line-height:
span {
border-left: 1em solid red;
background: rgba(255, 0, 0, 0.2);
font-family: arial;
font-size: 25px;
}
.container>div {
margin-bottom: 5px;
border: 1px solid;
line-height: 40px;
}
.container>div:nth-of-type(1) span {
padding: 10px;
}
.container>div:nth-of-type(2) span {
border-bottom: 5px solid red;
}
.container>div:nth-of-type(3) span {
padding: 10px;
background-clip: content-box;/*I limit the background to content-box only*/
}
.container>div:nth-of-type(4) span {
margin: 20px;
}
<div class="container">
<div>
<span>Hello World</span>
</div>
<div>
<span>Hello World</span>
</div>
<div>
<span>Hello World</span>
</div>
<div>
<span>Hello World</span>
</div>
</div>
I can vertically center one-lined text with line-height, but also with padding-top and padding-bottom.
What are the pros and cons of each?
body {
font-size: 12px;
font-family: sans-serif;
}
div {
border: 1px solid #333;
padding-left: 10px;
padding-right: 10px;
display: inline-block;
}
.vcenter1 {
line-height: 50px;
}
.vcenter2 {
padding-top: 19px;
padding-bottom: 19px;
}
<div class="vcenter1">Lorem ipsum line-height...</div>
<div class="vcenter2">Lorem ipsum padding...</div>
For me both of the methods are valid for instances where the line of text is guaranteed to only ever span one line (either by nature of the containers width being fixed or by manipulation of the content and/or CSS white-space property), but it depends on your intention as to which is more appropriate:
If you want the height of the element the text is contained within to be fixed, then using line-height seems most appropriate and maintainable because changes to the size of the font wont impact the height of the container (unless the font becomes taller than the container).
If however the height of the container is not fixed and it's more important that the white-space either side of the font remains, padding is the more appropriate option.
There are of course other ways of centring text vertically within an element, this previous question How do I vertically center text with CSS? has a lot of useful information on the topic.
Purely in terms of vertically centering, it matters not a jot. But note that in the second case, you are padding around a line box whose height is proportional to the font-size. Different browsers use slightly different proportions by default, so the bordered box will be different sizes in different browsers. That won't happen in the first case.
I've been given a set of web pages to knock up, and one of the specifications from the designer is a set of vertical measurements from the baseline of fonts i.e. the height from the baseline to the block above is 50 pixels and to the block below to 30 pixels.
If I know the font size in pixel can anyone suggest a way to calculate the top and bottom margins (and / or line height etc).
The line-height CSS property can be set as a numeric value. So the calculated line-height will be numeric value * font size. If you set line height to 1, then the line height will be equal to the font size. Here is an example with font-size: 20px
div {
font-size: 20px;
padding-bottom: 30px;
padding-top: 30px;
line-height: 1;
}