Simple HTML / CSS box model confusion - html

Using this really simple html / css (http://jsfiddle.net/XXzTj/)
<div style="background-color:red;">
<div style="margin:12px; background:blue;">hello</div>
</div>
The margin is spaced 12px all round correctly, but I was expecting the red background of the parent element to be shown in the top and bottom 12px spaces, instead its just 'blank space'.
Am I going mad or have I done something wrong?

try this --
<div style="background-color:red;height:auto;overflow:hidden;">
<div style="margin:12px; background:blue;">hello</div>
</div>
http://jsfiddle.net/XXzTj/1/

The child div is forcing the parent div to be rendered offset from its surroundings because you are using the margin property. Since the parent div has no content the browser has no reason to apply styling above or below the child div.
In order to honour the margin properties of the child div, however, which does have content, the parent div is rendered with its background either side of the content.
To have the browser render it in the way I imagine you expect, you would need to apply the padding style. Again, that's because the parent div has no content. Padding forces its styles to be rendered within the area because padding essentially acts like space that content would fill up.

It's collapsing margins in action. Either use padding for parent element instead of margin for child one, or create new context by setting position: relative, overflow: auto/scroll/hidden, or add generated content (:before and :after pseudoelements) with display: block to parent element to prevent margin collapsing.

Not too sure why that isnt working to be honest but this does work:
<div style="background-color:red; padding:12px;">
<div style="background:blue;">hello</div>
</div>
​

Related

How can I get a CSS margin to overlap with CSS padding to avoid redundant spacing?

Basically I have a wrapping <div> mean to add a border around something. It has a padding of 19px. Inside that wrapping <div> I want to insert pretty much any kind of content. Currently, it has another <div> inside. The problem is that that internal <div> has a bottom margin of 20px, so there is a space of 39px between the end of the internal <div> and the border, which just looks awkward.
As far as the question is concerned the relevant code is just
<div style="padding: 19px;">
<div style="margin-bottom: 20px;"></div>
</div>
I just want to know how I can make the margin of the inner div overlap the padding of the outer div (or alternatively be set to zero by CSS acting on the class of the outer div).
Is there a way to make the bottom margin of the last item in the wrapper overlap with the padding? Alternatively, could I simply set the margin of the last child of the wrapper to 0px?
I actually figured out a way that seems to work for the alternative option (setting the bottom margin of the last child of the wrapper to 0px). Here's the relevant CSS where "callout-box" is the class of the wrapper.
.callout-box > :last-child {
margin-bottom: 0px;
}
I'm still curious if there's a way to actually cause the margin and padding to overlap without removing the margin. In this case, there is a 1px difference since the solution I just gave sets the spacing to 19px whereas overlapping the margin and padding would give 20px.
I just want to know how I can make the margin of the inner div overlap the padding of the outer div (or alternatively be set to zero by CSS acting on the class of the outer div).
Answer:
Very simple just add negative top margin. Look at the code below.
<div style="padding: 19px;">
<div style="margin-bottom: 20px; margin-top:-19px;">Inner Div</div>
</div>

Strange behavior of an input html element with display: block

I'm trying to make some html form with help of bootstrap. Some of my inputs must have no gap from left or right side. But bootstrap .col-XX-Y blocks have gutter via paddings from left and right. So my idea was to use negative margin for my input elements, and display: block. And here I'm stuck.
Please refer to this codepen example. I was faced with several strange things for me:
Why input with display: block doesn't fill all it's parent
container, like div does? It fills the container only with: width:100%; (comment width for red-bordered input in codepen example)
Why if I'm apply negative margin-left to compensate parent container's
left padding, my input shifts to the left, but keeps it's original width (like if left css property was used). Doesn't it have to behave
like a block element (e.g. div): shifts to the left and keep
filling of all width of it's parent, excluding right padding?
When I'm apply negative right margin for my input to compensate parent's right padding, then nothing happens (look my example, compare orange div
with red input). Why? What about of a behavior like block element?
If this is normal behavior, can you give me some link to html standard docs with explanations of that.
If you don't want the padding on a grid parent element to effect its children, surround all its children elements in a block element with a class of row.
Bootstrap input elements are meant to span the whole width of there parent elements even without display block style attribute.
<div class="col-md-12">
<div class="row"> <!--this is what you need -->
</div>
</div>
full example code
<div class="col-md-12">
<div class="row">
<input type="text" placeholder='I\'m some damned input' />
</div>
<div class="row">
<div>I am some div</div>
</div>
</div>
Form elements do not behave the same way as regular block level elements. When you display an <input> field as block it will not fill the full width.
For this reason you need to make give the element width: 100%. This is how Bootstrap styles form elements.
Like any other block element, giving it a width of 100% will allow it to fill the width of its container. When you apply a negative margin-left, the width will still be the same (100% = containers width) which will cause the gap to appear.
I would suggest wrapping the <input> field in a <div> and apply the negative margin to that instead:
.wrap {
margin: 0 -20px;
}
.wrap input {
width: 100%;
display: block;
}

bootstrap row height 100% issue

I'm working on a project using the framework Twitter Bootstrap 3.
My basic HTML layout is.
Sidebar
Main content
The sidebar element has 100% height and float: left so that the div classed main-content stays inline.
When I give the sidebar float left property and add a row classed div in main-content div.
The height of .row goes crazy. But instead of float: left if I use position: fixed to the sidebar then the .row height gets adjusted according to content inside the .row.
I did play with the web console in Chrome and noticed that there are two pseudo elements created on row :before and :after.
When I unchecked the css property of those pseudo classes the height of the .row is to the height of the child.
Why do I have this issue when I use float: left to the sidebar?
How can I overcome it?
Did google on this, and I found this. But it doesn't help me.
Also I've created a fiddle to demonstrate the strange behaviour of the .row classed div where it extends to almost to screen of the height but there's nothing present inside the .row element.
Someone help me to get this clarified and fixed.
Thanks in advance.
EDIT : Why the height of the .row div is 100% when I didn't define it's height?
I find your mark-up a bit odd considering you are working with Bootstrap. Why don't you make use of the Bootstrap functionality to create your sidebar and main content div? This way you also don't run into unwanted "100% height divs".
Have a look: http://jsfiddle.net/GeA7N/3/
<div class="page-container">
<div class="row">
<div class="sidebar col-xs-4">
</div>
<div class="main-content col-xs-8">
<div class="well custom-well"></div>
<div style="background: red">Content div that is not 100% height by default</div>
</div>
</div>
</div>
Have you tried using http://www.layoutit.com as a guide for a layout? You don't have to register to use it. Once you get the columns setup correctly you can go in and and set the height of the columns with the style attribute on the div. Hope this helps a little bit
Children inherit attributes from parents, unless otherwise specified.
So let's specify a height for row and it will no longer inherit.
All I am adding is a row height attribute to overwrite both the parent's height attribute.
.row {
background-color:blue;
height:50%;
}
JSFiddle Demo Blue is to show the row div. The grey is just the underlying background of the page.
EDIT : Why the height of the .row div is 100% when I didn't define
it's height?
Reason: The ::before and ::after pseudo-elements of the .row class have the style display:table; thereby causing your first row to fill as much remaining space as it can.
Solution: To avoid overriding the Bootstrap framework, simply encapsulate your .container class with another div which has the style display:flex;

How to display parent div over child div

If I have this:
<div id='parent'>
<p>Parent stuff here</p>
<div id='child'>Child stuff here</div>
</div>
Is there a way to make the parent div appear overtop of the child div without using position:absolute? Basically, you wouldn't see the child div at all. z-index doesn't seem to work. I want to do this with a transparent PNG so that I can highlight certain divs on mouseover - the transparentness will allow the under stuff to still be seen a little.
Thanks!
z-index will only work if a position other than static (the default) is set on that element. Add position: relative; to the relevant element and z-index will work. Here is an example: http://jsfiddle.net/sl1dr/8gR6V/

why doesn't this div get the background?

Here there is the whole example of my divs.
Why doesn't footer get the background color from the parent (container)?
When you float an element, this is like it was disconnected from the parent. So, inherit values cannot be inherited. Also, the parent stops expanding to the children heights. Remove the float and you can see it working.
But if you really need the float, you need to put background-color on footer.
Remember that you can put another <div style="clear: both"></div> after footer like showed on another answer, but it is just a trick to that the parent can follow the child height.
You have to clear the floating div: http://jsfiddle.net/74MvW/14/
It doesn't get the bg color, because the "container" div has the background, but the "footer" div is floating to left, which means that it doesn't affect the "container" div's height.
You have to either get rid of the float or simply add a clearer div after the footer div like this:
<div class="container">
<div class="footer">
Hello
</div>
<div style="clear:both;float:none;"><!-- Clearer --></div>
</div>
As other answers have mentioned, the problem is the float value. The nicest way to get around this is to set the .footer div to "inherit" the parent's background:
.footer {width:910px; height:150px; float:left; background: inherit}
Demo.
Some CSS properties are inherited by default (e.g. font-family); others have default properties. In the case of background-color, the default is transparent. If you want the property to be inherited, you have to say so explicitly.