HTML inline elements and vertical/horizontal margins - html

In the fiddle - http://jsfiddle.net/dddaaLwL/ you can see that horizontal margins have an effect on the inline elements. and vertical margins do not have an effect. Is this right? why so?
#s1 {
margin-left: 40px;
}
#s2 {
margin-top: 40px;
}

Yes your fiddle is correct. why?
An inline element occupies only the space bounded by the tags that
define the inline element.
More info HERE
Examples of Inline Elements:
<a>,<span>,<b>,<em>,<i>,<cite>,<mark>, and <code>
More about Inline Elements
An inline element has, but may not be limited to, the following characteristics:
Flows along with text content, thus
Will not clear previous content to drop to the next line like block
elements Is subject to white-space settings in CSS
Will ignore top and bottom margin settings, but will apply left and
right margins, and any padding
Will ignore the width and height properties
If floated left or right, will automatically become a block-level
element, subject to all block characteristics
Is subject to the vertical-align property
More info HERE

Actually, vertical margins do have an effect on inline elements, but because the element above it isn't a block, it's actually using the margin from the top of the page instead of the previous element. Let's take a quick look at the box model:
Because inline elements don't handle bounding in the same way that block type elements do. They can only hold data, and other inline elements, and they follow the constraints of the parent element, and only exert influence over their individual space.
However, if they were inline-block elements, you'd see a different result:
As you can see, inline-block elements can actually influence the behaviour of other elements, whereas inline elements do not.
See Also:
MDN Documentation on Inline Elements
MDN Documentation on Block-level Elements

Have a look at below jsfiddle
#s1 {
margin-left: 40px;
}
#s2 {
margin-top: 100px;
}
<span id="s1"> span 1 </span>
<br>
<br>
<span id="s2"> span 2 </span>
<p id="s2"> p 3 </p>
p and div elements are block level elements where span is an inline element and hence margin on span wont work.

Related

How to determine height of content-box of a block and inline element

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.

Box Model for Inline Elements

W3C's CSS2.1 specification, chapter 8.6 The box model for inline elements in bidirectional context, states:
For each line box, UAs must take the inline boxes generated for each
element and render the margins, borders and padding in visual order
(not logical order).
When the element's 'direction' property is 'ltr', the left-most
generated box of the first line box in which the element appears has
the left margin, left border and left padding, and the right-most
generated box of the last line box in which the element appears has
the right padding, right border and right margin.
Questions
It says "left-most generated box", which indicates that the inline-level element creates more than one inline-level box. Is that because at each line break it creates a new anonymous inline-level box?
Why does the padding/border of inline boxes behave as below? Insight into why it shows up the way it does, with basis in the CSS specification, would be greatly appreciated.
.test {
margin: 0 10px;
padding: 20px;
border: 5px solid blue;
}
<span class="test">test2test2test2test2test2test2test2 test2test2test2test2test2test2test2test2test2test2 test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2test2</span>
For the second question you may 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.)
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.
.test {
margin: 0 10px;
padding: 20px;
border: 5px solid blue;
}
div {
border:1px solid red;
margin:50px 0;
}
<div>
<span class="test">test2test2test2test2test2test2test2 test</span>
</div>
<div>
<span class="test">test2test2test2test2test2test2test2 test st2test2test2test2 test st2test2test2test2 test st2test2test2test2 test</span>
</div>
<div>
<span class="test" style="line-height:50px;">test2test2test2test2test2test2test2 test2test2</span>
</div>
<div>
<span class="test" style="line-height:50px;">test2test2test2test2test2test2test2 test2test2 test2test2test2test2test2test2test2 test2test2</span>
</div>
To answer the first question:
It says "left-most generated box", which indicates that the inline-level element creates more than one inline-level box. Is that because at each line break it creates a new anonymous inline-level box?
Yes, but that's only one reason. An inline-level element can create zero, one or many inline-level boxes. So an inline element with no content or horizontal padding, border, or margin will create zero inline-level boxes. A different way in which an element can create multiple inline-level boxes is if the element contains child elements.
So if we have <span>foo <b>bar</b> baz</span>, then even if that all sits on one line, the span will create one inline-level box for foo, which will get the left margin, left border and left padding, and a separate inline-level box for baz, which will get the right margin, right border and right padding.
The b element creates the inline-level box for bar, which may have its own margins, borders, and paddings.
See Temani's answer for your second question.

Why don't containers expand to fit their inline elements

I simply have a container like a div or a button which contains an inline element with padding - the container doesn't grow to fit the inline element.
button, div {
background: blue;
}
span {
background: orange;
/*display: inline-block; */ /* toggle to see container element grow */
padding: 4em;
}
hr {
margin:100px;
}
<div>
<span class="btn__content">
I'm div inline content
</span>
</div>
<hr>
<button class="btn" type="button">
<span>
I'm button inline content
</span>
</button>
Why does this happen?
NB: I'm not looking for a fix - (for instance, I already know that I could display:flex on the container and that would make the container expand to the content)
Rather, I'm looking for an explanation from a credible source like the spec which explains this behavior of inline elements.
The reason is explained in the Visual Formatting model documentation (emphasis mine):
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.
The width of a line box is determined by a containing block and the
presence of floats. The height of a line box is determined by the
rules given in the section on line height calculations.
The line height is then calculated as:
The height of a line box is determined as follows:
The height of each inline-level box in the line box is calculated. For
replaced elements, inline-block elements, and inline-table elements,
this is the height of their margin box; for inline boxes, this is
their 'line-height'. (See "Calculating heights and margins" and the
height of inline boxes in "Leading and half-leading".)
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.
The line box height is the distance between
the uppermost box top and the lowermost box bottom. Empty inline elements
generate empty inline boxes, but these boxes still have margins,
padding, borders and a line height, and thus influence these
calculations just like elements with content.
And as MDN notes about the box model:
Note that, for non-replaced inline elements, the amount of space taken
up (the contribution to the height of the line) is determined by the
line-height property, even though the border and padding appear
visually around the content.
and reiterated by the W3 for inline non-replaced elements:
The 'height' property doesn't apply, but the height of the box is
given by the 'line-height' property.
https://www.w3.org/TR/REC-CSS2/visudet.html#q15
Where the line height is "the height that is used to calculate line box height." So while padding or borders might give the look of height to an inline element, only the line-height property will affect parent nodes. As you can see in the example below, the line height on the spans is affecting the height of the parent div.
button,
div {
background: blue;
}
span {
background: orange;
line-height: 10em;
}
hr {
margin: 100px;
}
<div>
<span class="btn__content">
I'm div inline content
</span>
</div>
<hr>
<button class="btn" type="button">
<span>
I'm button inline content
</span>
</button>
See also Inline elements and line-height
I believe it's because of these two sections:
9.4.2 Inline formatting contexts
The height of a line box is determined by the rules given in the section on line height calculations.
10.8 Line height calculations: the 'line-height' and 'vertical-align' properties
The height of each inline-level box in the line box is calculated. For replaced elements, inline-block elements, and inline-table elements, this is the height of their margin box; for inline boxes, this is their 'line-height'.
Setting a line-height does change the height of the containing box
button, div {
background: blue;
}
span {
background: orange;
/*display: inline-block; */ /* toggle to see container element grow */
padding: 4em;
line-height: 8em;
}
hr {
margin:100px;
}
<div>
<span class="btn__content">
I'm div inline content
</span>
</div>
<hr>
<button class="btn" type="button">
<span>
I'm button inline content
</span>
</button>

Why does text-align center headers?

Why does text-align: center headers?
Headers are block elements h1,h2,etc. Why is it that text-align centers headers even though the documentation specifically says it does not: Docs on text-align
This property describes how inline-level content of a block container
is aligned.
I'm a little confused as to why it wont center a block element like a div, but willing to center a header. Could it potentially be because text inside a header is inline, but the actual header itself is a block element?
http://codepen.io/stephenhuh/pen/KrkLZG - codepen on this phenomenon.
* {
text-align: center;
}
.box {
background-color: blue;
width: 150px;
height: 150px;
}
From CSS 2:
Any text that is directly contained inside a block container element (not inside an inline element) must be treated as an anonymous inline element.
Like everyone else has already explained, it is centering the text content inside the header element. I'd just like to add that you can easily test this by adding a border or background to elements. If you do this, you'll notice that the header will span the entire width of its container by being a block element, and the text will only be centered inside that block.
(Alternatively, you could use an inspector to show the actual space an element is occupying)
The property text-align affects specific children of the parent that the property was assigned; namely inline type children. Text is inline, as well as spans and inputs unless otherwise overridden by CSS. If you need to center a block level element (horizontally) use margin:0 auto;.

Any difference between aligning elements in a float div versus a regular div?

I've used "margin: 0 auto" on <p>, <a>, and <img> elements inside a float div but it doesn't seem to affect them. Therefore, I manually aligned them by "margin-left." It looks ok but I'd rather apply a uniform rule to all elements in the div. Thank you.
The float div:
#side {
float: left;
width: 300px;
height: 630px;
background-color: white;
border-radius: 10px;
}
If I understand you correctly, you are trying to centrally align all the elements (p, img, and a) inside the floated div.
Out of the 3 html elements you specified, <p> is a block level element, but <img> and <a> are inline elements. In order for you to use margin: 0 auto all the elements should have a width specified. And the width can only be specified for the block level elements.
So you can use the property display: block for the inline elements like a and img which will convert them to a block level element. And then you can specify the width property for all the elements inside the div (including p, a, and img). Once the width for all the elements are specified, now you can use margin: 0 auto and it should work perfectly fine.
If you want the text inside the div to be centrally aligned all the time, then you can use the css property called text-align: center on the div.
The layout inside a container is not affected by whether the container is float or not. That only affects where the container is positioned, not how the child elements inside the container are positioned.
The elements you are trying to use margin on are inline elements, not block elements.
With things like margin: 0 auto, the auto applies to block elements that would normally go full width, not inline elements which will normally be only as wide as their content.
For inline elements, you may want to use text-align: center, but we'd really have to see your exact HTML and the desired layout in order to know exactly what to recommend.