Reputation: 99
I want to align two elements in such a way, that one sticks to the top, and one to the bottom of the viewport. I'm trying to achieve this with flexbox, but don't want to use absolute positioning.
Whatever I tried, didnt work: I found this question on stock overflow, and tried to implement those answers - yet I still can't achieve the wanted result. Can anybody point me in the right direction, or explain what I did wrong?
Below is my html / css, here you can find the code snippets on jsbin, with different stuff i tried.
All of the other stackoverflow questions I found regarding this topic didn't work for me either - I really don't get why. Any help would be really appreciated.
<html>
<body>
<div class="top">
<p class="text">Top</p>
</div>
<div class="bottom">
<p class="text">Bottom</p>
</div>
</body>
</html>
body {
min-height: 100%;
display: flex;
flex-direction: column;
}
.top {
flex-grow: 1;
}
.bottom {
margin-top: auto;
}
Upvotes: 1
Views: 60
Reputation: 5291
The CSS in the snippet contains a full explanation of what I did and why, so here just a summary:
min-height: 100%
needs to be min-height: 100vh
as with 100%
body will only take up the summarized height of the direct child elements it contains.justify-content: space-between
to move outermost child elements to either side of the flexbox container. With flex-direction: column
that would be top and bottom of the container..top
and .bottom
CSS as-is obsolete.Snippet
/* Demo, to better see space distribution */
* { outline: 1px dashed }
p {
/* BEWARE: by default a <p> has 'margin: 1em 0'
adding extra space above and below */
}
body {
min-height: 100vh; /* from 100% */
/* as 100% will make body only use up total height
of elements it contains. 100vh will force it to
fill the entire viewport height.
*/
margin: 0; /* to remove HTML default 8px spacing */
/* Margin adds to the total height of body
causing the vertical scrollbar to appear
when using 100vh */
display: flex; flex-direction: column;
/* moves two outer elements to either side */
/* more elements get distributed inbetween */
justify-content: space-between;
/* I put in extra <div> between top and bottom
to show what happens.
*/
}
.top {/* [OBSOLETE] */
/* makes this element fill the entire screen */
/* flex-grow: 1; /* probably unwanted, disabled */
}
.bottom {/* [OBSOLETE] */
/* margin-top: auto; /* not required for effect */
/* handled by flexbox parent justify property */
}
/*
As body grows with content it can (and probably will)
exceed 100vh, making .bottom move downward out of the
viewport. And when you scroll down, .top will move out
of view.
If you need either top/bottom permanently fixed you
will have to use the position: fixed property
on the elements instead of the Flexbox solution.
- .top { position: fixed; top: 0 }
- .bottom { position: fixed; bottom: 0 }
*/
<div class="top">
<p class="text">Top</p>
</div>
<div>
<p>extra div > p 1</p>
</div>
<div>
<p>extra div > p 2</p>
</div>
<div class="bottom">
<p class="text">Bottom</p>
</div>
Upvotes: 2
Reputation: 9238
You could use CSS grid and just create 3 rows. Two with size of auto
making the rows as big as they need to be and one of size 1fr
meaning it takes the rest of the space. There is a great guide for CSS grid at CSS Tricks.
body {
margin: 0px;
padding: 0px;
height: 100vh;
/* CSS Grid */
display: grid;
/* 3 rows */
grid-template-rows: auto 1fr auto;
}
.bottom {
background: red;
}
.top {
background: red;
}
<body>
<div class="top">
<p class="text">Top</p>
</div>
<div>
Content
</div>
<div class="bottom">
<p class="text">Bottom</p>
</div>
</body>
Upvotes: 2