Children element not stretch parent container - html

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

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.

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

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.

Why does positioning effect div width?

I was fiddling with my web-app to try and get a div to wrap around some p elements. The structure looks like this, i.e. pseudo-code ...
<div id='outer'>
<p></p>
<p></p>
<p></p>
</div>
What I found is that if I set the outer div to
position:absolute;
instead of
position:relative
that the div would correctly wrap around only the p elements.
Otherwise it would extend all the way to the very right of the page, and I had previously had to set the width manually.
What is governing this behavior?
Also, the p tags use
display:inline
and the containing div just uses the default display.
This CSS below works well in my app.
// outer div
#mi_control {
position: absolute;
left: 580px;
top: 660px;
width: auto;
padding-top: 5px;
padding-bottom: 5px;
}
// p elements
.menu_bottom {
margin-left: 18px;
display: inline;
}
This is a common issue..
I quote:
Question: relative div takes 100% width automatically but absolute div only takes content width. why?
Answer: Setting position:absolute removes the element in question from the normal flow of the docment structure. So unless you explicitly set a width it won't know how wide to be. you can explicitly set width:100% if that is the effect you're after.
By default, a div element is set to display: block;. Block elements will be 100% of the width of the parent element.
When you set an element to position: absolute; it takes it out of the document flow and the element is no longer sized according to the parent element. It can mess with your layout though.
My recommendation is to set the div element to display: inline-block; - this will make it sized as per its contents, but will not remove it from the flow of the document.
#outer
{
display: inline-block;
}
I don't know exactly what rules governing this behavior but what you observed is the right behavior and is consistent across all browsers. A DIV takes minimum width when its position is set to absolute or fixed; otherwise it takes full available width.
The default value for width for a div element is auto.
This means that it will take up the full with of the available space, or more if the contents forces it to. If you use position: absolute however, you take the element out of the document flow. As there is nothing that it can relate to as the full width any more, it will use the width that the contents forces it to use.
The behaviour is governed by the spec. Absolute positioned elements have dedicated rules about how widths are calculated: http://www.w3.org/TR/CSS2/visudet.html#abs-non-replaced-width and http://www.w3.org/TR/CSS2/visudet.html#abs-replaced-width
Once it is set to absolute, it is taken out of the normal flow of content. Absolutely positioned elements always appear in the top left corner, unless otherwise specified. The element will also shrink to be only as big as it has to, because that's how position:absolute works
divs naturally have a width of 100%, so that is why you have to set the width manually. Relatively positioned elements behave almost identically to statically positioned elements. The only difference is how they can be moved
Not sure what you are seeing but even if your div is positioned absolutely, it will STILL wrap your P tags
http://jsfiddle.net/8MSDH/
you are seeing it at the bottom right because you set your top and left
left: 580px;
top: 660px;

Avoiding parent div properties in child div

I am using the following code to center align my webpage,
#parent{
margin:0 auto;
width: 960px;
}
<div id="parent">
<!--more code goes here-->
</div>
The properties have moved to all of the child div's causing them to be center aligned. I am not a CSS coder but I rememeber there is a trick to make the parent div elements to stick to the parent div only. Please help. Thanks
#parent{
margin: 0 auto;
width: 960px;
}
#parent * {
margin: 0;
width: auto;
}
#parent{
margin:0 auto;
width: 960px;
}
#child{
margin:0;
width: 960px;
}
<div id="parent">
<div id="child">
<!--more code goes here-->
</div>
</div>
would work, right?
What I usually do to avoid having children inherit properties is have one parent with two children. I make identical divs for each of the children. Then, I give one of those divs the properties you DO NOT want the other children to have, like opacity or others. After that, I put the regular children layout divs and content into child number 2. That way, the undesirable properties become sibling properties, and not inherited.
The margin and width properties are not inherited (except via the use of the inherit value). However, an inner element appears by default within the outer element visually, so it may look like it inherited those properties. In reality, e.g. margin-left is 0 (by default), but this means that the element starts at the same horizontal position as its parent. Similarly, width is auto for block elements that have no width set on them, and this means the available horizontal space.
The fix to your problem depends on what the problem is. There is no inheritance problem for these properties. But if you wish to make e.g. a child of a centered element start at the very left of the browser window, you need to e.g. set negative margin on it or to use absolute positioning.
For many other properties, such as color, an element inherits the property from its parent if the property is not set on the element itself. If inheritance is not desirable, set the property on the inner element. There is no trick; this is how CSS works.

Floating divs in the absolute div are not expanding the parent. Clearfix doesn't seem to work

I have this issue: two floating divs inside an absolute-positioned parent div.
CSS:
.wrapper {
position: absolute;
left: 0;
top: 0;
overflow: hidden; /* doesn't do anything! */
}
.left {
float: left;
}
.right {
float: right;
}
.clear {
clear: both;
}
HTML:
<div class="wrapper">
<div class="left">some text here</div>
<div class="right">some text here too</div>
<div class="clear"></div>
</div>
In Firefox, if the wrapper doesn't have position:absolute, everything works, as intended. As soon as I make it absolute, the wrapper shrinks and the content in floating divs overlap the rest of the document. Also, if I set the wrapper's width to 100% it overlaps the vertical scrollbar.
What am I missing?
Since you're using the overflow: hidden clearfix, the div.clear is completely unnecessary. But since you're also positioning your wrapper absolutely the overflow: hidden clearfix is also unnecessary as position: absolute will also clearfix (at least in Chrome and FF).
http://jsfiddle.net/j6jkk/
Floating an element takes it out of the document flow. That means it will not have an impact on its parent's dimensions, and absolutely positioned elements are 0 x 0 by default. Clearing the floated element's next sibling is only going to expand the width of the parent container if you actually have content in that element, have its width set in its style, or one of its other siblings still in the document flow has width greater than the parent's initial width.
See this article from the Mozilla Developer Network, although this is true of CSS in general, not just Firefox:
float - MDN
Regarding the width: 100% issue, if the offset parent of the wrapper is the document, this may be how Firefox responds to the positioning style. You might be able to alleviate that by placing the absolutely positioned element in an empty div with position set to relative.
Try adding this:
.wrapper{
display: inline-block;
}