CSS Relative children take height of parent - html

I have a parent div with padding, inside there are 2 children. I want for second child b to take the rest of the height of parent (minus div a). And if div a is not present, than take all height. (with same css!)
#parent {
position: relative;
left: 0;
max-width: 500px;
max-height: 200px;
background: #333;
top: 0;
overflow: hidden;
}
#parent:after {
padding-top: 56.25%;
display: block;
content: '';
}
.a {
position: relative;
height: 20px;
width: 100%;
background: red;
}
.b {
position: relative;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: blue;
overflow: hidden;
}
<div id="parent">
<div class="a">1 </div>
<div class="b">2 </div>
</div>
edit:
why was the question downvoted? What is wrong with the question? how do I ask it without being downvoted?

You can use view-height css unit for div b. Example with your code. If you remove div a you will notice that div b will take all the height.
#parent {
position: relative;
left: 0;
max-width: 500px;
max-height: 200px;
background: #333;
top: 0;
overflow: hidden;
}
#parent:after {
padding-top: 56.25%;
display: block;
content: '';
}
.a {
position: relative;
height: 20px;
width: 100%;
background: red;
}
.b {
position: relative;
top: 0;
left: 0;
width: 100%;
height: 100vh;
background: blue;
overflow: hidden;
}
<div id="parent">
<div class="a">1 </div>
<div class="b">2 </div>
</div>

The intended behaviour can be achieved with flex-box layouts, as demonstrated in the Code Snippet embedded below.
Solution Breakdown:
#parent - declare flex on containing parent element, as well as
flex-wrap so that nested elements can occupy the full-width of the
container, we want to maintain the row direction here.
.a - declare flex-basis on this nested element; which is
tantamount to declaring width: 100% - we want it to remain
full-width so that the following sibling element (.b) wraps to a
new row.
.b - declare the shorthand property flex: 1 1 to specify that
this element should occupy the full width and height of its
containing element but not exceed it. The flex1 property is a
shorthand for flex-shrink2,
flex-grow3, and flex-basis4
#parent {
position: relative;
left: 0;
max-width: 500px;
max-height: 200px;
background: #333;
top: 0;
overflow: hidden;
/* additional */
display: flex;
flex-wrap: wrap;
}
#parent:after {
padding-top: 56.25%;
display: block;
content: '';
}
.a {
position: relative;
height: 20px;
background: red;
/* additional */
flex-basis: 100%;
}
.b {
position: relative;
background: blue;
/* additional */
flex: 1 1;
}
<div id="parent">
<div class="a">1</div>
<div class="b">2</div>
</div>
<br>
<div id="parent">
<div class="b">2</div>
</div>
A note on flex-box:
Since flex-box has limited to no support for legacy browsers (like I.E) for full browser support and compatibility refer to either one of the aforementioned alternatives.
See browser compatibility:
caniuse.com
flex - CSS | MDN
Edit
Updated
#parent {
position: relative;
left: 0;
max-width: 500px;
max-height: 200px;
background: #333;
top: 0;
overflow: hidden;
/* additional */
display: flex;
flex-direction: column;
height: 200px; /* an absolute height value is required for relative flex-box heights */
}
/*#parent:after { kill the interloper
padding-top: 56.25%;
display: block;
content: '';
}*/
.a {
position: relative;
height: 20px;
background: red;
}
.b {
position: relative;
background: blue;
/* additional */
flex: 1 1;
}
<div id="parent">
<div class="a">1</div>
<div class="b">2</div>
</div>
<br>
<div id="parent">
<div class="b">2</div>
</div>
The updated snippet demonstrates an alternative solution with a column direction. The pseudo-element #parent:after has been removed as it negates any attempt to achieve the behaviour specified in your question (if this pseudo-element is required in any shape or form, consider updating your question to point this out with clear explanations as to its function and or role).

Related

width:100vw of element breaks position: sticky

I am trying to stretch a sticky element to size of the screen. I have the following HTML
.large {
height: 200vw;
width: 200vw;
}
.header {
left: 0;
top: 0;
color:white;
position: sticky;
width: 100px;
height: 100px;
background: black;
}
<div class="header">Header</div>
<div class="large">Content</div>
The problem is that this works but the element is not stretched. If I change width:100px to width:100vw the sticky to the left breaks. So it seems like I cannot specify relative width and use sticky to the left at the same time?
You can achieve this by adding a div around both elements and giving that div a display: inline-block;:
.container {
display: inline-block;
}
.large {
height: 200vw;
width: 200vw;
}
.header {
left: 0;
top: 0;
position: sticky;
width: 100vw;
height: 100px;
background: black;
}
<div class="container">
<div class="header"></div>
<div class="large"></div>
</div>

How to get a div centered with another div on the right of it?

I'm trying to make a centered div with another div on the right of it. So the div on the left is horizontal centered. De div on the right is directly on the right of the centered div. I've tried it in many ways with different displays and margins etc but I can't seem to figure it out.
All tips are welcome!
div {
width: 100px;
height: 100px;
display: inline-block;
}
#left {
left: 50%;
background: #009a9a;
}
#right {
background: #bbad4f;
}
<div id="left"></div>
<div id="right"></div>
You can do it with the Flexbox and positioning:
.flex-container {
display: flex; /* displays flex-items (children) inline */
justify-content: center; /* centers them horizontally */
position: relative;
}
.flex-container > div {
width: 100px;
height: 100px;
}
#left {
background: #009a9a;
}
#right {
position: absolute;
left: 50%; /* moved right by half of the parent's width */
transform: translateX(50%); /* and half of its own width */
background: #bbad4f;
}
<div class="flex-container">
<div id="left"></div>
<div id="right"></div>
</div>
No matter the divs width (as long as they stay the same), this solution is dynamic, therefore no unnecessary margins or calc().
But with the help of CSS variables you can make it completely dynamic:
:root {
--leftWidth: 200px;
}
.flex-container {
display: flex;
justify-content: center;
position: relative;
}
.flex-container > div {
width: 100px;
height: 100px;
}
#left {
width: var(--leftWidth);
background: #009a9a;
}
#right {
position: absolute;
left: calc(50% + (var(--leftWidth)/2)); /* moved right by half of the parent's and sibling's width */
background: #bbad4f;
}
<div class="flex-container">
<div id="left"></div>
<div id="right"></div>
</div>
body,
html {
height: 100%;
font-size: 0;
}
div {
width: 100px;
height: 100px;
display: inline-block;
}
#left {
left: 50%;
top: 50%;
position: relative;
transform: translate(-50%, -50%);
background: #009a9a;
}
#right {
background: #bbad4f;
left: calc(50% + 100px);
top: calc(50% + 100px);
position: relative;
transform: translate(calc(-50% - 100px), calc(-50% - 100px));
}
<div id="left"></div>
<div id="right"></div>
Here another example if you can't use transform or if you don't know elements size. You can do it with flexbox or just just by using margin: auto to center the first element.
.Container {
display: flex;
justify-content: center;
}
.Left {
background-color: red;
position: absolute;
left: 100%;
top: 0;
}
.Centered {
background-color: cyan;
position: relative;
}
/* Demo only */
.Centered, .Left {
border-radius: 4px;
padding: 8px 24px;
}
<div class="Container">
<div class="Centered">
<div class="Left">Right</div>
Centered
</div>
</div>
This is using absolute positions. Please not that the amount of left:150px; is the half width of centered div + half width of left div. Also the style margin-left:200px; on the lef div, comes from the width of centered div.
.container {
position: relative;
}
.centered {
width: 200px;
background: #eeeeee;
position: absolute;
height: 100px;
margin: auto;
left: 0;
right: 0;
}
.leftOf {
background: #ff8800;
position: absolute;
left: 150px;
margin-left: 200px;
height: 100px;
width: 100px
}
<div class="container">
<div class="centered"></div>
<div class="leftOf"></div>
</div>

How to make div height 100% inside relative div?

This is my code:
<div class="parent">
<div class="child-1"> CHILDREN 1 </div>
<div class="child-2"> CHILDREN 2 </div>
<div class="child-3"> CHILDREN 3 </div>
</div>
CSS:
.parent {
position: relative;
height: 250px;
}
.child-1 {
position: absolute;
top: 0;
width: 100%;
}
.child-2 {
height: 100%;
}
.child-3 {
position: absolute;
bottom: 0;
width: 100%;
}
I set child-2 as 100% but didn't happen. So, how to make .child-2 height 100% and between child-1 and child-3?
Assuming I understood correctly what you want to do... This seems like a job for Captain FlexBox®.
.parent {
display: flex;
flex-direction: column;
width: 300px;
height: 200px;
background: Yellow;
}
.child-1 {
background: Red;
}
.child-2 {
flex-grow: 1;
background: Green;
}
.child-3 {
background: Blue;
}
<div class="parent">
<div class="child-1"> CHILDREN 1 </div>
<div class="child-2"> CHILDREN 2 </div>
<div class="child-3"> CHILDREN 3 </div>
</div>
The important parts are setting display: flex on the container, instructing the rendering engine to calculate by the flex rules, changing the direction to vertical with flex-direction: column and making only the middle child fill up all the remaining space with flex-grow: 1.
Maybe if you delete the position: absolute; from your .child you will get that you want, cause in your case you get the .child-2 on the top of .child-1 div.
Try this:
.parent {
position: relative;
height: 250px;
}
.child-1 {
top: 0;
width: 100%;
}
.child-2 {
height: 100%;
}
.child-3 {
bottom: 0;
width: 100%;
}
You can use display:table-cell property for this
Add your child-2 below css:
.child-2 {
height: 100%;
position: absolute;
top: 50%;
bottom: 50%;
}
And your child-3 class top 100%:
.child-3 {
position: absolute;
bottom: 0;
width: 100%;
top: 100%;
}
child-2 will become at the middle of the other two divs.

IE setting "top" to a percentage value not working for an absolutely positioned element inside table-cell

I've tried the following and it's working well in Firefox, Opera, Chrome and Safari. I couldn't get it to work with IE though, am I missing something?
http://jsfiddle.net/amrn/qn0dwohn/
inside .centered the left property is working properly, but it seems to be ignoring top.
(I'm using table and table-cell because I want the height of .right to be automatically the same as .left).
.wrapper {
display: table;
}
.left,
.right {
display: table-cell;
width: 200px;
}
.left {
height: 200px;
background-color: orange;
}
.right {
background-color: teal;
position: relative;
}
.centered {
background-color: tomato;
height: 70px;
width: 70px;
position: absolute;
top: 50%;
left: 50%;
}
<div class="wrapper">
<div class="left"></div>
<div class="right">
<div class="centered"></div>
</div>
</div>
There seems to be a couple of ways to handle this.
UPDATED
Because IE seems to have an issue with absolute positioning while using table cells you can add another nested div that uses display: block; You can see the js.fiddle here.
<div class="wrapper">
<div class="left"></div>
<div class="right">
<div class="nest">
<div class="centered"></div>
</div>
</div>
</div>
.nest {
position: relative;
background: pink;
}
The second method would be to not use display: table-cell and instead use display: inline-block Like this:
.wrapper {
display: block;
}
.left, .right {
position: relative;
display: inline-block;
width: 200px;
height: 200px;
}
.left {
background-color: orange;
}
.right {
background-color: teal;
}
.centered {
background-color: tomato;
height: 70px;
width: 70px;
position: absolute;
top: 50%;
left: 50%;
}
You can see this working in your Js.Fiddle here.
Or lastly you could do the easiest fix which would be to add height to your HTML and BODY which will give your table a height of something greater than 0 since no content exists in it. You can see a similar SO question here about it.
html, body {
height: 100%
}
Hope that helps.
I ended up doing it by using an extra nested div which is absolutely positioned in relation to the relatively positioned table (not the table-cell). http://jsfiddle.net/amrn/qn0dwohn/17/
The downside is that I have to explicitly set the width on that extra div to be the same as its parent.
.wrapper {
display: table;
position: relative;
}
.left,
.right {
display: table-cell;
width: 200px;
}
.left {
height: 300px;
background-color: orange;
}
.right {
background-color: teal;
}
.right-wrapper {
position: absolute;
width: 200px;
bottom: 0;
top: 0;
background-color: aquamarine;
}
.centered {
background-color: tomato;
height: 70px;
width: 70px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
<div class="wrapper">
<div class="left"></div>
<div class="right">
<div class="right-wrapper">
<div class="centered"></div>
</div>
</div>
</div>

Get CSS DIV to fill all height between other DIVs

I have a modal dialog for a workflow that displays content roughly of a fixed height, but also displays an embedded PDF for a user to review.
I'd like to maximize the height of the PDF for the user's screen size, so the dialog scales vertically, but I can't get the PDF to fill all the remaining space within the dialog's div.
Here is the Html:
<div class="container">
<div class="popUp">
<div class="popUpHeader">Header</div>
<div class="fixedContent">Fixed Height Content</div>
<div class="resizeableContent">I should fill all the free vertical space in .popUp</div>
<div class="popUpFooter">Footer</div>
</div>
</div>
and CSS I'm using:
body, html {
margin: 0;
height: 100%;
}
.container {
height: 100%;
min-height: 100%;
background: #F8F8FF;
}
.popUp {
background: lightgrey;
margin: auto;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
width: 70%;
height: 90%;
}
.popUpHeader {
width: 100%;
background: darkgrey;
text-align: center;
}
.popUpFooter {
width:100%;
background:darkgrey;
text-align:center;
position: absolute;
bottom: 0;
}
.fixedContent {
height: 10em;
text-align: center;
background: #E1E1EE;
}
.resizeableContent {
background: #7d7f7c;
text-align: center;
width: 100% height: 100%;
}
JsFiddle: http://jsfiddle.net/trainman1124/pnbeoyb9/2/
Here is an image of the desired result:
Edit
Here is a sample JsFiddle using an embedded PDF, which is what actually needs to be done.
http://jsfiddle.net/trainman1124/pnbeoyb9/3/
Note, I've corrected the missing semicolon in the example and also added overflow:hidden
You could use the display: table; and display: table-row properties in order to fill the space.
Set the .container to fill 100% of the page and .popUp div to display: table; and fill it's parent.
Display all the children as display: table-row;, and then set heights for the popUpHeader and popUpFooter divs.
Allow your resizableContent div to fill the remaining space:
.resizeableContent {
background: #7d7f7c;
width: 100% height: 100%;
display: table-row;
}
Check out this CodePen
Modify Popup class to make its color same as resiseableContent
.popUp {
background: #7d7f7c; /* Modified here */
margin: auto;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
width: 70%;
height: 90%;
overflow: hidden;
}
Depending on what browsers you need to support (This wont work earlier than IE9), one solution would be to use calc and vh units.
Something like:
.popUp {
background: lightgrey;
margin: auto;
height: calc(100vh - 10em); /* Height of viewport minus your .fixedContent div, you may also want to include the height of the header */
overflow: hidden;
}
The updated fiddle has the heights set to % instead. That works as you want I think?
Update
http://jsfiddle.net/batcave/pnbeoyb9/7/
.popUpFooter {
width:100%;
background:darkgrey;
text-align:center;
position: absolute;
bottom: 0;
height: 7%;
}
.resizeableContent {
background: #7d7f7c;
text-align: center;
width: 100%;
height: 80%;
}
.fixedContent {
height: 10%;
text-align: center;
background: #E1E1EE;
}