Why a div with an empty inline-block has height? - html

div {
background:red;
}
<div><span style="display: inline-block"></span></div>
The w3c send
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. We call that imaginary box a "strut." (The name is inspired by TeX.).
https://www.w3.org/TR/CSS2/visudet.html#inline-box-height
But when the span display is 'inline', why the div's height are 0?
I am confused?

But when the span display is 'inline', why the div's height are 0?
Not 100% correct because if the span has at least one character the height will be different from 0. Even an invisible zero width space:
div {
background: red;
}
<div><span>​</span></div>
In case of an empty span (having display:inline) the browser will generate 0 line box. So inside your div there is no line box thus you have a height equal to 0.
Adding one character will trigger the creating of one line box and the rule you quoted will be used and the line-height will define the height of the line box and the height of a div is the height of its line box (since we only have one).
Same logic if you add an empty inline-block element. Even empty, an inline-block will trigger the creation of a line box.
Same logic if you use an empty img:
div {
background: red;
}
<div><img></div>
To use easy words, an inline-block element is still considered as an existing element and we need to generate a line box to hold it. An empty inline element will be considered by the browser as a non-existing element so we don't need any line box to hold something that doesn't really exist.
Line boxes are created as needed to hold inline-level content within an inline formatting context. Line boxes that contain no text, no preserved white space, no inline elements with non-zero margins, padding, or borders, and no other in-flow content (such as images, inline blocks or inline tables), and do not end with a preserved newline must be treated as zero-height line boxes for the purposes of determining the positions of any elements inside of them, and must be treated as not existing for any other purpose. ref

line-height only applies when there are actual lines inside an element, in your case, <span>.
Since you did not fill the element with any text, the div does not expand.
If you want to leave the span empty, try specifying height or adding margin to the span, like this:
div {
background: red;
}
span {
display: inline-block;
margin: 1em;
}
<div>
<span></span>
</div>

Related

Difference line box between empty inline and inline-block element

My understanding is that in an inline formatting context, line box stacks vertically. And the height of the container box is the distance from the top edge of the topmost line box to the bottom edge of the bottommost line box.
But what happens if the inline element and inline-block element is empty? I guess that no line box will be created in both cases and the container height would be 0.
However the empty inline-block element puzzles. Because its container has a positive height which equals to the line height. It really creates a line box!
Why the empty inline-block element creates a line box, but the empty inline element does not?
<!DOCTYPE html>
<html lang="en">
<body>
<div style="background:red">
<span style="display:inline-block"></span>
</div>
</body>
</html>
Essentially, this statement from CSS 2.2 Section 9.4.2 Inline formatting contexts
Line boxes are created as needed to hold inline-level content within an inline formatting context. Line boxes that contain no text, no preserved white space, no inline elements with non-zero margins, padding, or borders, and no other in-flow content (such as images, inline blocks or inline tables), and do not end with a preserved newline must be treated as zero-height line boxes for the purposes of determining the positions of any elements inside of them, and must be treated as not existing for any other purpose.
So inline-blocks explicitly stop the line containing them from being treated as zero height or not existing.
When you use display: inline it means the content will be in the same line(continuation) as whatever is before and after.
When you use display:inline-block, it begins the display in a new line followed by new content.
Here is a link for examples
https://www.w3schools.com/cssref/pr_class_display.asp
Elements with display: inline-block create a new block and the element will naturally expand to fill the container. Inline elements don't have a width or height property so they don't have any height or width unless there's some content inside it.

What's the exact containing block of an absolutely positioned element in the case the containing block is inline?

<style type="text/css">
body > div {
display: inline;
position: relative;
}
body > div > div {
position: absolute;
}
</style>
<div>
<div></div>
</div>
What's the exact containing block of the inner div?
In the case that the ancestor is an inline element, the containing block is the bounding box around the padding boxes of the first and the last inline boxes generated for that element. In CSS 2.1, if the inline element is split across multiple lines, the containing block is undefined.
What's the meaning of "the bounding box around the padding boxes of the first and the last inline boxes generated for that element" in the text above?
An inline element cannot "contain" a block-level box in the traditional sense. What happens is that that inline element gets split into individual inline boxes, which live in anonymous block boxes surrounding that block-level box. See section 9.2.1.1 past the first example:
When an inline box contains an in-flow block-level box, the inline box (and its inline ancestors within the same line box) are broken around the block-level box (and any block-level siblings that are consecutive or separated only by collapsible whitespace and/or out-of-flow elements), splitting the inline box into two boxes (even if either side is empty), one on each side of the block-level box(es). The line boxes before the break and after the break are enclosed in anonymous block boxes, and the block-level box becomes a sibling of those anonymous boxes. When such an inline box is affected by relative positioning, any resulting translation also affects the block-level box contained in the inline box.
(There is no translation happening here, so the last sentence is impertinent.)
Your case however is a little more special, since the only thing between the start tag of the outer div and start tag of the inner div, and end tag of the inner div and end tag of the outer div, is inter-element whitespace (including line breaks and indentation), which gets collapsed under normal circumstances. So the inline boxes that are generated end up being
empty, and
in the same position: the same position as the strut.
And since the inline element has no padding, the padding boxes of the empty inline boxes is measured to be zero in length, times the line height. (Note that some browser developer tools may render this as a single point marked by a crosshair when you inspect the outer div.) The containing block of the inner (absolutely positioned) div is defined by the perimeter of those padding boxes combined, and any offsets on the inner div (top, right, bottom, left) are relative to that perimeter. Note, however, that since the inline boxes don't actually have content, the actual position of the inner div is the same as the outer div, had the outer div had content.

Padding-left of inline container does not pad. Why? [duplicate]

This question already has an answer here:
What goes wrong when a display:inline custom element contains display:block elements?
(1 answer)
Closed 6 years ago.
Can anyone point me to specs?
x-x {
padding: 10px;
}
<x-x>
<div>1</div>
<div>2</div>
</x-x>
padding-left does not pad
however, padding-top and padding-bottom does
why is this?
http://codepen.io/geoyws/pen/NNJjPV
Your custom element (<x-x>) defaults to CSS initial values. So its display value is inline.
This element contains two divs, which are block-level elements.
Because an inline box cannot wrap a block-level box, the browser implicitly closes the <x-x> before it wraps the div.
Hence, the reason the left padding is not working is because the custom element is not actually wrapping the two divs. It's closed right before the first opening <div> (in effect, making the custom element and the divs more like siblings).
However, if you put a span in the custom element, the padding will work, because a span is display: inline by default, and it can be wrapped by another inline-level element (demo).
All this can be verified in dev tools. Highlight the custom element to see that it doesn't wrap the divs.
As described in the spec, inline-level boxes "break around" block-level boxes:
9.2.1.1. Anonymous block
boxes
When an inline box contains an in-flow block-level box, the inline box
(and its inline ancestors within the same line box) are broken around
the block-level box (and any block-level siblings that are consecutive
or separated only by collapsible whitespace and/or out-of-flow
elements), splitting the inline box into two boxes (even if either
side is empty), one on each side of the block-level box(es). The line
boxes before the break and after the break are enclosed in anonymous
block boxes, and the block-level box becomes a sibling of those
anonymous boxes. When such an inline box is affected by relative
positioning, any resulting translation also affects the block-level
box contained in the inline box.
You have set padding to x-x by 10px which having display: inline; by default where as the display property of its child is display: block; So by just adding display block to parent i.e. to x-x element along with padding: 10px; you will get your expected result.
x-x {
padding: 10px;
display:block;
}
Happy coding :-)

Why does display:inline cancel height?

I was making a menu with id menu which had the following set:
display: inline;
height: 200px;
Once I removed display: inline;, height worked again.
Why?
display: inline;
Are usually used to refer to text elements;
From the w3c page:
[inline] Causes an element to generate one or more inline boxes.
Therefore, the height you must set is the line-height property. From the w3c page:
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.
Notice here that you can control only the minimal height of your inline elements
Because the spec says so:
'height' … Applies to: all elements but non-replaced inline elements, table columns, and column groups
line-height, however, does apply to inline elements.
By making something display inline you are effectively making it the same as a span. As such the only valid height value is line-height since you are working on an inline element.
To render height values you would need to use a div tag or force your existing tab to render like a div / object which accepts height attributes. You can do this by setting display:block.
In essence you can render a div to work like a span by setting display:inline, and conversely render a span as effectively a div via display:block.
Span tag are meant for inline styling such as font size, colour, decoration, etc.

How Input Div Span elements respond to a float element placed above it?

We took a 300px wide div, in that we had a 100px wide label tag and had it float:left and immediately after that we took three scenarios. We placed:
an input with width:400px
a div with width:400px
a span with small text and large text
You can see how they are rendering here: http://realution.in/htmlcss/practise/repost.html
Can anyone explain why they are rendering so differently?
Also is <input> a block or inline element?
They render so differently because you set different css properties and use different elements in every example. Also adding the float to label but not to any other elements, and not giving any other elements the css clear property creates this rendering issue.
A proper explenation of floats is done on A List Apart
Inline: An inline element only takes up as much width as necessary, and does not force line breaks.
Block: A block element is an element that takes up the full width available, and has a line break before and after it.
from w3schools
The label element is a inline element. Adding the float: left removes it from the document flow and makes it a block element. The explicit display:block isnt necessary.
Most properties you use on a span element are useless unless you set it to display: block, float: left or display: inline-block. Right now the set height, width and margin are ignored. If you want to adjust the size of the span you can only use: line-height and padding
Both the label and input are inline elements. The input takes up a newline because it will never be able to fit next to anything. The size of the input is larger then its parent.
The css display: block doesnt really do much for a label in this case. Because it has a float and no other element does. In a good browser, you should not see any difference between the label with or without display:block except for the last example where the label will actually be on the left against instead of floating against the previous label
The div is displayed ontop of the label. This is because with the float: left the label is outside of the normal document flow. The div element is ontop of it, because the div is inside the normal document flow.
The text inside the div is next to the label and not ontop of it, because text has a default inline display. If you would remove the text from the label the text inside the div would align on the left.
Adding a clear: left to the div would restore the normal document flow, putting the div on a new line
The label both float left and the span is displayed after them. The width: 300px; on the span doesnt really do anything on inline elements. If you want it to have a width you should either float it, give it a display: block or display: inline-block
The height of the pink area is determined only by the span because this is the only element inside the document flow. adding overflow:hidden to the parent div or a empty div with clear:both after the last label will both fix the box to go around all elements inside it.
The labels still both float on the left, only this time the inline span is so big the email label cant float left of it, so it is positioned next to email but lower, where there is room. The room is there because the span is only 15 pixels high while the label is 20px high, this is for both elements determined by the line-height property