I have a block with a certain line-height, where I insert content with the ::before pseudo element.
.block::before {
content:'text here';
}
This works well. However, if I also give the content a smaller font size
.block::before {
font-size:.6em;
content:'text here';
}
the block actually becomes higher. Why is that?
.container {
display:inline-block;
}
.lorem, .ipsum, .dolor, .sit {
line-height:3em; border:1px solid green
}
.ipsum:before {
content:'world!';
}
.sit:before {
font-size:.6em;
content:'world!';
}
<div class="container">
<div class="lorem">Hello</div>
</div>
<div class="container">
<div class="ipsum"></div>
</div>
<hr style="clear:both"/>
<div class="container">
<div class="dolor">Hello</div>
</div>
<div class="container">
<div class="sit"></div>
</div>
The top row doesn't have font size changes, the bottom row does.
Now I found out that a possible solution is to set the line-height of the pseudo element to 0. Or to 1em. Or even to normal. So what is going on? Is the line-height set to some weird value by setting the font size to .6em? Why?
PS Although this looks like a duplicate (see the list to the right), none of the answers I've read so far explains why setting line-height:normal solves the issue. There must be something happening that sets the line-height to a greater value implicitly. And that's what I'm trying to find out.
Edit: This question has had quite a number of new eyeballs lately, so here's an update to make it more useful.
Alohci's solution is correct, but it may not be absolutely clear for the more graphically-inclined.
So allow me to clarify the solution a bit, with pictures.
First, the line-height is inherited as its calculated size, so although it's specified in em units, children will inherit value in pixels. For example, with a font size of 20px and a line height of 3em, the line height will be 60 pixels, even for descendants with different font sizes (unless they specify their own line heights).
Now let's assume a font with a 1/4 descender. That is, if you have a 20px font, the descender is 5 pixels and the ascender 15 pixels. The remaining line-height (in this case, 40 pixels) is then divided equally above and below the baseline, like this.
For the block with the smaller font (0.6em or 12 pixels), the remaining amount of line-height is 60-12 or 48 pixels, which also gets divided equally: 24 above and 24 below the baseline.
Then if we combine the two fonts on the same baseline, you will see that the line heights are not divided in the same way, so the total height of the containing block increases, even though both line heights are 60 pixels.
Hope this explains things!
The height of the .lorem, .ipsum, .dolor, and .sit boxes is each the height of the single line box that they contain.
The height of each line box is the maximum of the height above the baseline + the maximum height below the baseline of the strut of the line and the text in the line. since the strut and the text are aligned on the baseline.
For clarity, heights below in em, refer to the font size of the overall container (i.e. the body element)
In .ipsum, (where the font size is 1em) the height above the baseline is 1em (the upper half-leading) + 13/16em (the ascender, approx) for both the strut and the text, and the height below the baseline is 1em (the half-leading) + 3/16em (the descender, approx) + 1em (the lower half-leading) making a total of 3em.
In .sit (where the font size is 0.6em) the height above the baseline is the maximum of [1em (the upper half-leading) + 13/16em (the ascender, approx) for the strut] and [1.2em (the upper half-leading) + 0.6 x 13/16em (the ascender, approx) for the text], and the height below the baseline is the maximum of [1em (the lower half-leading) + 3/16em (the descender, approx) for the strut] and [1.2em (the lower half-leading) + 0.6 x 3/16em (the descender, approx) for the text].
Evaluating that and converting to decimal gives 1.8125em above the baseline and 1.3125em below the baseline making a total of 3.125em, which is larger that the 3em of .ipsum.
Since there are already two answers that explain well why the height is increased, to quickly fix this problem you simply need to remove the units in line-height.
.lorem, .ipsum, .dolor, .sit {
line-height:3; border:1px solid green;
}
According to MDN
The line-height CSS property sets the height of a line box. It's
commonly used to set the distance between lines of text. On
block-level elements, it specifies the minimum height of line boxes
within the element. On non-replaced inline elements, it specifies the
height that is used to calculate line box height.
Values
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.
number (unitless) The used value is this unitless number multiplied by the element's own font size. The computed value is the
same as the specified number. In most cases, this is the preferred
way to set line-height and avoid unexpected results due to
inheritance.
length The specified length is used in the calculation of the line box height. Values given in em units may produce unexpected results.
percentage Relative to the font size of the element itself. The computed value is this percentage multiplied by the element's
computed font size. Percentage values may produce unexpected results.
So basically your question is one of the cases of unexpected results due to inheritance.
.container {
display:inline-block;
}
.lorem, .ipsum, .dolor, .sit {
line-height:3; border:1px solid green;
}
.ipsum:before {
content:'world!';
}
.sit:before {
font-size:.6rem;
content:'world!';
}
<div class="container">
<div class="lorem">Hello</div>
</div>
<div class="container">
<div class="ipsum"></div>
</div>
<hr style="clear:both"/>
<div class="container">
<div class="dolor">Hello</div>
</div>
<div class="container">
<div class="sit"></div>
</div>
Hi please add a specific height on your box...
.lorem, .ipsum, .dolor, .sit {
border:1px solid green;
height:30px;/*changes*/
}
Fiddle :http://jsfiddle.net/jxf29/
The font property on .sit:before is affecting this, the content property of css follows the current elements' css properties very stricly,
Its because of this that you can be able to manipulate the value of the content property within the same style that the content property is created
e.g
sit {
color: green;
}
sit:before{
content: "text-here";
color: red;
}
this would emphasize the color to be red.
Related
I have a block with a certain line-height, where I insert content with the ::before pseudo element.
.block::before {
content:'text here';
}
This works well. However, if I also give the content a smaller font size
.block::before {
font-size:.6em;
content:'text here';
}
the block actually becomes higher. Why is that?
.container {
display:inline-block;
}
.lorem, .ipsum, .dolor, .sit {
line-height:3em; border:1px solid green
}
.ipsum:before {
content:'world!';
}
.sit:before {
font-size:.6em;
content:'world!';
}
<div class="container">
<div class="lorem">Hello</div>
</div>
<div class="container">
<div class="ipsum"></div>
</div>
<hr style="clear:both"/>
<div class="container">
<div class="dolor">Hello</div>
</div>
<div class="container">
<div class="sit"></div>
</div>
The top row doesn't have font size changes, the bottom row does.
Now I found out that a possible solution is to set the line-height of the pseudo element to 0. Or to 1em. Or even to normal. So what is going on? Is the line-height set to some weird value by setting the font size to .6em? Why?
PS Although this looks like a duplicate (see the list to the right), none of the answers I've read so far explains why setting line-height:normal solves the issue. There must be something happening that sets the line-height to a greater value implicitly. And that's what I'm trying to find out.
Edit: This question has had quite a number of new eyeballs lately, so here's an update to make it more useful.
Alohci's solution is correct, but it may not be absolutely clear for the more graphically-inclined.
So allow me to clarify the solution a bit, with pictures.
First, the line-height is inherited as its calculated size, so although it's specified in em units, children will inherit value in pixels. For example, with a font size of 20px and a line height of 3em, the line height will be 60 pixels, even for descendants with different font sizes (unless they specify their own line heights).
Now let's assume a font with a 1/4 descender. That is, if you have a 20px font, the descender is 5 pixels and the ascender 15 pixels. The remaining line-height (in this case, 40 pixels) is then divided equally above and below the baseline, like this.
For the block with the smaller font (0.6em or 12 pixels), the remaining amount of line-height is 60-12 or 48 pixels, which also gets divided equally: 24 above and 24 below the baseline.
Then if we combine the two fonts on the same baseline, you will see that the line heights are not divided in the same way, so the total height of the containing block increases, even though both line heights are 60 pixels.
Hope this explains things!
The height of the .lorem, .ipsum, .dolor, and .sit boxes is each the height of the single line box that they contain.
The height of each line box is the maximum of the height above the baseline + the maximum height below the baseline of the strut of the line and the text in the line. since the strut and the text are aligned on the baseline.
For clarity, heights below in em, refer to the font size of the overall container (i.e. the body element)
In .ipsum, (where the font size is 1em) the height above the baseline is 1em (the upper half-leading) + 13/16em (the ascender, approx) for both the strut and the text, and the height below the baseline is 1em (the half-leading) + 3/16em (the descender, approx) + 1em (the lower half-leading) making a total of 3em.
In .sit (where the font size is 0.6em) the height above the baseline is the maximum of [1em (the upper half-leading) + 13/16em (the ascender, approx) for the strut] and [1.2em (the upper half-leading) + 0.6 x 13/16em (the ascender, approx) for the text], and the height below the baseline is the maximum of [1em (the lower half-leading) + 3/16em (the descender, approx) for the strut] and [1.2em (the lower half-leading) + 0.6 x 3/16em (the descender, approx) for the text].
Evaluating that and converting to decimal gives 1.8125em above the baseline and 1.3125em below the baseline making a total of 3.125em, which is larger that the 3em of .ipsum.
Since there are already two answers that explain well why the height is increased, to quickly fix this problem you simply need to remove the units in line-height.
.lorem, .ipsum, .dolor, .sit {
line-height:3; border:1px solid green;
}
According to MDN
The line-height CSS property sets the height of a line box. It's
commonly used to set the distance between lines of text. On
block-level elements, it specifies the minimum height of line boxes
within the element. On non-replaced inline elements, it specifies the
height that is used to calculate line box height.
Values
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.
number (unitless) The used value is this unitless number multiplied by the element's own font size. The computed value is the
same as the specified number. In most cases, this is the preferred
way to set line-height and avoid unexpected results due to
inheritance.
length The specified length is used in the calculation of the line box height. Values given in em units may produce unexpected results.
percentage Relative to the font size of the element itself. The computed value is this percentage multiplied by the element's
computed font size. Percentage values may produce unexpected results.
So basically your question is one of the cases of unexpected results due to inheritance.
.container {
display:inline-block;
}
.lorem, .ipsum, .dolor, .sit {
line-height:3; border:1px solid green;
}
.ipsum:before {
content:'world!';
}
.sit:before {
font-size:.6rem;
content:'world!';
}
<div class="container">
<div class="lorem">Hello</div>
</div>
<div class="container">
<div class="ipsum"></div>
</div>
<hr style="clear:both"/>
<div class="container">
<div class="dolor">Hello</div>
</div>
<div class="container">
<div class="sit"></div>
</div>
Hi please add a specific height on your box...
.lorem, .ipsum, .dolor, .sit {
border:1px solid green;
height:30px;/*changes*/
}
Fiddle :http://jsfiddle.net/jxf29/
The font property on .sit:before is affecting this, the content property of css follows the current elements' css properties very stricly,
Its because of this that you can be able to manipulate the value of the content property within the same style that the content property is created
e.g
sit {
color: green;
}
sit:before{
content: "text-here";
color: red;
}
this would emphasize the color to be red.
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.
Take a look at the following snippet. How can I increase the width of the red container with 10px?
Is there a way to increase the width of an element in CSS, still affecting the parent container? Or do I have to use a pseudo-element placeholder to accomplish this instead?
<div style="
background:blue;
display:inline-block;
height:50px">
<div style="
font-size:30px;
width:calc(100% + 20px);
background:red">
Inner container</div>
</div>
In the snippet above the blue container is not affected, and the red overflows.
Is there a way to increase width of an element by a certain amount, where the width of the element itself is not known until runtime?
You can only reliably do this using padding; however, padding will affect the layout of the element's contents, which may not be what you want. In your example, padding the child element will affect the layout of the text inside it; the content width is never really increased at all.
You can't change an element's content width by a definite amount when it is not known in advance and depends on external factors such as the amount of content it actually has, which is usually the case with floats, absolutely positioned elements, and inline-blocks. The closest you can get is an auto width, and that only has a meaningful effect on in-flow block boxes — which are none of the above — with respect to their parents, not their children.
In fact, the behavior that you see with calc(100% + 20px) is not governed by the spec, although it's as far as browsers generally go without falling into the cyclic dependency trap:
<percentage>
Specifies a percentage width. The percentage is calculated with respect to the width of the generated box's containing block. If the containing block's width depends on this element's width, then the resulting layout is undefined in CSS 2.1.
(calc() is CSS3, but the box model hasn't changed much from CSS2.1.)
If I understood correctly, you want to increase the child's initial width and add another 10px.
But when you set this property:
The width: 100% will always be relative to its parent, so if you add another 10px in relation to the 100% it will always be 10px bigger than its parent.
You may want to set just a min-width and a max-width instead of setting explicitly its width so that the child will be within some specified ranges, but to increase the width by 10px from the starting witdh using JUST CSS its not possible.
Note: Keep in min that using calc you have to add the according browser-engine property extension i.e:
-webkit-calc()
-moz-calc()
calc()
<div style="
background:blue;
display:inline-block;
height:50px">
<div style="
font-size:30px;
width: 100%;
background:red">
Inner container</div>
</div>
Hope this helps in some way, gl.
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 />
1-What's the difference between simple(width and height) and max/min(width and height)? Explain in terms of what will happen if the content, width and height of the element, for which (width and height) or max/min(width and height) is already specified in an internal style, grows more than the specified ones?
2-Secondly, how do we know which one to use when?(simple or max/min)
3-In the following example:
<html>
<head>
<style type="text/css">
p
{
max-height:50px;
background-color:yellow;
}
</style>
</head>
<body>
<p>The maximum height of this paragraph is set to 50px.
The maximum height of this paragraph is set to 50px.
The maximum height of this paragraph is set to 50px.
The maximum height of this paragraph is set to 50px.
The maximum height of this paragraph is set to 50px.
The maximum height of this paragraph is set to 50px.
The maximum height of this paragraph is set to 50px.
The maximum height of this paragraph is set to 50px.
The maximum height of this paragraph is set to 50px.
The maximum height of this paragraph is set to 50px.
</p>
</body>
</html>
Here, the max-height seems to have no effect on the content of the element as it's height grows and shrinks with the content in it?. Iam currrently using IE8.
Answers:
1: Please see below for the difference between simple and max:
#element {
width: 100px;
height: 100px;
background-color: red;
}
<div id="element">
I'm a 100px wide, 100px high block!
</div>
The div above will be a 100px high and 100px wide red block on the page with the text 'I'm a 100px wide, 100px height block' inside it. If the text were to long for this block it would either leak out or if you put overflow: hidden in your css for the element, the excess content would be hidden.
If instead you did this:
#element {
max-width: 100px;
max-height: 100px;
background-color: red;
}
<div id="element">
I'm a flexible block!
</div>
The element would be as large as your content but if your content ever reached 100px high or over the element would stop and it would do the same thing as the above example (either cut the content off if you have overflow: hidden in your css or the content will leak into the page from the element).
2: If you want a big red block on the page or. use width/height, if you want a small red block on the page that needs to grow but only grow to a certain size use max.
3: There are two types of elements inline and block, setting height and width (max or simple) will do nothing on an inline element (which a p, in your example, is not). You can set it to block in your css by adding display: block to the p css or use a div instead (which is block by default).