How can I create two children to fill a parent's height? - css

Given an outermost "containing" div of arbitrary dimensions, I am looking for markup and css that will place two divs within it, and display them left to right, as follows. The first div, on the left, should have a fixed width of 200 pixels. It should take up 100% of the height of its parent. The second div, on the right, should take up the remaining width of the parent and also 100% of its height.
So, given the following HTML for a parent container along with the two children:
<div class="a">
<div class="b">
</div>
<div class="c">
</div>
</div>
And given this CSS for the parent:
.a {
height: 300px;
width: 600px;
background-color: gray;
}
And given this incomplete CSS for the children:
.b {
background-color: red;
}
.c {
background-color: green;
}
How can I complete the CSS for the children, in a way that does not depend on the exact height and width of the parent?
(It would also be permissible to add another element ".d" as the parent of the two children, for example as a flex container, giving the following HTML:
<div class="a">
<div class="d">
<div class="b">
</div>
<div class="c">
</div>
</div>
</div>
The point is that I cannot modify the outermost element, but I can accomplish my goals with any combination of elements and css beneath it.
)

display: flex was designed for this type of set up.
My personal favourite post, when I need to brush up on the settings, is CSS-Tricks': "A complete guide to Flexbox"
.a {
display: flex; /* turn element into a flex container, and all its children into flex elements */
flex-direction: row; /* render the flexbox horizontally */
height: 300px;
width: 600px;
background-color: gray;
}
.b {
width: 200px; /* Element will be exactly 200px wide */
background-color: red;
}
.c {
flex-grow: 1; /* This (flex) element will take all available space */
background-color: green;
}
<div class="a">
<div class="b">
</div>
<div class="c">
</div>
</div>

This is how I do it: with relative positioning.
.b {
background-color: red;
position: relative;
left: 0px;
top: 0px;
width: 100px;
height: 300px;
}
.c {
background-color: green;
position: relative;
left: 100px;
top: -300px;
height: 300px;
}
Basically, relative positioning moves the boxes relative to where they would have been under normal positioning.

Related

CSS: Align bottom of child element to top of parent element (above it on Y axis) while the child has variable height

Is it possible to align (with pure CSS/SASS) bottom of child element to the top of parent element while the child has variable height? I want to achieve a popover that is placed above (Y-axis) of parent.
<div id="parent">
<div id="child">
Bottom border of this should always be on top
border of parent - regardless of child's height
</div>
</div>
I can offset child against relative parent with the position: absolute and top: someOffset, but this requires either dynamic offset calculation in js (I don't have any idea how to do it with calc()) or a fixed height of child, but then as the child changes height it will overflow the parent or leave a gap between them.
You have two ways to solve this:
#parent {
display: inline-block;
width: 180px;
height: 100px;
margin: 100px 0;
border: 1px solid red;
position: relative;
}
.child {
position: absolute;
border: 1px solid green;
}
.one {
bottom: 100%;
}
.two {
top: 0;
transform: translateY(-100%);
}
/* this one is hacky but can be useful in some cases */
.three {
height: 0;
top: 0;
display: flex;
align-items: flex-end;
}
<div id="parent">
<div class="child one">
Bottom border of this should always be on top border of parent - regardless of child's height
</div>
</div>
<div id="parent">
<div class="child two">
Bottom border of this should always be on top border of parent - regardless of child's height
</div>
</div>
<div id="parent">
<div class="child three">
Bottom border of this should always be on top border of parent - regardless of child's height
</div>
</div>
The way you started is also fine, just do it this way, using bottom:
#parent {
border: 1px solid red;
position: relative;
margin: 100px 0;
}
#child {
position: absolute;
bottom: 100%;
border: 1px solid yellow;
}
<div id="parent">
Parent
<div id="child">
Bottom border of this should always be on top
border of parent - regardless of child's height
</div>
</div>
Also on JSFiddle.

Is it possible for absolute div to have width: auto, and also ignore it's parent's width?

I'm trying to make a div that stretches to fit its content, up to some maximum width, after which the content should wrap.
Using an absolutely positioned div works fine -- unless its parent's width is limited. When its parent's width is limited, the absolutely positioned div acts as though its max-width is the width of its parent.
I'd essentially like for the absolutely positioned div to "pretend" its parent has 100% width, and give me the nice "stretch-to-fit" behavior, while honoring the max-width I set on it.
In the below example, I'd like the first .abs to work, even though it is a child of a "skinny" div.
.parent {
position: relative;
background: #EEE;
width: 100px;
}
.abs {
position: absolute;
max-width: 200px;
/* width: auto, but ignore parent! */
}
.parent2 {
margin-top: 150px;
background: rgba(0,128,0,.1);
width: 100px;
}
<div class="parent">
<div>
Doesn't work.
</div>
<div class="abs">
This wraps after 100px, because it's parent has 100px width.
</div>
</div>
<div class="parent2">
<div>
Does work.
</div>
<div class="abs">
This wraps at 200px, because it's parent is as wide as the viewport, so it honors the max-width of 200px.
</div>
</div>
https://jsfiddle.net/nqws2p09/1/
Since padding of the parent is considered in the width calculation of the absolute element you can then add more padding to the parent element:
.parent {
position: relative;
background: #EEE content-box; /* Color only the content */
width: 100px;
padding-right:200px;
margin-right:-200px; /*to consume the padding added*/
}
.abs {
position: absolute;
max-width: 200px;
}
.parent2 {
margin-top: 150px;
}
<div class="parent">
<div>
Does work.
</div>
<div class="abs">
This wraps after 100px, because it's parent has 100px width.
</div>
</div>
<div class="parent parent2">
<div>
Does work.
</div>
<div class="abs">
This wraps at 200px, because it's parent is as wide as the viewport, so it honors the max-width of 200px.
</div>
</div>
Or consider a big margin on the positioned element:
.parent {
position: relative;
background: #EEE;
width: 100px;
}
.abs {
position: absolute;
max-width: 200px;
margin-right:-200px;
}
.parent2 {
margin-top: 150px;
}
<div class="parent">
<div>
Does work.
</div>
<div class="abs">
This wraps after 100px, because it's parent has 100px width.
</div>
</div>
<div class="parent parent2">
<div>
Does work.
</div>
<div class="abs">
This wraps at 200px, because it's parent is as wide as the viewport, so it honors the max-width of 200px.
</div>
</div>
Use width: max-content; to force the absolutely positioned child to size itself based on its content instead of the parent element's dimensions.
This also works alongside max-width.
.parent {
position: relative;
background: #EEE;
width: 100px;
}
.abs {
position: absolute;
max-width: 200px;
width: max-content; /* this forces width: auto */
}
<div class="parent">
<div>
Div inside parent element. This will wrap at 100px.
</div>
<div class="abs">
This absolutely positioned child element wraps after 200px, even though the parent's max-width is set to 100px
</div>
</div>
This is somewhat solved by wrapping abs in an absolute div that has a much wider width than the relative parent. The problem now becomes sizing wrapper to stretch to the right of the viewport, which is a topic for another question.
.parent {
position: relative;
background: #EEE content-box; /* Color only the content */
width: 100px;
}
.abs-wrapper {
position: absolute;
width: 800px;
}
.abs {
position: absolute;
max-width: 200px;
border: 1px solid gray;
}
<div class="parent">
<div>
Doesn't work.
</div>
<div class="abs-wrapper">
<div class="abs">
This correctly wraps after 200px, because it's parent is a wrapper with a very large width. Thus, this div will stretch-to-fit, and also honor max-width.
</div>
</div>
</div>
<div class="parent" style="margin-top: 150px">
<div>
Doesn't work.
</div>
<div class="abs-wrapper">
<div class="abs">
< 200px shrinks to fit.
</div>
</div>
</div>
https://jsfiddle.net/rxwqtpsz/

How can you horizontally center an absolutely positioned element relative to the viewport when it has a positioned parent?

Eg. how can you get the blue child in this example to be horizontally centered relative to the viewport (ie. in the center of the page), provided that the parent must stay the same.
Other qualifications:
I don't want it to be fixed.
Suppose that distance between the parent and the left viewport is unknown.
.parent {
margin-left: 100px;
margin-top: 100px;
background: red;
position: relative;
width: 50px;
height: 50px;
}
.child {
background: blue;
position: absolute;
bottom: 100%;
}
<div class="parent">
<div class="child">
child
</div>
</div>
I am trying to make this question a SSCCE. In reality, the use case is that I have a dropup (like dropdown, expect it appears above rather than below the triggering button). I want the dropup menu to be centered.
The menu needs to be absolutely positioned, otherwise it'd get in the way of the flow of other DOM elements. And I need to position the container so that I could set bottom: 100%; on the menu so that it appears right above the triggering button.
In in this case you can use position:fixed BUT to avoid it being fixed apply a null transform to the body:
body {
transform:translate(0,0);
min-height:150vh;
}
.parent {
margin-left: 100px;
margin-top: 100px;
background: red;
position: relative;
width: 50px;
height: 50px;
}
.child {
background: blue;
position: fixed;
left:50%;
transform:translate(-50%,-100%);
}
<div class="parent">
<div class="child">
child
</div>
</div>

CSS: make div height fit parent div

I'm trying to make a floating div have a height that fills in the parent div.
http://jsfiddle.net/sergep/2qPZ2/1/
The structure is as follows:
Parent div______________________
| Middle child
| Left child - float:left
| Right child - float:right
The problem is that the left child has less text than the right, meaning the right increases the height of the parent div (to fit the div), but the left floating div does not follow suit.
The css looks like so:
.bottomcontainer {
bottom: 0;
position: absolute;
width: 100%;
height: auto;
}
.bottomleft {
background: #346CA5;
float:left;
width: 50%;
}
.middle {
background: #FFCE3C;
}
.bottomright {
background: #65B237;
float:right;
width: 50%;
}
How can I make the blue .bottomleft class stick to the bottom of the .bottomcontainer? - I'm trying to make responsive, so I don't want to use actual pixel sizes!
Consequently, how do I make the text inside vertically align middle?
Use display:table-cell; on the child divs, see here for an example that can be extrapolated
I misunderstood the question. You can fix that by adding an extra div around .bottomleft and .bottomright and display it as table / tablecells:
HTML:
<div id="nav"></div>
<div id="container">
<div class="bottomcontainer">
<div class="middle">
<h2>Intro tag line here</h2>
</div>
<div class="bottom">
<div class="bottomleft">
<h2>Tag line here</h2>
</div>
<div class="bottomright">
<h2>Longer tag line goes here</h2>
</div>
</div>
</div>
</div>
<div name="content" id="content"></div>
CSS:
.bottom {
display: table;
}
.bottomleft {
display: table-cell;
background: #346CA5;
opacity: 1.0;
width: 50%;
vertical-align: middle;
}
.bottomright {
display: table-cell;
background: #65B237;
opacity: 1.0;
width: 50%;
}
And updated Fiddle 2
Delete the float, and add an absolute positioning:
.bottomleft {
background: #346CA5;
opacity: 1.0;
position: absolute;
bottom: 0;
width: 50%;
vertical-align: middle;
}
Also check the updated Fiddle.

How do I automatically stack divs vertically inside a parent?

Here's what I am trying to accomplish...
"parent" has position:relative
"div 1-3" have position:absolute
However, whenever I do this, I find myself having to assign specific "top" values in my CSS. So div 1 might be top:50px, div 2 would be top:150px, and div 3 would be top:225px;
Is there a way to make sure the divs continue to stack inside the parent without assigning top values and/or absolute positioning?
A div should already display as a block and take up a full "row". Here is some HTML and CSS to give an example, compare it to your code:
http://jsfiddle.net/mWcWV/
<div id="parent">
<div class="child">Foo</div>
<div class="child">Bar</div>
<div class="child">Baz</div>
</div>
Should be straight:
HTML:
<div class="container">
<div class="red"></div>
<div class="blue"></div>
<div class="green"></div>
</div>
CSS:
.container {
position: relative;
width: 500px;
height: 500px;
background-color: #ffbf00;
}
.red {
background-color: #f00;
width: 200px;
height: 150px;
margin: 5px auto;
}
.blue {
background-color: #0f0;
width: 200px;
height: 150px;
margin: 5px auto;
}
.green {
background-color: #00f;
width: 200px;
height: 150px;
margin: 5px auto;
}
Check this fiddle.
In css file use...
div
{
display : block;
}
Which will give a break line for each div block and that feature is by default and don't use relative - absolute technique.
Div elements are block elements, which means that they will take a full row and that any element next to them will skip a line.
Just do:
<div></div>
<div></div>
<div></div>
If that does not work, you probably need to put them in display: inline-block;
Just remove absolute positioning. Center the divs using margin:auto and then provide whatever vertical margins you like.
You can give margin to inner div.

Resources