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

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 :-)

Related

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

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>

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.

Prevent span elements from wrapping

My UI shows a list of email addresses retrieved by backbone. It is currently rendered as a span of spans that contain spans. Here's some typical generated html:
But I am getting breaks inside the spans (notice the beginning of angelstwo is on two lines), probably because I am using the wrong html tags (ul and li sounds better for a list). It can look like this:
I tried divs but I got one entry per line and I don't want that.
Is there something I can do to make this work with spans? Or should I change to something else like ul and li?
span elements are, by default, inline elements. In an inline formatting context boxes can wrap. (This is what happens to text when it wraps around a floated image.)
div elements are, by default, block elements. In a block formatting context the boxes will occupy all available horizontal space (width: 100%).
This is why your spans and divs aren't working as you want.
If you switch from display: inline to display: inline-block, you'll get block-level like behavior, which will prevent wrapping line boxes, but elements will stack horizontally with other inline elements.
W3C References:
9.2.2 Inline-level elements and inline boxes
9.2.1 Block-level elements and block boxes

Child element's text is not aligned with parent's element text in Chrome when parent element has vertical-align: top

Consider this HTML:
<div id="x">Foo</div>
<div id="y">Bar <span>Baz</span></div>
And this CSS:
#x {
background: orange;
display: inline;
font-size: 200%;
}
#y {
background: cyan;
display: inline;
vertical-align: top;
}
Here is the JSFiddle demo: http://jsfiddle.net/ePBZz/
With Firefox 28.0 and Internet Explorer 8, both 'Bar' and 'Baz' appear on the same line. However, with Chrome 33.0, they do not appear on the same line.
(Output with Firefox on left; Output with Chrome on right)
From the 'Inspect element' feature of Firefox and Chrome I figure that in both cases the span element obeys the standard of using vertical-align: baseline (the default). So Chrome must be using a different definition of baseline for the span element than Firefox when vertical-align: top is used for the parent element, otherwise I do not know how to explain the difference in the output between Chrome and Firefox.
By the way, I know how to fix this code. By adding the following to the CSS.
#y span {
vertical-align: inherit;
}
This would force the child span element to inherit vertical-align: top from the parent #y element. However, that is not my question.
I want to know which one is the buggy behaviour and which one is the correct behaviour as per the W3C CSS standard for my code without the fix I mentiond later, or if the result of this kind of code is unspecified by the standard. If possible, please quote the sections from the W3C documents that clarifies the behaviour for such code.
After reading CSS 2.1 specification (W3C Recommendation 07 June 2011) it seems to me that both Chrome and Firefox are correct and they are free to choose different baselines.
Section 9.2.2. defines what an inline-level box is.
9.2.2 Inline-level elements and inline boxes
Inline-level elements are those elements of the source document that
do not form new blocks of content; the content is distributed in lines
(e.g., emphasized pieces of text within a paragraph, inline images,
etc.). The following values of the 'display' property make an element
inline-level: 'inline', 'inline-table', and 'inline-block'.
Inline-level elements generate inline-level boxes, which are boxes
that participate in an inline formatting context.
An inline box is one that is both inline-level and whose contents
participate in its containing inline formatting context. A
non-replaced element with a 'display' value of 'inline' generates an
inline box. Inline-level boxes that are not inline boxes (such as
replaced inline-level elements, inline-block elements, and
inline-table elements) are called atomic inline-level boxes because
they participate in their inline formatting context as a single opaque
box.
Section 9.4.2 defines what a line box is.
9.4.2 Inline formatting contexts
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.
Then section 10.8 mentions:
The inline-level boxes are aligned vertically according to their
'vertical-align' property. In case they are aligned 'top' or 'bottom',
they must be aligned so as to minimize the line box height. If such
boxes are tall enough, there are multiple solutions and CSS 2.1 does
not define the position of the line box's baseline (i.e., the position
of the strut, see below).
This seems to apply to the code at http://jsfiddle.net/ePBZz/. In this code, vertical-align: top has been applied to the div id="y" which has been defined as follows.
<div id="y">Bar <span>Baz</span></div>
There are two inline-level boxes in this element. The two inline-level boxes are:
Anonymous: "Bar"
SPAN: "Baz"
Now it is not clear what it really means for inline-level boxes to be tall enough, but if we assume that these two inline-level boxes are tall enough, then as per the last quoted text, the standard does not define the baseline of the line box that contains these two inline-level boxes. As a result, Chrome and Firefox are free to choose different baselines and align the baseline of the second inline level-box (SPAN: "Baz") with these differently chosen baselines, thereby producing different outputs.