Can i get the height of the previous element using only CSS?
I am using calc() function to set dynamically height of the div B.
#b{
height:calc(100vh - heightOfPreviousElement);
}
I need to know the height of the previous element.
what i know is that, 100vh is equal to 100% of the screen height.
I used the code in the answer below.Using flex,
I have one problem. The height of the color orange become smaller.
You can easily achieve the effect you're looking for using flexbox. The trick is to allow the blue container (the one with the flexible height) to grow in size whenever the need arises, using flex: 1 1 auto, which is simply a shorthand for:
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;
See proof-of-concept code snippet below:
body {
padding: 0;
margin: 0;
}
.wrapper {
display: flex;
flex-direction: column;
flex-wrap: no-wrap;
align-items: center;
justify-content: center;
height: 100vh;
}
.wrapper > div {
width: 100%;
}
#c1 {
background-color: #880015;
color: #fff;
height: 60px;
margin-bottom: 10px;
}
#c2 {
background-color: #ff7f27;
}
#c3 {
background-color: #00a2e8;
flex: 1 1 auto;
margin-bottom: 10px;
}
<div class="wrapper">
<div id="c1">height: 60px</div>
<div id="c2">height: auto (determined by content?)</div>
<div id="c3">flexible height</div>
</div>
No you can't select a previous element in CSS.
You might be interested in JQuery Prev OR Parents method for selecting previous element and apply height using .css() method?
Related
This is how I want my Layout
Currently it looks like this
I can increase the size of the second box by specifying the height.
.row-2 {
height: 500px;
}
Surely there is a better way than this.
I've also tried to force the last row of boxes to the bottom without any luck:
.row-3 {
margin-top: auto;
}
My flexbox is as follows:
<div className="container">
<div className="row-1">1</div>
<div className="row-2">2</div>
<div className="row-3">
<div>3</div>
<div>4</div>
</div>
</div>
.container {
display: flex;
flex-direction: column;
max-width: 100%;
}
.row-1 {
border: 2px solid green;
}
.row-2 {
border: 2px solid blue;
}
.row-3 {
border: 2px solid red;
display: flex;
flex: 1;
margin-top: auto; /* not working */
}
.row-3 > div {
flex-grow: 1;
border: 2px solid purple;
}
Having flex-grow: 1; is probably a problem. I think that you're specifically saying that the third row can grow more. You might want to delete that and set flex-grow: 2; on the second row.
Maybe set width: 100%; on the second row?
It does look like you should use css-grid instead though. I'd recommend this tutorial for learning it
I am suspecting that your container is the immediate child of the <body>. If so, body will have height as much as it has to hold, in this case it will have the height same as the container. Because of this you are not able to do what you really want.
I would recommend you to add min-height: 100vh to the container, this will create the container of height 100% of the viewport.
.container {
min-height: 100vh
}
And your rest of the code will do the job.
In the following HTML, I want to set the height of left and right 100% of the parent element. In addition, the left div has fixed width. The right should use all of the remaining width.
I think because of using display: flex; in the parents div, the width of the left div doesn't stay constant. How can I set fixed width for it and allocate all of the remaining space to the right.
Edit: the calc(100-52px) is the height of the parent. The question is only about setting fixed width of 100px to the left so that it doesn't change on resizing the window.
Here's what I'm trying:
body {
padding: 0;
margin: 0;
}
.parent {
background: red;
display: flex;
height: calc(100vh - 52px);
}
.left {
width: 100px;
background: yellow;
}
.right {
background: orange;
width: 100%;
}
<div class="parent">
<div class="left">the width should be fixed, not flexible</div>
<div class="right">width should be all of the remaining</div>
</div>
parent { display: -webkit-box;display:-webkit-flex;display: -ms-flexbox;display:flex;flex-wrap: wrap; }
.parent > [class*='col-'] { display: flex; flex-direction: column; }
You can use width: calc(100% - 100px) or flex: 1 for the right div.
Percentage values are calculated from the parent element, therefore you need to extract static values from 100% to get the remaining area.
But as you are already using a flex container here, you can just set flex: 1, which is the shorthand for flex-grow: 1, that will allow your container to take all the extra space in the parent container, since no other items are available.
Add a flex declaration to the .left selector:
flex: 0 0 100px;
flex syntax:
none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
So this declaration is stating: "don't grow, don't shrink, define the initial size as 100px"
Read more: flex (MDN)
If right is to stand 52px away from the far right, then a margin will do . Please clarify your question.
body {
padding: 0;
margin: 0;
}
.parent {
background: red;
display: flex;
height: calc(100vh - 52px);
}
.left {
width: 100px;
background: yellow;
}
.right {
flex-grow: 1;
background: orange;
margin-right: 52px;
}
<div class="parent">
<div class="left">the width should be fixed, not flexible</div>
<div class="right">width should be all of the remaining</div>
</div>
Set flex: 0 0 100px; on your .left div (you can remove width: 100px) if you want it to be a constant 100px - so no growing or shrinking.
body {
padding: 0;
margin: 0;
}
.parent {
background: red;
display: flex;
height: calc(100vh - 52px);
}
.left {
flex: 0 0 100px;
background: yellow;
}
.right {
background: orange;
width: 100%;
}
<div class="parent">
<div class="left">the width should be fixed, not flexible</div>
<div class="right">width should be all of the remaining</div>
</div>
see if this helps you, comment if you need any changes
stackblits link for 1 fixed width, 1 relative column
This question is more project specific. I have two <div> in my template which looks like this.
I want that last div to acquire full height respective to window from its vertical position.
For example,
If I add another div, it should look like this.
Right now in this example, I am setting height explicitly just for demonstration purpose.
How can I make the last div calculate height according to its vertical position and all content should be visible inside the window.
You can use flexbox for this. The flow is column so the div's are vertically aligned. The last div get a flex:1 to expand.
flex:1 or flex:1 1 0% is a short writing for:
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0%;
For your last div the flex-grow and the flex-basis is important.
See flex property
body {
height: 100vh;
}
.container {
display: flex;
flex-flow: column nowrap;
height: 100%;
}
.container>div {
background: #ccc;
border-top: 3px solid white;
}
.container>div:last-child {
flex: 1;
}
<div class="container">
<div>1</div>
<div>2</div>
<div>3</div>
</div>
.container {
display: block;
position: fixed;
top: 0; /* where you want to start; */
bottom: 0; /* (the end) */
left: 0;
/* you can use width 100% or code right:0; */
}
<div class="container">
somethin
</div>
I am using css flex layout to build a dashboard and would like to put two widgets (one on top of the other) inside of a flex item and make them 50% height of their parent at all times (regardless of content). So if my html is:
<div class="flex-container">
<div class="flex-item">
<div class="widget" id="w1">
widget 1 content
</div>
<div class="widget" id="w2">
widget 2 content
</div>
</div>
</div>
and my css looks like:
.flex-container {
display: flex;
flex-direction: column;
}
.flex-item {
flex: 1;
}
How can I get the two .widgets to always occupy 50% height of .flex-item?
I've tried:
.flex-item {
flex: 1;
display: flex;
}
.widget {
flex: 1;
}
But this only works when the content in both widgets are the same.
I've worked up a more elaborate jsfiddle to better illustrate my issue.
Thanks in advance!
When you say that flex: 1 only works when the content in both widgets are the same, that is not correct. That would defeat the purpose of flex: 1.
flex: 1 tells flex items to distribute container space evenly among themselves. If there are four flex items with flex: 1, each will take 25%. Three would take 33.33%. And two flex items will take 50%. This is regardless of content quantity.
See this illustration: DEMO
The problem you're having is not clear in the code you posted in the question. However, it's apparent in your fiddle demo.
You have a main container with a height: 400px. You also have a rule adding 10px padding all-around to your divs. This adds 20px height to each div. You also have a header with height: 2em.
When you account for the extra heights the layout works.
Try these adjustments:
HTML (no changes)
CSS
div {
box-shadow: inset 0 0 0 1px rgba(30, 100, 200, 0.5);
padding: 10px; /* sneaky villain */
font-family: arial;
}
h1, p { margin: 0; }
#main-wrapper {
height: 400px; /* primary height */
display: flex;
flex-direction: column;
}
#header {
flex-shrink: 0;
height: 2em; /* header height */
}
#main-column-wrapper {
flex: 1;
display: flex;
flex-direction: row;
height: calc(100% - 2em - 20px); /* primary height - header height - padding */
}
#side-column {
width: 20%;
flex-shrink: 0;
}
#main-column {
flex: 1;
display: flex;
flex-direction: column;
height: calc(100% - 40px); /* main-column-wrapper height - padding (2 divs) */
}
#widget1,
#widget2 {
flex: 1;
flex-shrink: 0;
overflow: auto;
}
Revised Fiddle
Another option would be to use box-sizing: border-box to adjust for the padding. Learn more here: https://css-tricks.com/box-sizing/
This question already has answers here:
Chrome / Safari not filling 100% height of flex parent
(5 answers)
Closed 6 years ago.
I've got a delicate problem for any CSS guru out there.
My green div has a flexible height, taking up the remaining.
And now I want to put a div inside that div which should be the half of the green div. But it seems like if Chrome treats it like half of the whole page rather than the flex item.
http://jsfiddle.net/unh5rw9t/1/
HTML
<body>
<div id="wrapper">
<div id="menu">
1
</div>
<div id="content">2
<div id="half_of_content">2.1</div>
</div>
<div id="footer" style="">
3
</div>
</div>
</body>
CSS
html,body {
height: 100%;
margin: 0;
}
#wrapper {
display: flex;
flex-flow: column;
height: 100%;
}
#menu {
height: 70px;
background-color: purple
}
#content {
flex: 1;
height: 100%;
background-color: green;
}
#half_of_content {
height: 50%;
background-color: yellow;
}
#footer {
height: 100px;
background-color: cyan
}
#Michael_B explained why Chrome behaves like this:
You gave the body a height: 100%. Then gave its child (.wrapper)
a height: 100%. Then gave its child (.content) a height: 100%.
So they're all equal height. Giving the next child (#half_of_content) a height: 50% would naturally be a 50% height
of body.
However, Firefox disagrees because, in fact, that height: 100% of .content is ignored and its height is calculated according to flex: 1.
That is, Chrome resolves the percentage with respect to the value of parent's height property. Firefox does it with respect to the resolved flexible height of the parent.
The right behavior is the Firefox's one. According to Definite and Indefinite Sizes,
If a percentage is going to be resolved against a flex item’s
main size, and the flex item has a definite flex
basis, and the flex container has a definite main
size, the flex item’s main size must be treated as
definite for the purpose of resolving the percentage, and the
percentage must resolve against the flexed main size of the
flex item (that is, after the layout algorithm below has been
completed for the flex item’s flex container, and the flex
item has acquired its final size).
Here is a workaround for Chrome:
#content {
display: flex;
flex-direction: column;
}
#content::after {
content: '';
flex: 1;
}
#half_of_content {
flex: 1;
height: auto;
}
This way the available space in #content will be distributed equally among #half_of_content and the ::after pseudo-element.
Assuming #content doesn't have other content, #half_of_content will be 50%. In your example you have a 2 in there, so it will be a bit less that 50%.
html,
body {
height: 100%;
margin: 0;
}
#wrapper {
display: flex;
flex-flow: column;
height: 100%;
}
#menu {
height: 70px;
background-color: purple
}
#content {
flex: 1;
height: 100%;
background-color: green;
display: flex;
flex-direction: column;
}
#content::after {
content: '';
flex: 1;
}
#half_of_content {
flex: 1;
background-color: yellow;
}
#footer {
height: 100px;
background-color: cyan
}
<div id="wrapper">
<div id="menu">
1
</div>
<div id="content">2
<div id="half_of_content">2.1</div>
</div>
<div id="footer" style="">
3
</div>
</div>
You could absolutely position div id="half_of_content".
#content {
flex: 1;
height: 100%;
background-color: green;
position: relative; /* new */
}
#half_of_content {
height: 50%;
background-color: yellow;
position: absolute; /* new */
width: 100%; /* new */
}
DEMO
With regard to your statement:
But it seems like if Chrome treats it like half of the whole page
rather than the flex item.
You gave the body a height: 100%. Then gave its child (.wrapper) a height: 100%. Then gave its child (.content) a height: 100%. So they're all equal height. Giving the next child (#half_of_content) a height: 50% would naturally be 50% height of body.
With absolute positioning, however, you don't need to specify parent heights.
Nesting flexboxes is a little buggy. I reworked your markup a little by adding an inner wrapper with display: flex; which seems to do the job. Here is the fiddle (also using class names instead of ids).
<div class="content">
<div class="wrapper-inner">
2
<div class="half">
2.1
</div>
</div>
</div>
.wrapper-inner {
position: absolute;
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
}
Fix:
on #content set
display: flex;
flex-flow: column nowrap;
justify-content: flex-end
on #half_of_content set flex: 0 0 50%;
Caveat: you need to add an extra div as a child of #content.
Here's the full example:
html,body {
height: 100%;
margin: 0;
}
#wrapper {
display: flex;
flex-flow: column;
height: 100%;
}
#menu {
height: 70px;
background-color: purple
}
#content {
flex: 1;
height: 100%;
display:flex;
flex-flow: column nowrap;
justify-content: flex-end;
background-color: green;
}
#half_of_content {
flex: 0 0 50%;
background-color: yellow;
}
#footer {
height: 100px;
background-color: cyan
}
<body>
<div id="wrapper">
<div id="menu">
1
</div>
<div id="content">2
<div id="half_of_content">2.1</div>
</div>
<div id="footer" style="">
3
</div>
</div>
</body>