Derived from an actual problem with borders and margin on my site I have made this test example which I think acts a little strange:
<!DOCTYPE html>
<html>
<head>
<style>
body {
background-color:black;
}
.outer {
width:100px;height:100px;
}
.inner {
margin-top:40px;
height:20px;
border:1px solid red;
}
#outer-1 {
background-color:blue;
border-top:10px solid yellow;
}
#outer-2 {
background-color:green;
border-top:none;
}
#sep {
background-color:white;
}
</style>
</head>
<body>
<div id="outer-1" class="outer">
<div class="inner">
CONTENT
</div>
</div>
<div id="sep">TEST</div>
<div id="outer-2" class="outer">
<div class="inner">
CONTENT
</div>
</div>
</body>
</html>
Why does the top margin on ".inner" move "outside" when the border-top is removed in #outer-2? I would have thought the red border would have stayed inside the blue and green areas at relatively the same spot? but it doesn't.
Why? and is there a way to have it to look like I had imagined?
Because margins are evil (and tend to collapse -> is it a bug? margins of P element go outside the containig div). In your case you can simply add overflow:hidden; to .outer
http://jsfiddle.net/yhAaQ/
Your problem is that margins are exactly what the name states: they set margins to other elements, not positioning offsets. If two elements are next to eachother, with different margins, they will be placed the highest margin apart, that way both margins are satisfied. In this case, 2 margins are present with nothing separating them, so logically they collapse.
Using padding on the .outer should solve this, or relative positioning. Margins are stricly for maintaining distances to other elements.
The margin on the outer2 element is calculated from the bottom of the element above it with no top margin applied to the outer2 element. If you add border, however, it is calculated from the bottom of the border.
Also, when bottom and top margins are applied to elements that follow each other, they collapse, that is just the way the box model works.
If you want to control the offset of an element inside another element, use padding.
body{/* just a reset to simplify example */
padding:0;
margin:0
}
.inner {
margin-top:40px;
height:40px;
width:40px;
background-color:blue;
}
#outer{
background-color:green;
height:60px;
width:60px;
}
<div id="outer">
<div class="inner">
<div class="inner">
<div class="inner">
<div class="inner">
test
</div>
</div>
</div>
</div>
</div>
Above code is a more general case of the problem you mentioned. All .inner are having margin-top=40px in CSS. But in reality, since there is no border involved, all the margins just collapse down to one final margin of 40px which "bubble up" outside of root parent.
Related
My pages are structured as nested divs. They have padding and margin so inner divs are typically physically smaller than outer divs. However, in some cases I would like one of the inner divs (red box in the image below) to expand widthwise to match the left and right edges of the outermost div.
<div id="div-a">
<div id="div-b">
<div id="div-c">
<div id="div-d">
</div>
</div>
</div>
</div>
This is just an example -- the number of nested divs can vary. The width of the outermost div is variable. The heights of all the divs are also variable.
I have tried using absolute positioning, but this removes div-d from the document flow. Since I don't know the height of its content, I can't compensate. Any other suggestions? Thank you for any help.
#div-a {
position:relative;
}
#div-d {
position:absolute;
left:0;
right:0;
}
Could this approach be a solution?
#div-c {
position:relative;
}
#div-d {
position:absolute;
padding:0 -(div-c + div-b + div-a padding values) 0 -(div-c + div-b + div-a padding
values)}
#div-c {
display: flex;
align-items: center;
}
#div-d {
width: calc(100% + PADDINGS + BORDERS);
}
PADDINGS: sum of each parents divs padding.
BORDERS: sum of each parents borders.
Unfortunately I could not find a CSS-only solution for my particular problem. I had to resort to Javascript.
wrap the div that needs to be full-width with another div
<div id="div-a">
<div id="div-b">
<div id="div-c">
<div id="div-d-wrapper">
<div id="div-d">
</div>
</div>
</div>
</div>
</div>
use this CSS
#div-a {
position:relative;
}
#div-d {
position:absolute;
left:0;
right:0;
}
apply the following Javascript (using jQuery)
$('#div-d-wrapper').height($('#div-d').outerHeight());
div{
padding:10px;
border: 1px solid red;
}
#div-d{
margin-left:-32px;
margin-right:-32px;
}
i used hard code values to for the given div . My solution is to use Negative margins in css. When the div grows dynamically, you use javascript or jquery to find parent reach from child div and calculate the margins accordingly.
fiddle demo: https://jsfiddle.net/bqrxtLvd/
Source:
Negative margin css tricks
Detailed negative margin
If I have some HTML:
<div class="wrapper">
<div class="first"> </div>
<div class="second"> </div>
</div>
And some CSS:
.wrapper{
font-size:0px;
padding-top:200px;
background:rgba(255,0,0,.2);
}
.first{
display:inline-block;
width:25%;
height:300px;/*Actually the height will be dependent on text.*/
background:black;
position:relative;
bottom:100px;
}
.second{
display:inline-block;
width:75%;
height:100px;/*Height actually dependent on text*/
background:green;
}
NOTE: The heights are not really fixed. They are dependent on text.
See JSFiddle here.
How do I make the wrapper only wrap the contents and not wrap the space that remains when you move the column up? I want there to be no pink underneath the black column.
I tried every combination of overflow:auto/hidden/visible/etc I could think of, and I googled and found information that it's not possible to do with position:absolute, but I couldn't find anything regarding position:relative.
Thanks!
You can try adding margin-bottom:-100px; to this code(to .first class).
I'm trying to play with positioning in css and I noticed something that confused me. It's probably a dumb question...but I'm having trouble understanding it.
I created three divs with the width and height of 50px with different background colors. When I position the third div up -60px using margin-top, the third div is on top of the second div. However, when I make the first and second divs inline elements, then both the first two divs are now on top of the third one.
Can someone please explain this concept to me?
<head>
<style>
<!-- Divs with the same width and height. Second one where both the first two divs are inline below this one. -->
#one{
background-color:red;
width:50px;
height:50px;
}
#two{background-color:blue;
width:50px;
height:50px;
}
#three{background-color:green;
width:50px;
height:50px;
margin-top:-60px;
}
</style>
</head>
<body>
<div id="one">
</div>
<div id="two">
</div>
<div id="three">
</div>
</body>
<head>
<style>
<!-- First two divs are inline -->
#one{
background-color:red;
width:50px;
height:50px;
}
#two{background-color:blue;
width:50px;
height:50px;
}
#one, #two{display:inline-block;}
#three{background-color:green;
width:50px;
height:50px;
margin-top:-60px;
}
</style>
</head>
<body>
<div id="one">
</div>
<div id="two">
</div>
<div id="three">
</div>
</body>
I think there are two issues going on here. One is that by leaving the third div display:block it will naturally wrap the first two divs. For a quick primer on blockvs inline-block see here.
The second part of this is that you have margin-top: -60px while having height: 50px. The negative margin is basically moving it higher up the page. This means the green box will apear 10px higher than the red one (-60 + 50 = -10).
Example Fiddle - I've added margin-left: -5px; and you can see the third div peeking out from under the first.
I sometimes get confused with divs when I try and build a little more complicated layout than normal.
I have made a quick example showing what my current problem is:
EDIT: UPDATED jsFIDDLE
Sorry, it's a little messy, but I'm just trying to get it to work. As you can see, I have forced a height on one of the vertical lines (but thats ok. that line is supposed to be fixed height). The vertical line I have problems with is the one between "Pictures for download" and "videos for download"
http://jsfiddle.net/GLjND/
<div id="wrapper">
<div id="first"></div>
<div id="second"></div>
<div id="third"></div>
</div>
I have lots of div's, and I guess my problem lies within some parent somewhere, but I cant figure it out.
Basically I have a wrapper,and I have 2 areas of content. In this example, those are "first" and "third".
The "second" is a vertical dotted line that I want to stick in-between these to areas, and the height of this div (which contains a vertical dotted image with repeat-y) should matsh the height of the wrapper, which in turn is defined by the largest of the two other divs ("first" and "third").
How would I do this?
Thanks in advance! :)
Here you go.
http://jsfiddle.net/GLjND/3/ (the yellow background is just so you can see the new div)
Just give the divs
display: table-cell
and you're done.
Here it is - fiddle
<div id="wrapper">
<div id="first"></div>
<div id="second"></div>
<div id="third"></div>
</div>
body{
padding:0;
margin:0;
}
#wrapper{
width:500px;
height:auto;
background:red;
}
#first{
display: table-cell;
width:230px;
height:300px;
background:blue;
}
#second{
display: table-cell;
background:white;
border-left: thick dotted #ff0000;
}
#third{
display: table-cell;
width:270px;
height:350px;
background:green;
}
When you are using float property, i recommend you to set overflow:hidden to the parent div
#wrapper{
overflow:hidden;
}
And for the #second u have set the height to 100%, for this to work u should fix an height for the parent div
#wrapper{
height:400px;
}
Here is the Jsfiddle
Hope this will a good solution and will be more informative
Just give the CSS property:
overflow : hidden
display : table-cell
I have no idea why, and this seems illogical, but for some reason the text in one div affects the position of another. The difference in the number of lines the text takes up offsets the height of a div with fewer lines. These divs are side-by-side inline boxes, so it really shouldn't do that period. Not only that, but they have fixed dimensions. I have no clue why this is happening but it ruins my design. Here's the code, stripped down to the problem without anything else in it.
<div class="box">
<div class="main">
<br><i>"Message"</i>
</div>
</div>
<div class="box">
<div class="main">
<br><i>"Message that is longer than the other message."</i>
</div>
</div>
<style>
table {
width:100%;
}
div.box {
background:#ccc;
border:1px solid #000;
display:inline-block;
height:100px;
padding:4px;
margin:4px;
width:100px;
}
</style>
My browser is Google Chrome, latest release.
You need to add vertical-align: top to div.box.
Demo without: http://jsfiddle.net/ucE8r/
Demo with: http://jsfiddle.net/ucE8r/1/
See here:
http://www.brunildo.org/test/inline-block.html
http://blog.mozilla.com/webdev/2009/02/20/cross-browser-inline-block/