I have two divs, one nested in the other, i.e. the #messages div is inside the #mainContent div. The #messages div should be 0px from the top of its parent. Everything is fine until i put a unordered list inside it, then it pushes the whole div down from the whole #messages div down by a few pixels.
If i put margin-top:0px; on the ul element, everything is fine again, but i want the ul to be margin-top:10px; from it's #messages parent. If i put margin-top:10px; it again pushes #messages 10px from #mainContent.
Can someone please explain why this is happening, and can someone provide a clean solution for this?
Thank you, it's jsfiddle is:
http://jsfiddle.net/wtKuP/4/
"Can someone please explain why this is happening, and can someone provide a clean solution for this?"
The top margins of a block-level element and its first in-flow block-level child will always collapse. There are many ways to avoid this (read the above link for a complete list) - one is to just add overflow: hidden to the parent of the <ul> as this creates a new Block Formatting Context and prevents the standard margin collapsing behaviour.
http://jsfiddle.net/wtKuP/22/
From the 2.1 Spec, Section 8.3.1:
Margins of elements that establish new block formatting contexts (such as floats and elements with 'overflow' other than 'visible') do not collapse with their in-flow children.
Put
margin:0;
padding:0;
on both divs. Then ul will have a 10px margin from messages div, but messages div will have no margin with maincontent.
Add ul:{margin:0;}. Better use eric myers reset.css which will remove browser inconsistence
Try this
JSFiddle updated with what you were asking for
<div id="mainContent">
<div id="messages">
<ul>
<li>Remove the UL and LI, and the #messages div will be 0px from the top of the parent div #mainContent. Why?</li>
</ul>
</div>
</div>
And then...
div#mainContent {
border:1px solid black;
position:absolute;
width:500px;
height:600px;
margin-top:50px;
margin-left:-250px;
left:50%;
}
#mainContent > #messages {
margin: 0;
width:499px;
height:525px;
background-color:red;
}
#messages ul {
display: inline-block;
margin-top: 10px;
}
Related
Div with id "message-box" is going outside its parent div "message-container"
I dont understand why?
I used "overflow:auto;" in my css for "message-box". but still its not giving me the desired result. margin left is not working properly when i use "overflow:auto" on "message-box".
Below is my HTML file:
<html>
<head>
<link rel="stylesheet" type="text/css" href="styles.css" >
<title>temp</title>
</head>
<body>
<div id="main">
<div id="header">header</div>
<div id="container">
<div id="user-container">user</div>
<div id="message-container">
<div id="message-box">message box</div>
<div id="text-box"> text box</div>
</div>
</div>
<div id="footer">footer</div>
</div>
</body>
</html>
Below is my CSS file:
#main{
border: 1px solid red;
margin: 5px;
}
#header{
border: 1px solid red;
height:30px;
margin: 10px;
}
#container{
margin:10px;
height:32em;
}
#footer{
border: 1px solid red;
height:30px;
margin: 10px;
}
#user-container{
border: 1px solid red;
float:left;
width:120px;
height:32em;
}
#message-container{
border: 1px solid red;
height:32em;
width:100%;
}
#message-box{
border: 1px solid grey;
overflow:auto;
margin:5px;
}
#text-box{
border:1px solid grey;
overflow:auto;
margin:5px;
}
please someone help me out here.
Quick answer
Your #message-box has correct margins all around in relation to the #message-container div, but the problem is that both #message-container and #message-box are overflowing into #user-container. Since #message-box has the overflow property, it is clipped at the exact edge where it overflows into #user-container. Since #message-container does not have overflow, it continues to flow behind the #user-container to the edge of the #container div. To fix this, add overflow to the #message-container.
#message-container {
height: 32em;
border: 1px solid red;
overflow: hidden;
}
I think what you want here is overflow: hidden to clip the overflowing content; overflow: auto adds scroll bars to see the overflowing content.
Explanation
The float on #user-container is causing the problem. Floats remove an element from the normal document 'flow' (see Normal Document Flow below).
I added background colors to #user-container(green) and #message-container(blue) so you can see what's happening. If you remove overflow from #text-box and #message-box, you'll see margins are actually working correctly between #message-box and #message-container. Add them back and you'll see how they get clipped by #user-container.
This is what's happening http://jsfiddle.net/fmceqbdp/2/
Normal Document Flow
The DOM has an element hierarchy. The document is the highest level parent (or outermost box), and any element you add is its child. The element's starting position is the upperleft of its parent. If you add another element at the same level (not nested), it is another child of the document and a sibling of the first element. The sibling also wants to be positioned as close as it can to the upperleft of the document, but it gets pushed right by the first element (inline) or to the next line (block). When you nest an element inside that element, the nested element is the child, it is contained inside the parent. It's starting position is the upperleft of its parent element. This is normal document flow. A floated element is removed from this normal flow, so it doesn't push other elements the way it normally would.
How Floats Behave
Divs are block elements, they push other elements away. However, when you float an element, it removes that element from the normal document flow -- that means its position is invisible to sibling elements (elements at the same level), so they're now positioned in front or behind the floated element as though the floated element doesn't exist. Because you floated #user-container, #message-container fills the entire #container as though #user-container is not there.
How Overflow Works
The element that has the overflow property will self-clear from overflowing into other elements. This is why #message-container flowed into the space occupied by #user-container but its children #message-box and #text-box with the overflow property had cleared themselves from flowing into the space #user-container. Their margins were still relative to their parent #message-container, not where they're clipped, which is why it appeared there was no left margin where they ran into #user-container.
For more details, see http://css-tricks.com/the-css-overflow-property/ -- scroll about 1/4 of the way down the page.
You need to add an overflow to #message-container because that's the div that's being pushed by the float not its children. #message-box and #text-box don't interact with their parents previous siblings.
So, remove all overflow: auto; and do this:
#message-container {
height: 32em;
border: 1px solid red;
overflow: hidden;
}
Here is a Fiddle:
http://jsfiddle.net/Ljqmjzkp/1/
PS: Cleaned the code so it's easier to read, also I indented it according to your DOM so you can see the structure. Keep that in mind, it helps ^^
I'm building a menu where every dropdown item has the width of its content. To manage that I had to make the items inline-blocks, but that means they all end up on the same line. Is there a way to make them all on their line without using margins, OR is there a way to have blocks have the width of their content?
Thanks
sample menu item HTML:
<div class="menuItemWrap">
resources
<div class="menuItemContentWrap">
articles
web reviews
bookstore
powerpoint
schwab forms
blunck forms
</div>
</div>
CSS:
.menuItemWrap{
display:inline-block;
float:left;
}
.menuItemHead{
padding:14px 22px;
margin: 0px;
border:0px;
background:#2389DD;
}
.menuItemContentWrap{
position:absolute;
display:none;
width:100px;
background:#A6CFD1;
}
.menuItemContentItem{
display:block;
padding: 8px 14px;
background: red;
color:#333;
position:relative;
float:left;
}
float removes the width and height of an element. In order to make the elements appear on separate line use the clear property:
float: left;
clear: left;
Quote from MDN:
The clear CSS property specifies whether an element can be next to
floating elements that precede it or must be moved down (cleared)
below them.
Demo
I'm certain this has been asked before in some form or other, but I just can't find an answer..
I have some nested divs
<div class="parent">
<div class="child">A</div>
</div>
And the child has display:inline-block and overflow:hidden
.parent{
background-color:red;
}
.child{
background-color:green;
display:inline-block;
overflow:hidden;
}
And it gets rendered like this:
You can notice that the parent is 5px higher than the child.
Where does the extra height come from?
Here is the sample: http://jsfiddle.net/w8dfU/
Edit:
I don't want to remove display:inline-block or overflow:hidden, this is a simplified example to illustrate the problem, but in my real layout I need them both.
I just want to understand why this extra height appears. Is it specified somewhere that it should be like this? Is it a consequence of some other css feature?
I had this issue when building a horizontal slider. I fixed it with vertical-align:top on my inline-block elements.
ul {
overflow-x: scroll;
overflow-y:hidden;
white-space: nowrap;
-webkit-overflow-scrolling: touch;
}
ul&::-webkit-scrollbar {
display: none;
}
li {
display: inline-block;
vertical-align: top;
width: 75px;
padding-right: 20px;
margin:20px 0 0 0;
}
The accepted answer above is correct, but it does not give the explanation I was looking for.
A good explanation was provided by #Alohci in his comment.
Explanation in a few words:
The value for vertical-align is baseline, therefore the child div is aligned with the baseline of the text.
This text baseline is not the same as the bottom line. It's a bit higher up, to accommodate letters with descenders: p, q, g.
This is why the problem is fixed by setting vertical-align:top.
.child{
background-color:green;
display:inline-block;
overflow:hidden;
vertical-align: top;
}
This extra space coming from overflow:hidden of Child class. Remove this property and check and if your really wanted to use overflow:hidden property then use negative margin to child class . You can remove this extra space.
I have a list of names which is rendered inside <ul>. I am applied some CSS code but facing some browser specific issues.
Chrome : List element is getting displaced by 1 row.
Firefox : All list items collapsing to one item.
Code snippet (JS bin editor)
HTML
<div id='container'>
<ul class='list'>
<li> <div class='rel'>
<div class='abs'> item 1 </div>
</div> </li>
... More items similar to above one
Css
#container {
height: 100px;
overflow-y:scroll;
width: 200px
}
.list {
background-color: skyblue;
}
.rel {
position: relative;
}
div.abs {
position: absolute;
left: 20px;
}
I want to know the reason of this misbehavior in both the browsers. Have I written wrong CSS ?
Update: With in <div class='abs'> I have a lot of code which I have not added here as it is not necessary and the content of abs div is positioned with respect to its parent i.e. <div class='rel'>
The problem is indeed the
div.abs {
position: absolute;
left: 20px;
}
This positions every element with class "abs" 20px to the left (and 0px from top) of the ul element.
What would you like to achieve? Your menu horizontally or vertically?
Horizontally: Use float:left or display:inline with a margin-left:20px;
Vertically: for a 20px margin-left:
http://jsbin.com/ediloh/17/edit
I first added margin:0px to delete the top and bottom margin of the ul element. Next I added a left margin of 20px to move it to the right.
alternative: put margin-left on the li-element instead. This will not move the circles
The divs with position:absolute are taken out of the page flow, basically causing their parent divs to have no content at all (no content amounting to any width or height that is). So they will collapse.
What outcome do you actually want. You are fixing the div.abs to be indented by 20px inside its containing div.rel.
Could you give some idea of what you are trying to achieve.
Wing
I have a div called NAV and inside of NAV I have an UL with 5 li which I float to the left, the li's that is but when I do that the NAV collapses. I know this because I put a border around NAV to see if it collapses and it does. Here is the example.
collapsed http://img401.imageshack.us/img401/8867/collapsedze4.png
no collapsed http://img71.imageshack.us/img71/879/nocollapsedkx7.png
as you can see in the first image, the links in the NAV div are floated left and that
black border ontop is the actual div called NAV.
in this image you can see how it has top and bottom border and it not collapsed.
here is some of the html and css I used.
alt text http://img301.imageshack.us/img301/5514/codejc8.png
#nav #ulListNavi a {
float: left;
}
Add any overflow value other than visible to your container:
div#nav { overflow:auto; }
Then add width to restore the width
div#nav { width: 100%; overflow:auto; }
One solution is to add a "clear:both" style to an element after the last floated anchor, for instance:
<div id="nav">
<ul id="ulListNavi">
<li>Home</li>
<li>Search</li>
<li>Flowers</li>
<li>My Account</li>
<li>Contact Us</li>
</ul>
<div style="clear:both;"></div>
</div>
This causes the containing element to clear all floating elements before closing the containing box.
A few other options for clearing floats here:
http://www.quirksmode.org/css/clearing.html
http://www.sitepoint.com/blogs/2005/02/26/simple-clearing-of-floats/
As to the best way of doing it, that's almost a holy war, the purists would freak about the extra div, if you are not fussed by a little extra markup, the addition of the cleared div as suggested by Joshua and AJ will work fine, and is a reliable technique, but there are at least 17 other ways of doing it...
add this code after your ul:
<div style="clear: both"></div>
Try floating the containing element to the left too.
Don't bother with clearing elements or overflow. Add this:
#nav {
float: left;
}
When you float the LI's, the #nav no longer "contains" anything so it collapses. But if the #nav is floated also, it contains anything floated inside it, so it expands again.
(Also consider removing the #nav div and just applying the same styles to the UL.)
Your problem is because you are floating the <A> elements, but each of them is inside an <LI> element. LIs display as blocks by default, so each <LI> is forcing it's child <A> to begin on a new line.
If you float the <LI>s, I think you'll solve your problem.
#nav #ulListNavi li {
float: left;
}
The quickest solution would be to add overflow:hidden to clear the float on the parent element:
#nav{overflow:hidden;}
Without changing your HTML:
#nav
{
width: 100%;
overflow: auto;
border: solid 1px red;
}
#ulListNavi
{
margin: 0;
padding: 0;
list-style: none;
}
#nav #ulListNavi li
{
float: left;
}
#nav #ulListNavi li a
{
margin-left: 5px;
}
Works in IE8 and FF 3.5