Why is there space between line boxes, not due to half leading?
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 em
1 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>
Remove white space above and below large text in an inline-block element
It appears as though you need to explicitly set a font, and change the line-height
and height
as needed. Assuming 'Times New Roman' is your browser's default font:
span {
display: inline-block;
font-size: 50px;
background-color: green;
/*new:*/
font-family: 'Times New Roman';
line-height: 34px;
height: 35px;
}
<span>
BIG TEXT
</span>
Understanding CSS2.1 specification regarding height on inline-level boxes
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.
Why the text in an element with display:inline;line-height:0 , still has different yAxis position in different rows?
To get the same result you need to apply the same font-size
and line-height
to the parent container
.parent {
border: 1px solid red;
margin: 100px;
width: 300px;
}
.child1 {
display: inline;
/*line-height:0;
font-size: 50px;*/
word-break: break-all;
}
.child2 {
display: inline-block;
line-height: 0;
font-size: 50px;
word-break: break-all;
}
<div class="parent" style="line-height:0;font-size: 50px;">
<span class="child1">Why Is There Space Between Line Boxes, Not Due to Half LeadingWhy Is There Space Between Line Boxes, Not Due to Half Leadingaaaaaa</span>
</div>
<div class="parent">
<span class="child2">Why Is There Space Between Line Boxes, Not Due to Half LeadingWhy Is There Space Between Line Boxes, Not Due to Half Leadingaaaaaa</span>
</div>
List of blocks and inline-blocks show incorrect vertical spacings
Because the inline one has to be positioned inside the line height of its container.
If you set the container's line-height
to 10px
(the body
in your examples) it will work fine.
Line height issue with inline-block elements
The line-height
is applying but you need to understand how it's applying. If we refer to the specification:
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
By setting line-height:5
on the parent element you set a minimum height for the linebox.
On a non-replaced inline element, 'line-height' specifies the height that is used in the calculation of the line box height.
By setting line-height:1.5
you defined the height of your element inside the linebox.
To make it easier, you have an element with a height equal to 1.5
inside a linebox with a height equal to 5
1 but you cannot visually see this. If you inscrease the line-height of child and you reach 5
you will then reach the minimum height and you will start increasing the linebox previously defined by the parent element.
To see this you need to apply vertical-align
. If the line height of child element is smaller than the line height of the parent (the height of the child smaller than the height of the linebox) you can align:
.container {
max-width: 200px;
border: 2px black solid;
line-height: 5;
}
.container>a {
line-height: 1.5;
}
<div class="container">
<a>First</a>
<a style="vertical-align:top;">Second</a>
<a>Third</a>
<a style="vertical-align:bottom;">Fourth</a>
</div>
Why does unitless line-height behave differently from percentage or em in this example?
Based on clues in the proposed answers, I think the rendering behavior seen in these examples is counterintuitive, but correct, and mandated by the interaction of several rules in the spec, and the overall CSS box model.
CSS calculates the leading L needed for a box by the formula
line-height
= L + AD, where AD is "the distance from the top to
the
bottom"
of the font. Then "half the leading is added above A and the other
half below D." So text that hasfont-size:16px
andline-height:24px
will have 4px of leading above and below. Text
thatfont-size:8px
andline-height:24px
will have 8px of leading
above and below.By default, however, "user agent must align the glyphs ... by their
relevant
baselines.".
This starts to explain what's happening here. Whenline-height
is
specified by percentage or em, a computed value is inherited by the
child (here, thesmaller
span). Meaning, thesmaller
span gets
the sameline-height
as the parent block. But because of the L +
AD formula, the text of that span has more leading on the top and
bottom, and thus the baseline sits higher in its box. The browser
pushes down thesmaller
span vertically to match the baselines.But then the browser has a new problem — how to deal with the line
spacing in the enclosing block, which has been disrupted by this
baseline-adjusting process. The spec resolves this too: theline-height
of a block-level element "specifies the minimal
height of line boxes within the
element".
Meaning, CSS makes no promise that you'll get your exactline-height
, just that you'll get at least that amount. So the
browser pushes the lines apart in the enclosing block so that the
realigned child box will fit.
The reason this is counterinitutive is that it's the opposite of how most word processors and page-layout programs work. In these programs, a smaller stretch of text within a paragraph is aligned by its baseline (like CSS) but line height is enforced as a distance between baselines, not as a box surrounding the smaller text. But that's not a bug — CSS is designed around a box model. So in the end, we could say that this spacing behavior is a consequence of that model.
That still leaves us to explain the behavior in the example with the unitless line-height:
First, note that when no
line-height
is specified, the browser
will apply a unitless line-height by default. This is required by
the
spec:
the initial value ofline-height
isnormal
, which is defined to
have "the same meaning as <number>", and the spec recommends a
value "between 1.0 and 1.2". And that's consistent with what we see
in the examples above, where the paragraphs withline-height: 1.5
have the same behavior as the paragraphs with no line-height setting
(i.e., they are impliedly gettingline-height: normal
)As others have pointed out, when the paragraph has
line-height: 1.5
, the calculated line-height of the paragraph is
not inherited by thesmaller
span. Rather, thesmaller
span
calculates its own line height based on its own font size. When the
paragraph hasline-height: 1.5; font-size: 14px
, then its
calculated line height is 14px * 1.5 = 21px. And if thesmaller
span only has the propertyfont-size: 50%
, then its font size is
14px * 50% = 7px, and its line height is 7px * 1.5 = 10.5px (which
will generally be rounded to a whole pixel). But overall, thesmaller
box is half the size of the surrounding text.As before, the browser will vertically align the
smaller
span to
the adjacent baseline. But this time, because the box aroundsmaller
is shorter than the surrounding text, this realignment
doesn't have any side effects in the enclosing block. It already
fits, so there's no need to spread the lines of the parent paragraph, as
there was before.
Both cases represent a consistent implementation of the spec. That's good news, because it means we can predict the line-spacing behavior.
That brings us back to the original reason for this question. While I now understand that the CSS box model requires this behavior, as a practicing typographer, this is rarely the behavior I want. What I want is for the lines within a paragraph to have consistent & exact line spacing, even if some spans of text within that paragraph are smaller.
Unfortunately, it seems there's no way to directly enforce exact line spacing in CSS as one can in a word processor or page-layout program. Again, this is because of the CSS box model: it doesn't use a baseline-to-baseline line-spacing model, and line-height
is specified to be a minimum measurement, not maximum.
But we can at least say that unitless line-height values produce the best approximation of exact line spacing in CSS. Fussy typographers like myself should feel comfortable using them, because unitless values are endorsed by the spec, and they produce consistent results across browsers. They are not a hack, nor are they deprecated.
The caveat is that they're still only an approximation. Unitless line-height values don't change the underlying CSS box model, nor the CSS box-positioning rules. So it's possible that in some edge cases, they won't have the intended result. But eternal vigilance is the price of good typography. Be careful out there.
alignment box for inline-block non-replaced elements
The statement
for inline non-replaced elements, the box used for alignment is the box whose height is the 'line-height'
does not apply to inline-blocks. Inline-blocks are not inline elements. Inline elements are elements with display: inline
, and generate inline boxes. Inline-blocks are not inline boxes, but inline-level (the "-level" part is important!) block container boxes. Therefore, the statement
For all other elements, the box used for alignment is the margin box.
applies instead, which results in vertical-align: text-top
causing the top outer edge of the inline-block to align with the top of the line box.
Any part of the specification that is said to apply to inline elements does not apply to inline-blocks.
Related Topics
How to Add a Tool Tip to a Span Element
Make <Body> Fill Entire Screen
Make Row Stretch Across All Columns in CSS Grid
Easiest Way to Extract the Urls from an HTML Page Using Sed or Awk Only
Create a Slanted Edge to a Div
Do I Need a "/" at the End of an <Img> or <Br> Tag, etc.
How to Keep Footer at Bottom of Screen
Bootstrap 3: Push/Pull Columns Only on Smaller Screen Sizes
How to Hide Columns in HTML Table
HTML + CSS: Ordered List Without the Period
CSS Image Resize Percentage of Itself
Heading with Horizontal Line on Either Side
Flexbox Affects Overflow-Wrap Behavior
Center Image Element in Parent Div
How to Give a CSS Class Priority Over an Id
Form and File Upload with HTMLservice and App Script Not Working