Container div does not expand to fit child div (without floats) - html

My container div does not expand to fit its child div - which has a top: 20px value.
I don't even have floats and have used both overflow:hidden (cuts part of the child div) or overflow:auto (creates scrollbars).
See codepen example: Codepen
<div class="container">
<div id="model">fdsf</div>
</div>
Appreciate any solutions to this problem.

Remove top and position properties and use margin: 10px auto 0 auto;
#model {
background: yellow;
border: 1px solid orange;
width: 100px;
height: 100px;
margin: 10px auto 0 auto;
display: block;
}
Demo

1) In your example, the container is expanding to fit the child div correctly. The height of the child is 100px plus two times the border of 1px, in total 102px. Then, the height of the container is exactly 102px, as the developer tools in any browser can tell you.
Height of the contents totals 102px, thus the inner height of the container is 102px. This is by definition "expanding to fit the contents".
2) Now, you are setting position: relative for your child div. The following quote from Mozilla Developer Network should give a complete explanation to what is happening in your example.
Relative positioning:
This keyword lays out all elements as though the element were not
positioned, and then adjust the element's position, without changing
layout (and thus leaving a gap for the element where it would have
been had it not been positioned). The effect of position:relative on
table-*-group, table-row, table-column, table-cell, and table-caption
elements is undefined.
3)
Obviously, you can get rid of this effect by getting rid of relative positioning, and just using margin instead. Regarding your comment, no, top, right, bottom, and left should absolutely not work. They are meant to be used for a totally different thing, for what the quote above explains.

Related

Why does a child of an absolutely positioned element not expand its parent width on overflow-y?

I have an absolutely positioned element attached to the body of a page. It does not have limitations on its height or width. I have child of the absolute element that contains a list and it's height is limited on the y-axis. This listing can be variable in length and width so I would prefer not to use any hard-set paddings or margins nor "overflow-y: scroll" because the scroll bar will show even when not needed.
<style>
.the-absolute {
display: block;
position: absolute;
}
.the-list {
border: 1px solid blue;
display: flex;
flex-direction: column;
max-height: 100px; /* arbitrary limit for example */
overflow-y: auto;
white-space: nowrap;
}
</style>
<body>
<div class="the-absolute">
<div class="the-list">
<div>Title</div>
<div>Year</div>
<div>Studio</div>
<div>Worldwide</div>
<div>Domestic</div>
<div>Budget</div>
<div>Title</div>
<div>Year</div>
<div>Studio</div>
<div>Worldwide</div>
<div>Domestic</div>
<div>Budget</div>
</div>
</div>
</body>
I would expect the width of the child element to expand the parent width while accommodating the scroll bar. Instead, the content of the longest list items is overlapped by the scroll bar on the right.
This works as I would expect in Chrome, but does not seem to play nice in IE11 (surprise!), Firefox or Safari.
I am a bit baffled here and would appreciate a better understanding of how absolute positioning affects the children of an element and if there is a way I can have dynamic (i.e. no hard-set margins, widths, etc) list that will be scrollable if it hits a certain threshold without overlapping the content.
I have tried multiple iterations and wrapping elements but something about the absolute positioning causes this. I can hack it using JS but would prefer a pure CSS solution. I just assume there is some detail I am missing or I lack the right combination of keywords to find the solution via google/stackoverflow.
All help is appreciated!
Absolutely-positioned elements are no longer part of the document flow, so they aren't really "in" their parent element anymore. They therefore do not affect the parent's dimensions.

css margin seems to refer to body instead of parent?

I have the following HTML structure:
<div class="slide active" id="sli-0-1">
<div class="mediaWrapper" id="musWrapper">
<div class="albumWrapper" id="albumWrap-1">
. . .
</div>
</div>
</div>
For the entire code please refer to this jsFiddle
Since I set the height of the child div to 90% in order to compensate for the total of 10% vertical margin, I expected the div to vertically centered within its parent div. As you can see, that is not the case.
I have no clue why - never had this sort of problem before and for some reason I cannot for the life of me figure out what might becausing this behavior. Tried using padding instead of margin with the same height - no changes. Tried to only set margin-top to 5% and height to 90 - no changes.
This might very well be caused by some stupid mistake of mine, in which case I apologize in advance. If not, I would appreciate if somebody cared to explain this to me.
Thank you.
It's because the percentage based margin-top value is relative to the width, not the height. You will notice this if you resize the window horizontally - see the margin change relative to the width?
Box Model - 8.3 Margin properties
The percentage is calculated with respect to the width of the generated box's containing block. Note that this is true for 'margin-top' and 'margin-bottom' as well. If the containing block's width depends on this element, then the resulting layout is undefined in CSS 2.1.
As a work-around, you could absolutely position the element and add top: 5% for vertical centering.
Updated Example
div.albumWrapper {
background: transparent;
border: 1px solid #a00000;
margin: 0 2%;
width: 96%;
height: 90%;
z-index: 20;
position: absolute;
top: 5%;
}
You center the div by adding this line to the css corresponding to the div you intend it to affect
#id{margin: 0 auto;}
That will center your div in window

Children element not stretch parent container

Children element not stretch parent container.
My code:
html:
<div class='window'>
<div class='wrapper'>
<div class='short'>short</div>
<div class='long'>long</div>
</div>
</div>
css:
.window{
width: 500px;
height: 100px;
overflow: auto;
background: gray;
}
.wrapper{
background: pink;
border: 1px solid red;
}
.long{
width: 700px;
background: beige;
}
example
I want .long stretch his parent .wrapper.
.wrapper width must be the same as .long (700px).
I can reach this by setting float: left to .wrapper.
But what happens here i don't understand, why it helps? What is the mechanism of such behavior? I need explanation, with links to w3c documentation.
What else can i do to extend .wrapper width?
By default, the .wrapper div is inheriting the fixed width you set on .window. You can float the .wrapper and set it's width to auto so the width expands without restriction to the parent.
CSS:
.wrapper {
float: left;
width: auto;
}
Example: http://jsfiddle.net/WTGAc/3/
Theory:
By default, the dimensions of wrapper are constained to the dimensions placed on it's parent, .window.
Floated elements still live within the parameters defined by their
parent element, ie the width available and horizontal position. They
still interact with text and other elements inside that parent element
(or other following elements). In that respect, they are quite
different from absolutely positioned elements, which are removed from
the document flow and don't interact with other elements ... but even
then, if they have a positioned ancestor then they are restricted by
the envelope of that ancestor and will use that as the basis for
calculating size and dimension (although they can still be made to
extend or exist outside that positioned ancestor).
Source of Quote
Since the element is floated and set outside of the normal document flow, it can now expand to the true width of the parent, instead of the fixed width initially defined.
Widths and the CSS Visual Formatting Model
In you example, you have the following:
<div class='window'>
<div class='wrapper'>
<div class='short'>short</div>
<div class='long'>long</div>
</div>
</div>
In the simplest case, .window is the containing block with a fixed width (500px). The child element .wrapper inherits the width from .window. The .long element has a width of 700px and it will trigger an overflow condition. Since .window has overflow: auto declared, the .window element will generate a horizontal scroll bar. Note that by using overflow: auto, .window establishes a new block formatting context, which is why the horizontal scroll bar appears on .window instead of the viewport/root element.
When you float .wrapper to the left, the .wrapper element defines an additional block formatting context. A new block formatting context will ignore the width inherited from its containing block and computes a new width sufficient to enclose the content (shrink-to-fit), which is why the pink background from .wrapper now extends the entire 700px in width.
You can trigger the same effect by adding position: relative to .window and position: absolute to .wrapper. However, this works because you set the height to .window, otherwise, the .window height would compute to zero since absolute elements are out of the flow and (unlike floats) will no longer affect how the .window content is laid out (not contribute to the height in this case).
As an aside, instead of using float: left on .wrapper, you can also try overflow: auto which will also establish a new block formatting context but this time the scrolling bar appears on .wrapper instead of .window.
The relevant documentation from w3.org is:
10 Visual formatting model details
10.3 Calculating widths and margins
10.3.5 Floating, non-replaced elements
Link: http://www.w3.org/TR/CSS2/visudet.html#float-width

Why does a negative bottom margin on an element decrease the height of parent of that element?

This might be due to margin collapsing and I know about margin collapsing, at least how it affects adjacent elements, but I don't understand how it works on nested elements when negative margins are involved.
For example, in this markup and accompanying CSS:
Markup
<div class="parent">
<div class="child">
Child 1
</div>
</div>
<div class="parent">
<div class="child negative">
Child 1
</div>
</div>
CSS
body {
background: white;
padding: 45px;
}
.parent {
border: 1px solid black;
margin-bottom: 10px;
}
.negative {
margin-bottom: -1px;
}
Live example here.
When I inspect the height of the second .parent div, I notice it is 1 pixel less than the first one. This has happened because of the negative margin on the .negative element inside it. I had a quick look at W3C and couldn't find an explanation for this behavior.
Could someone please explain what's happening here and also provide me with a link to the W3C spec section about it?
This might be due to margin collapsing and I know about margin collapsing, at least how it affects adjacent elements, but I don't understand how it works on nested elements when negative margins are involved.
Section 8.3.1 has all the details. It also covers the behavior of adjoining margins between nested boxes, as well as negative margins.
However, what you're seeing here is not the effect of margin collapse because you have negated it with a border: 1px solid black declaration in your .parent rule. That means having a border there prevents your .parent margin from collapsing with your .child.negative margin altogether.
Rather, this is simply how negative margins work. This is covered in various sections of the visual formatting model, but it's most succinctly and directly addressed in the beginning of Section 11, which summarizes it thus:
Generally, the content of a block box is confined to the content edges of the box. In certain cases, a box may overflow, meaning its content lies partly or entirely outside of the box, e.g.:
...
A descendant box has negative margins, causing it to be positioned partly outside the box.
So what's happening here, instead, is:
The absolute value of the .child.negative element's negative margin is subtracted from the .parent element's actual height (by 1px).
As a result, the .child.negative element itself overflows .parent (because its own height is not changed and the default overflow for any div is visible).
Since margin collapse does not take effect here, the margin-bottom: 10px in your .parent is unaffected. Note that while any subsequent elements in normal flow will be shifted up by 1px, this is mainly due to the negative margin of your .child.negative element; in other words, a side effect of step 1.
And that's all there is to it.
when you are using .negative { margin-bottom: -1px; } then it will moved at the top. see this example.
please refer the following link you understand easily.
http://coding.smashingmagazine.com/2009/07/27/the-definitive-guide-to-using-negative-margins/
body {
background: white;
padding: 45px;
}
.parent {
border: 1px solid black;
margin-bottom: 10px;
min-height: 30px;
}
.negative {
margin-bottom: 20px;
}
conclusion:
For e.g. In your case i have to added min-height:30px to parent class so that it remains fix. if moved only if you add positive margins to negative class. It just because you can see results in above figure that tells all what you need is.
see the cssdesk link click here cssdesk
Hope, it will helps you. Cheers. !!
Margins of first and last elements will apply to outer element when the outer element doesn't have border, padding and content, instead of it self.
In your case, parent node has border, so margin collapsing won't apply in this case. As you have margin-bottom = -1px for the child node inside, when calculate the outer height of the child node will be the height of its content + padding + border-width + margin. So it will be 1px less when measuring from outside. That's why the height of parent node will be 1px less than the upper example. To see it more clearly, you may apply a background to the child node, say yellow, you will find that the child node will overlap the border of the parent node.
But if you remove the border of the parent node, it will be a total different situation.
For instance to explain margin collapsing, say you have
<div style="background-color:black">
<div style="height:10px; background-color:white; margin-top: 10px"></div>
</div>
You will not see a black box of 10px height, as the outer node will be considered to have a 10px margin on top, and the inner one's margin is ignored. And for negative situation, the outer margin will decrease.
Quote from spec:
When two or more margins collapse, the resulting margin width is the maximum of the collapsing margins' widths. In the case of negative margins, the maximum of the absolute values of the negative adjoining margins is deducted from the maximum of the positive adjoining margins. If there are no positive margins, the maximum of the absolute values of the adjoining margins is deducted from zero.
For more info:
https://developer.mozilla.org/en-US/docs/CSS/margin_collapsing

using z-index and position in css to seperate design and core!

I am using the yui-grids css (irrelevant if you don't know what this is) with three columns. and I'm putting all the fancy design stuff on the left column and using z-index and relative psitioning bringing them in the center. and then putting all the important stuff like forms, inputs buttons, links and context in the center. Is this wrong. I've never seen this done so I was wondering maybe there is something I don't know! or am not considering. Should I just use one column?
I'm not totally sure what you're asking, so I'll give it a shot:
Columns
If you're going with a column layout, you should give just floating elements a go. Due to how floating works, a clearfix hack will be nessecary (link provided below). Clearfix allows child elements to be floated while maintaining the parent element's height and block nature. Clearfix can only be added to block elements.
For my example, we will be going with a 2 column layout -- one #content column and a #sidebar column -- you could do two, three or more.
For the parent div (that contains the #content and #sidebar elements), you'll need to add a class="clearfix".
For the content div, you'll want to float it to the left. For the sidebar div, you'll want to float it to the right.
Now, the CSS:
#parentDiv { width: 750px; margin: 0 auto; }
#parentDiv #content { float: left; width: 500px; }
#parentDiv #sidebar { float: right; width: 200px; }
This should produce a 750px box with a content element on the left and a sidebar on the right with 50px in between both elements (750-(500+200) = 50).
Floating Module
If this isn't what you wanted, and were looking to produce a module element (lightbox, popup window, etc) instead, this is easy too.
First, create a div called #module. Put in your content into it. Let's say you want to give it a width of 500px and you want the height to be static at 300px. So we'd do this CSS:
#module { width: 500px; height: 300px; border: 1px solid #000; position: absolute; top: 50%; left: 50%; margin: -150px 0 0 -250px; z-index: 100; }
What's going on here?
The #module element is being set to position: absolute. This means that it will be floating around the window, and is not constrained to it's parent element. We position it to be 50% from the left of the window and 50% from the top, so it gets in the middle of the window. Percent values are nessecary as they are adjusted when the window resizes. Without the margin, the element's top left corner will be 50% from the top and 50% from the left, so we need to use margin to move it back half of it's width and half it's height. This will allow us to have a box perfectly centered in the middle. The z-index is added to make sure that the element is on top of any other element, including , and other positioned elements.
I hope this helps.
Links
Clearfix: http://gist.github.com/550114
This kind of layout wouldn't be correct in my opinion.
The design of an element must be described in that particular element.