Padding on parent versus margin on child - html

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.

Related

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.

How to have only inner margins in wrapped float left list

I was wondering how I could have a wrapped list of <li> elements using float: left; that didn't have any outer margins, only margins in between the elements. Here is an example of what I DON'T want as it has margins around the outside of the list whereas I want the border of the outer list to be touching the borders of the inner list items. Here is an example of what I DO want however I find this solution to be hacky, as it requires the use of a second container outside the <ul> to act as the list border, if you stick a border on the <ul> itself you will see that it is still 10px away from the list items, I also prefer avoiding negative margins unless I really need to use them.
It seems as though float is designed to pull elements like pictures to the side and allow text to flow either side of them, and not as a way to make horizontal wrapping list, due to the natural behavior of not considering floated child elements when determining height. Because of this I was also wondering if it would be better to use something like flexbox for things like this.
You're correct, this is a fundamental abuse of float. Flexbox would be one way to approach this, yes.

Why are the divs not affected by css?

The css only affects the first box. It does not make any sense. margin-bottom will only separate the first row from the second row and then it does not work. How do I fix this.
Here is a link to the test site. http://stack.x10.mx/
Your problem stems from the fact that both of the divs inside each srow div are floated, which means that the DOM doesn't count their height, and your srow divs essentially end up with a height of 0px. That's why you've had to set a bottom margin of 160px but only get a gap of 10px or so - your margin covers the entire height of the two items in each row, and then anything left over appears as the spacing. The second row's content is taller than 160px, so nothing is left over to appear as a gap.
The core problem is a slightly poorly coded layout, but if you wanted a quick (albeit slightly hacky) solution to this problem, just add <br style="clear:both;" /> inside each row, after the two content divs. This forces the DOM to recognise their height, which means your srow divs now have the correct height. Then, you can change the bottom margin of the row to something sensible like 10px, knowing that the layout will be calculated correctly.
Why is all the css inline? In a CSS file, or the element in the head, add:
.sdw{
margin-bottom: 5px;
}

How does browser combine two block elements?

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
}

CSS - make div's inherit a height

I'm trying to make a box with rounded corners where the height and width of the div depends on the content, so it's automatically adjust to it...
You can see the example here: http://pastehtml.com/view/1duizyf.html
The problem is that i can't get the "test_mid_left" (black background) and "test_mid_right" (turquoise background) to inherit the height from the "test_mid_center" (green background). I have tried height: 100% and auto, but none of thoose work. So how do I get them to inherit the height from the content?
(The reason why I have used "min-height: xx" in the left and right content on the example is just to show which boxes I am talking about)
As already mentioned this can't be done with floats, they can't inherit heights, they're unaware of their siblings so for example the side two floats don't know the height of the centre content, so they can't inherit from anything.
Usually inherited height has to come from either an element which has an explicit height or if height: 100%; has been passed down through the display tree to it.. The only thing I'm aware of that passes on height which hasn't come from top of the "tree" is an absolutely positioned element - so you could for example absolutely position all the top right bottom left sides and corners (you know the height and width of the corners anyway) And as you seem to know the widths (of left/right borders) and heights of top/bottom) borders, and the widths of the top/bottom centers, are easy at 100% - the only thing that needs calculating is the height of the right/left sides if the content grows -
This you can do, even without using all four positioning co-ordinates which IE6 /7 doesn't support
I've put up an example based on what you gave, it does rely on a fixed width (your frame), but I think it could work with a flexible width too? the uses of this could be cool for those fancy image borders we can't get support for until multiple background images or image borders become fully available.. who knows, I was playing, so just sticking it out there!
proof of concept example is here
The Problem
When an element is floated, its parent no longer contains it because the float is removed from the flow. The floated element is out of the natural flow, so all block elements will render as if the floated element is not even there, so a parent container will not fully expand to hold the floated child element.
Take a look at the following article to get a better idea of how the CSS Float property works:
The Mystery Of The CSS Float Property
A Potential Solution
Now, I think the following article resembles what you're trying to do. Take a look at it and see if you can solve your problem.
Equal Height Columns with Cross-Browser CSS
I hope this helps.
The negative margin trick:
http://pastehtml.com/view/1dujbt3.html
Not elegant, I suppose, but it works in some cases.
You need to take out a float: left; property... because when you use float the parent div do not grub the height of it's children... If you want the parent dive to get the children height you need to give to the parent div a css property overflow:hidden;
But to solve your problem you can use display: table-cell; instead of float... it will automatically scale the div height to its parent height...
Most of the times, the Previous parent has a heigt manually set, so you can use that value as reference, no other dirty tricks will be needed, and if the number is not the same for any reason maybe a comment can be added with the original number so in case you need to change it, by searching at the all the values, this one can be adjusted or even changed, in the time someone resolve this one for us.