How does browser combine two block elements? - html

I'm confused by the calculation of elements. I know how the browser calculates the size of the element but I don't know how the browser treat two elements or more. Say I have two block elements, which have paddings, margins, and borders. How does browser treat them when:
one is on the left and another one is on the right?
one is on the top and another one is on the bottom?
one is inside another one?

I'm going to assume that the block elements do not have a set width.
Let's work backwards...
One inside the other: all margins, borders and padding are cumulative. The inner block will expand to fill the outer block unless otherwise specified. And the outer block will expand to fill the width of its container unless otherwise specified. The width of the inner block will be calculated based on the overall container width minus the combined margins, borders and padding of both the outer block and inner block itself.
One above the other: under normal circumstances the bottom margin of the top block and top margin of the bottom block will collapse so that your overall margin between the two is the greater of the two. Borders and padding remain unaltered. The 2 block elements will expand to take up the available width of their container unless otherwise specified.
One beside the other: there are basically 2 ways to make this happen: by setting the display property of the elements to inline-block or by floating both elements. Since your question specifically states "block elements", I won't deal with inline-block. As far as floating goes, all margins, borders and padding remain unaltered. As already mentioned, block elements will take up the width of their container unless otherwise specified. This means they won't float next to one another unless you set the width of each so that the combined width + margin + border + padding of both blocks is equal to or less than the width of the container.
Hope that helps.

Your question is a bit ambiguous, all elements have unique IDs or classes that's how the browser treats them all differently and you can add different styles to each one
<div id="container">
<div class="element1"></div>
<div class="element2"></div>
</div>
css styles
.element1 {
float:left;
background:red;
border-style: solid 2px
}
.element2{
float:right;
background:yellow;
border-style: solid 5px
}

Related

Do fixed and absolutely positioned elements not take the full width of their container like block elements? If yes then why?

From this post I came to know that absolutely positioned elements do not behave as block level elements.
"Because absolutely positioned elements do not behave as block level elements and do not flow after each other like normal adoes."
From the discussion in comments it seems that absolutely positioned elements are still block-level elements. The only difference is that they do not take the full width of their parent container. I figured out that the same is true for fixed positioned elements too. I tried the following code. In this code two boxes are shown. One is statically positioned and second is absolutely positioned. It can be seen that statically positioned box takes the full width of it's parent container(viewport). But the absolutely positioned box doesn't take the full width of it's parent container(viewport).
<!DOCTYPE html>
<html>
<style>
.abslnowidth {
position: absolute;
display: block;
border: 1px dotted black;
padding: 10px;
background-color: gray;
}
.staticyeswidth {
position: static;
background-color: bisque;
padding: 15px;
border: 1px dotted black;
}
.abslnowidth:hover, .staticyeswidth:hover {
color:red; background-color: yellow;
}
body {
text-align:center;
border: 2px solid darkgreen;
}
</style>
<body style="">
<p>Two boxes are shown below, viz, the gray and bisque colored boxes. The gray colored box is absolutely poistioned and the bisque colored box is statically positioned <br></p>
<div class="abslnowidth">
Absolutely positioned
</div>
<div class="staticyeswidth">
Statically positioned
</div>
</body>
</html>
Note that the the fixed positioned box behaves similar to absolutely positioned box in that that it also doesn't take the full width of it's parent container.
Much to my surprise, I noticed the fixed/absolutely position element doesn't behave like block-level elements even if I explicitly set display: block; It kind of behaves like inline or inline-block elements, as inline or inline-block elements do not take the full width of their parent container.
Precise Question:
Are absolutely/fixed positioned elements still block-level elements?
Do fixed and absolutely positioned elements not take the full width of their container like block elements are supposed to take? If yes then why? If it is defined this way for some specific purpose then what is that purpose. Please note that I'm not asking for unilateral opinion. I mean if someone really knows why this feature exists and what would be the practical downsides, had it been not this way. Or in other words,
Would there be technical downsides to the web-design if the absolutely/fixed positioned boxes were made to take the full width of their container. My guess is that absolutely/fixed positioned block are supposed to be adjusted. E.g. see this code used to make tool-tip. The black tooltip section should not take the whole width of "Hover over me" box because then we'd have to manually set the width of tool tip box. So I think that's a good reason to define absolutely/fixed positioned boxes to not take the width of their container.
Please provide some good reference e.g. w3 official documentation if possible.
This question could have different possible answers depending on what kind of block behavior you're expecting or referring to.
As per your comment above, the following answer refers to the width behaviour of such element.
Normally, block-level elements per default take up the full available width of their container element. However, when you set position: fixed or absolute the element isn't displayed in the same sense as with the rest of the elements.
As per MDN:
A block-level element occupies the entire space of its parent element (container), thereby creating a "block."
As such, the meaning of the container for a block-level element makes alters when refering to absolute or fixed positioned elements. It makes more sense to rather call it the parent.
Since there is no container element to inherit its width, you're seeing it behave more like an inline-block-type element.
Here's what the W3C says for calculating the width of an absolutely positioned, non-replaced element:
The constraint that determines the used values for these elements is:
left + margin-left + border-left-width + padding-left + width + padding-right + border-right-width + margin-right + right = width of containing block.
If all three of left, width, and right are auto: First set any auto values for margin-left and margin-right to 0. Then, if the direction property of the element establishing the static-position containing block is ltr set left to the static position and apply rule number three below;
This is true. You have not defined any values for width, left nor right nor do they inherit such values. As such they take the default auto. The direction property is indeed ltr as well, so we continue on to rule number three as suggested, which says:
width and right are auto and left is not auto, then the width is shrink-to-fit . Then solve for right.
The shrink-to-fit width rule applies, and goes as follows:
Calculation of the shrink-to-fit width is similar to calculating the width of a table cell using the automatic table layout algorithm. Roughly: calculate the preferred width by formatting the content without breaking lines other than where explicit line breaks occur, and also calculate the preferred minimum width, e.g., by trying all possible line breaks. CSS 2.1 does not define the exact algorithm. Thirdly, calculate the available width: this is found by solving for width after setting left (in case 1) or right (in case 3) to 0.
Then the shrink-to-fit width is: min(max(preferred minimum width, available width), preferred width).

Is width required to float two divs side by side using float:left property?

When I first learned HTML, I was told that if you want to float 2 divs side by side using float:left, you must set a width on those two elements. This is because a div, by default, is a block element, which will take up the full width it has available to it.
As I've built various projects, I have come across cases where floating did not work without setting a width, but then in other cases, it seems a width is not needed, and the float itself will restrict the elements width.
For example, the following fiddle shows two elements floating side by side only using the float property, no width was required.
<style>
.left{
background-color:yellow;
float:left;
}
.right{
background-color:green;
float:left;
}
</style>
<div class="left">
Floating left
</div>
<div class="right">
Floating left
</div>
However, in other similar scenarios that I can't seem to reproduce right now, applying the float property to two divs does not allow them to float side by side unless a width is a set for both.
Am I losing my mind or is there some scenarios for which this behavior varies?
When set float:left or float:right on an element, it forces the creation of a new block formatting context, and it behaves similarly to inline block level, the width and height are dynamic (determined by the content).
... a block element, which will take up the full width it has available to
it.
A non-replaced block element in normal flow will take up the full width it has available to it. This requirement is stated at http://www.w3.org/TR/CSS2/visudet.html#blockwidth
A floated element is not in normal flow, so that rule does not apply. Instead, float widths are determined according to their own rules, stated and described at http://www.w3.org/TR/CSS2/visudet.html#float-width. This says that when a floated element has a computed width of "auto", its used width is determined using the shrink-to-fit algorithm.
Note that the shrink-to-fit algorithm is also used for other types of layout, including non-replaced inline-block elements and table cells, but in other respects, such as vertical alignment, the layout behaviour of those elements is quite different from that of floats.

How does the margin collapsing of parent and first/last child work?

MDN says:
If there is no border, padding, inline content, or clearance to separate the margin-top of a block with the margin-top of its first child block, or no border, padding, inline content, height, min-height, or max-height to separate the margin-bottom of a block with the margin-bottom of its last child, then those margins collapse. The collapsed margin ends up outside the parent.
I don't understand the last sentence. Why does the collapsed margin end up outside the parent? If it ends up outside the parent, where will it go? I have searched the web and read several tutorials about margin collapsing, but I didn't find anything about this.
I threw together this little demo to help demonstrate the way this works:
http://jsfiddle.net/9pq8bm0o/
As you can see, I've made three elements, all nested within each other. The 2 inner containers both have a top margin value of 20px, and the outermost container has a top border (one of the things that is considered a margin separator).
So what does this mean?
Because there is no separation at the top of the two child elements, there is only 20px of space in between the outermost container and BOTH of the two child elements... the inner-most child has had it's margin collapse. Conversely, that margin that is there exists within the outermost container simply because of that border.. if you remove the border, all three elements will share the same 20px of margin which will be outside of all three containers.
So why is it like this?
The best way to think about margin collapsing is like this:
Asking for a margin on an element will ensure that it has that much margin at it's top, and nothing more (unless it's forced to have more).. So looking at my example, Does the middle .parent element have 20px of space above it? Yes, it does. Does the innermost child .child have 20px of space above it? Yes, it also does... so the margin rule is being applied correctly. It doesn't matter where that space lives, as long as it is there.
Imagine that there was a border around the .parent element, but the margin was still displayed the way it is without, and then ask those same questions.. Does the .parent element have the space? Yes, but does the .child element? No, it no longer would, because there would not be 20px of space in between it and the border that is now sitting above it... So, in reality, the space does not collapse, so that both of those questions can be answered as a "yes".
I hope that helps.. it's a little less of a direct answer to your question, and more of the theory behind how it works, so to put things a bit more plainly:
tl;dr
Margin, unlike padding, is meant to add space outside of elements. Because of this, margin will always collapse to the highest parent element whenever possible, to ensure that space is always "outside". Because it is outside of the element, it can count towards multiple different elements, as they all share that "outside" space.

Padding on parent versus margin on child

When I want to place some (logically meaningful) div inside a (logical) container div with some space apart as below,
which of the two ways would be more logically correct?
Set the padding property of the container
Set the margin property of the div that is inside
Sometimes, I have more than one element in the container like this:
For such cases, I would need to set the space between the elements independently from the space surrounding the elements. For the space between, I cannot use the padding property of the container, and I have to go with the margin (-left or -right) of the elements inside. Taking this into consideration, for setting the space between the container and the elements, I am wondering whether it makes more sense to set the margin (-left, -right, -top, -bottom) of the elements or the padding of the container.
I use flexbox. And I also have the setting as box-sizing: border-box;. I am free to use CSS selectors such nth-child if necessary.
Consider what kind of gutter you want to add. Is it to seperate elements from each other? Is it to create space inside an element?
For gutter on all sides of an element, like the blue in your example:
Here, I'd use padding on the container. Logically, that's exactly what I want, so why consider anything else?
For gutter between elements on a row, like the space between the green elements in your second example:
Here, I'd use margin on the green elements. There's obviously a margin between them, so padding doesn't make a whole lot of sense.
When you use these two examples together, however, they create a problem where the margin on the green elements may be conflicting with their parent's padding. I manage this by removing the margins from the first and last children.
Additionally, you may want more of those fine, green elements on a new row. I usually clear on every row using an element wrapping the entire row with whatever appropriate method to clear the floats, so it makes a lot of sense to seperate the rows with a margin. Obviously, the same conflict with the parent's padding arises here, but it's easily handled in the same way (ie, removing the margin from the last row).
So, in short:
Padding on parent elements for gutter between its edges and its children.
Margin to seperate elements with the same parent from each other.
Remove margins from said children when its margin connects to the parent's padding (the first and/or last children in a row, the last child in a column).
Disclaimer: This is how I do things. I can't promise it's the most efficient way to do things, but it's the way that makes the most sense to me.
I prefer to set margin on the div that resides inside the container.
Suppose the black div below is the outer container with display: flex, width: 300px and height: 200px. When you assign padding: 30px padding to the outer div, this will result in 360px in width and 260px in height. Given that you won't expect the container to stretch, this will affect the elements around the container div. Hence, it is better to use margin on the inner div.
When you assign margin between the inner div and the container, the actual outer div won't move, and the margin will only affect the inner div, thus not affecting the elements around it.
If you are using box-sizing: border-box; then things will change accordingly, so it totally depends on what actual size the elements has to be. Using margin/padding on the inner elements will be the right way.
There is no hard-and-fast rule on this, because it all depends on context, and in complex designs, you usually have no choice but to use one or the other to get the desired result.
That said, you should try to group logically related rules together. For instance, when you have two HTML elements on a website that serve a similiar purpose, e.g. your outer <div> and another similar box (that should get no padding), then, all else being equal, it is better to set a margin on the inner <div>.
If, however, you are placing more than one element into the outer <div>, then you should in fact use a padding, because that takes care of all inner elements at once. #zzzzBov's answer works as well, but it relies on margin collapsing, which can be tricky to deal with.
edit: In your second situation, I usually combine padding and margin, like this:
.outer {
padding: 10px 15px 10px 5px
}
.inner {
margin-left: 10px
}
Probably looks complicated, but works regardless of margin collapsing and has served me very well.
It depends on how your subsequent content should render. If you're going to have multiple inner <div>s (green) separated by a similar amount of spacing, it will make sense to use margin so that the margin collapse allows the divs to render as:
+-------
| <- blue
| +----
| | <- green
| |
| +----
|
| +----
| | <- green
| |
| +----
|
+-------
Here is an example of some of the various options.

CSS Margin calculation

While i do understand the overall CSS box model in theory like padding, border, margin, my understanding is restricted to this individual parts.
I often gets confused how this is actually rendered by the browser. E.g. Like padding is within the border, but how is margin calculated?
Is it wrt the box border or with respect to the screen?
If we give both left and right margins, what takes higher precedence?
If there is a width as well as left/right margins, how does the actual rendering take place like is the width of box made first,then the padding or what is it like?
What difference does a float attribute added to this box with margin make?
The box consists of 4 sizes: outer to inner:
Margin - that's the space from the parent, it stacks with the parent's padding.
Border - that's the border's width, it can be specified with border: or border-width:
Padding - that's the space inside the box, if any content/elements inside that box will be spaced that from its sides.
Width - the actual box's width, may change according to content, 100%, or a fixed width as specified in width: or max-width:
An image for illustration:
A floated element takes margin into account, so if you have
#element { margin-left: 100px; float: left; }
it will float left, but will have a 100px margin from the left side.
"E.g. Like padding is within the border, but how is margin calculated?"
Study this: http://www.w3.org/TR/css3-box/#margins
"Is it wrt the box border or with respect to the screen?"
The calculation of margins is independent from the border and the screen. The browser calculates the value for the margin separately, and then decides how it's going to be applied (rendered).
"If we give both left and right margins, what takes higher precedence?"
An algorithm is specified here: http://www.w3.org/TR/css3-box/#blockwidth
Could you give a specific example?
"If there is a width as well as left/right margins, how does the actual rendering take place like is the width of box made first,then the padding or what is it like?"
The rendering is almost instantaneous, so what counts is the end result, not the order in which the browser renders the element's properties.
"What difference does a float attribute added to this box with margin make?"
Read here: http://www.w3.org/TR/css3-box/#floating
The used values of the margins are equal to the computed values,
except that the used values of any margins computed as ‘auto’ are ‘0’.