I have a simple page layout with a vertical centered content box using flex.
I use min-height: 70vh; to stretch the container height to allow the content-box to vertical center.
I also have a footer which height gap is stretched to the bottom of the page using flex: 1;.
https://jsfiddle.net/Lvod41L2/
Problem
If the content-box has enough content that makes it taller than the page the footer is not pushed to the bottom and scrolls with the page. Example: height: 2000px;
If I remove min-height: 70vh; the footer is pushed to the bottom of the page as it should look.
HTML/CSS
<!DOCTYPE html>
<html>
<head>
<style>
html, body {
height: 100%;
margin: 0;
padding: 0;
}
body {
display: flex;
flex-direction: column;
}
.header {
min-height: 40px;
padding: 0.8em 2em;
background: black;
color: white;
}
.flex-container {
display: flex;
align-items: center;
min-height: 70vh;
padding: 2em;
background: gray;
}
.content-box {
width: 300px;
height: 300px;
margin: auto;
padding: 2em;
text-align: center;
background: black;
color: white;
}
.footer {
z-index: 100;
position: relative;
flex: 1;
padding: 2em;
background: black;
color: white;
}
</style>
</head>
<body>
<div class="header">
Header
</div>
<div class="flex-container">
<div class="content-box">
Content Box
</div>
</div>
<div class="footer">
Footer
</div>
</body>
</html>
SOLUTION - JSFIDDLE
Add flex: 0 0 auto; to the container
.flex-container {
display: flex;
align-items: center;
min-height: 70vh;
padding: 2em;
background: gray;
flex: 0 0 auto; /* Added rule */
}
I hope that solves the issue.
Related
This question already has answers here:
Fill remaining vertical space with CSS using display:flex
(6 answers)
Make a div fill the height of the remaining screen space
(42 answers)
Closed 1 year ago.
I am trying to vertically center text inside a child div that is full height, but when I do that it has extra spacing at the bottom. How can I do this without the extra spacing? I'd like to have a nav along with some vertically centered text, but without the extra spacing.
html {
height: 100%;
}
body {
margin: 0;
min-height: 100vh;
}
h1 {
margin: 0;
padding: 0;
}
.landing {
background: url(bg.svg);
height: 100vh;
}
.landing-content {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.landing-content h1 {
color: white;
margin: 0;
}
.app {
background-color: black;
height: 100vh;
color: white;
}
<div class="app">
<div class="logo">
<h1>logo</h1>
</div>
<div class="landing">
<div class="landing-content">
<h1>hi, i'm jordan</h1>
</div>
</div>
</div>
The use of height: 100vh was not suitable, what it does is recognize the view-width as its height and that limit limits the height and recreate a small crack at the bottom. You can try using height: 100% instead
html {
height: 100%;
}
body {
margin: 0;
min-height: 100vh;
}
h1 {
margin: 0;
padding: 0;
}
.landing {
background: url(bg.svg);
height: 100vh;
}
.landing-content {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.landing-content h1 {
color: white;
margin: 0;
}
.app {
background-color: black;
height: 100%;
color: white;
}
<div class="app">
<div class="logo">
<h1>logo</h1>
</div>
<div class="landing">
<div class="landing-content">
<h1>hi, i'm jordan</h1>
</div>
</div>
</div>
Remove landing class height and add landing-content class height to 100%. When you add landing class height to 100vh, It covers 100vh height. But logo class already covers some height. so it overflows.
.landing {
background: url(bg.svg);
}
.landing-content {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
working fiddle - https://jsfiddle.net/alimurrazi/36svho08/1/
Since .app has the default display: block, .logo takes up however much space it needs, then .landing goes underneath, taking up an additional 100vh, so that you need to scroll to view its full content.
The solution here is either to simply add overflow-y: hidden to .app, but that still leaves your text off center by a bit. Another solution would be to give .app display: flex, and using flexbox to distribute the space as needed.
html {
height: 100%;
}
body {
margin: 0;
min-height: 100vh;
}
h1 {
margin: 0;
padding: 0;
}
.landing {
background: url(bg.svg);
flex-grow: 1;
}
.landing-content {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
.landing-content h1 {
color: white;
margin: 0;
}
.app {
background-color: black;
height: 100vh;
color: white;
display: flex;
flex-direction: column;
}
<div class="app">
<div class="logo">
<h1>logo</h1>
</div>
<div class="landing">
<div class="landing-content">
<h1>hi, i'm jordan</h1>
</div>
</div>
</div>
Change the .app class as follow.
.app {
background-color: black;
height: auto;
color: white;
}
I am having some problems with the last child / the last child's margin being hidden outside the page/it's parent while the parent has max-height: -webkit-fill-available; height: auto; display:inline-block; and overflow: auto, as seen at https://jsfiddle.net/andreasjj/ok9hqgxv/2/
<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
body, html {
font-size: 16px;
margin: 0;
padding: 0;
}
body {
min-height: 100vh;
height: 100vh;
display: flex;
flex-direction: column;
}
#root {
height: inherit;
min-height: inherit;
overflow: hidden;
}
#wrapper {
display: flex;
flex-direction: column;
height: inherit;
min-height: inherit;
width: inherit;
}
#header {
display: flex;
flex-direction: row;
align-items: center;
min-height: 50px;
width: inherit;
background-color: #f8f8f8;
}
#container {
display: flex;
flex-direction: row;
width: inherit;
height: inherit;
}
#content {
height: inherit;
width: 100%;
overflow: hidden;
}
#box {
display: flex;
-webkit-box-align: center;
align-items: center;
-webkit-box-pack: center;
justify-content: center;
height: inherit;
width: inherit;
}
#box-content {
max-height: -webkit-fill-available;
height: auto;
overflow: auto;
display: inline-block;
padding: 0.75rem;
width: calc(100vw - 1.0rem);
max-width: 900px;
}
.module {
background-color: black;
border: 1px solid #e9e9e9;
padding: 1.0rem;
margin-bottom: 3rem;
width: 541px;
height: 461px;
}
.module:first-child {
margin-top: 3rem;
}
</style>
</head>
<body>
<div id="root">
<div id="wrapper">
<div id="header"></div>
<div id="container">
<section id="content">
<div id="box">
<div id="box-content">
<div class="module"></div>
<div class="module"></div>
</div>
</div>
</section>
</div>
</div>
</div>
</body>
</html>
The last black box is missing most of its margin which is hidden (and if you remove the margin, part of the box itself will be hidden).
I have tried to change the height, max-height of different ancestors, in addition to different display values. But nothing seem to work. Any ideas?
The structure of the html might seem a bit weird, but this is html and css extracted from a react app, so I'd like to keep the structure somewhat similar to not break the whole thing.
I'm not sure I fully understand your problem, but what I always start my CSS scripts with, is the following piece of code:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
The * means 'select everything' and the box-sizing makes sure that all the extra's like margins and borders are included in the size of an object.
https://www.w3schools.com/css/css3_box-sizing.asp
Hope it works for you!
I am trying to make a navbar using flexbox. In my code I have the actual navbar wrapped with flex- direction:"row" to align the logo and the button.
Now I want to have the nav-inner (the beige div) under the navbar (that should be 100vw wide), but actually it sits next to the navbar.
I have tried to change the flex-direction to "column" inside my nav-menu div, but the Hamburger button goes out of the screen. Am I doing something wrong?
body {
margin: 0;
overflow: hidden;
}
/* defaults */
.safe-view {
display: flex;
height: 100vh;
}
.hamburger {
height: 30px;
width: 30px;
}
/**/
/* navbar */
.navbar {
position: sticky;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 30px;
width: 100vw;
font-size: 1.2em;
height: 100px;
}
.nav-menu {
width: 100%;
display: flex;
flex-direction:row;
/*flex-direction:column;*/
position: absolute;
height: 100%;
overflow: hidden;
background-color: white;
}
.nav-inner {
height: 100%;
width: 100%;
background-color: blanchedalmond;
}
/**/
<div class="safe-view">
<div class="nav-menu">
<div class="navbar">
<h1>logo</h1>
<button class="hamburger"></button>
</div>
<div class="nav-inner"></div>
</div>
</div>
This is a CSS box-model issue. You need to add box-sizing: border-box. This will ensure that padding is included in calculation of the width.
*{
box-sizing: border-box;
}
By default box-sizing is set to content-box. This will only care about the element content and shift padding and border outside of the element. That is why you saw the button push out to the right! This can also help you to understand further.
Also, flex-direction for .nav-menu needs to be set to column in order to position .nav-inner below.
Heres an alternative. I removed padding and just used calc() function to create padding. But always include box-sizing:border-box in your CSS :)
*{
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
overflow: hidden;
}
.safe-view {
display: flex;
height: 100vh;
}
.navbar {
position: sticky;
display: flex;
flex-direction:row;
align-items: center;
justify-content: space-between;
width: calc(100vw - 60px);
margin: 0 auto;
font-size: 1.2em;
height: 100px;
}
.nav-menu {
width: 100%;
display: flex;
flex-direction:column;
position: absolute;
height: 100%;
overflow: hidden;
background-color: white;
}
.nav-inner {
height: 50px;
width: 100%;
background-color: blanchedalmond;
}
<div class="safe-view">
<div class="nav-menu">
<div class="navbar">
<h1 class="logo">logo</h1>
<button class="hamburger">button</button>
</div>
<div class="nav-inner"></div>
</div>
</div>
This question already has answers here:
How can I vertically center a div element for all browsers using CSS?
(48 answers)
Closed 5 years ago.
I've been learning CSS and am now practicing by trying to replicate basic websites, but I've stumbled across a problem!
I'm trying to vertically align a box so that it is always in the middle, and will automatically scale if I make the browser vertically smaller. So far I've tried to replicate what I've done horizontally (normally margin: 0 auto;) but it isn't working.
My relevant HTML and CSS so far look like this:
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* Global Values */
html{
font-family: "Arial";
font-size: 16px;
line-height: 1.2;
height: 100%;
}
body{
background-color: #f9f9f9;
height: 100%;
}
.container{
display: block;
min-width: 240px;
max-width: 768px;
width: 100%;
/*----------------------------------------------*/
/* This is to make sure that the container height is always the same size as the browser. */
min-height: 100px;
height: 100%;
/*----------------------------------------------*/
margin: 0 auto;
text-align: center;
border-style: solid;
}
header{
border: solid;
min-height: 100px;
margin: auto 5%;
}
<body>
<div class="container">
<header>
<h1>Jon Phillips</h1>
<p>User Interface Designer</p>
<nav class="contact">
<p>Contact</p>
</nav>
</header>
</div>
</body>
I'm showing the borders so I can see what's going on, and am sure that (like horizontal centering) my margins need to be automatic. When I've done this horizontally, it's worked fine...
Does anyone have a recommendation on what to do??
Thanks in advance!
Flexbox is your friend! You need to add the following to your container styles
display: flex;
align-items: center;
justify-content: center;
We're setting the display to flex/flexbox with display: flex; and aligning everything to the center with align-items: center; and justify-content: center;
With all the vendor-prefixes it looks like:
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* Global Values */
html{
font-family: "Arial";
font-size: 16px;
line-height: 1.2;
height: 100%;
}
body{
background-color: #f9f9f9;
height: 100%;
}
.container{
display: block;
min-width: 240px;
max-width: 768px;
width: 100%;
/*----------------------------------------------*/
/* This is to make sure that the container height is always the same size as the browser. */
min-height: 100px;
height: 100%;
/*----------------------------------------------*/
margin: 0 auto;
text-align: center;
border-style: solid;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
}
header{
border: solid;
min-height: 100px;
margin: auto 5%;
}
<body>
<div class="container">
<header>
<h1>Jon Phillips</h1>
<p>User Interface Designer</p>
<nav class="contact">
<p>Contact</p>
</nav>
</header>
</div>
</body>
Check this: https://codepen.io/danieldd/pen/pdooVN
<div class="container">
<div class="item-centered"></div>
</div>
.container {
height: 400px;
width: 100%;
background-color: cyan;
display: flex; /*this is needed for centering*/
align-items: center; /*this center vertically childred elements*/
justify-content: center; /*this center horizontally childred elements*/
}
.item-centered {
height: 200px;
width: 200px;
background-color: red;
}
Sadly the auto margins trick only works horizontally. In CSS3, you can use another trick. You start with top: 50%; and then subtract half the height of your container using transform: translateY(-50%);. The perspective(1px) is just to correct the calculation to a whole pixel and prevent issues in some browsers. See the three lines I've added to your CSS:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* Global Values */
html {
font-family: "Arial";
font-size: 16px;
line-height: 1.2;
height: 100%;
}
body {
background-color: #f9f9f9;
height: 100%;
}
.container {
display: block;
min-width: 240px;
max-width: 768px;
width: 100%;
/*----------------------------------------------*/
/* This is to make sure that the container height is always the same size as the browser. */
min-height: 100px;
height: 100%;
/*----------------------------------------------*/
margin: 0 auto;
text-align: center;
border-style: solid;
}
header {
border: solid;
min-height: 100px;
margin: auto 5%;
position: relative;
top: 50%;
transform: perspective(1px) translateY(-50%);
}
<body>
<div class="container">
<header>
<h1>Jon Phillips</h1>
<p>User Interface Designer</p>
<nav class="contact">
<a href="mailto:jon#jonphillips.ca" target="_blank">
<p>Contact</p>
</a>
</nav>
</header>
</div>
</body>
On the parent of the item that you're trying to center, you can just use display: flex; and the child should center inside (with the rest of the styles that you already have set up).
This could also be achieved using absolute positioning, though it would be a few more lines:
.parent {
position: relative;
}
.child {
/* Vertically center - will still need left / right & width adjustment otherwise */
position: absolute;
top: 50%;
transform: translateY(-50%);
}
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* Global Values */
html{
font-family: "Arial";
font-size: 16px;
line-height: 1.2;
height: 100%;
}
body{
background-color: #f9f9f9;
height: 100%;
}
.container{
display: block;
min-width: 240px;
max-width: 768px;
width: 100%;
display: flex;
/*----------------------------------------------*/
/* This is to make sure that the container height is always the same size as the browser. */
min-height: 100px;
height: 100%;
/*----------------------------------------------*/
margin: 0 auto;
text-align: center;
border-style: solid;
}
header{
border: solid;
min-height: 100px;
margin: auto 5%;
width: 100%;
}
<body>
<div class="container">
<header>
<h1>Jon Phillips</h1>
<p>User Interface Designer</p>
<nav class="contact">
<p>Contact</p>
</nav>
</header>
</div>
</body>
There are different approuces to solve this problem, the easyest and with a good compatibility is the use of the "table-cell display", so in your case adding this to your CSS:
.container {
display:table-cell;
height:100%;
vertical-align:middle
}
The point is that a correct implementation of a table-cell should consider the parent element as a table, your parent element is the body itself, so do change your CSS into:
body{
background-color: #f9f9f9;
height: 100%;
width:100%;
display:table
}
http://jsfiddle.net/9tghnydg/
On a second though the height propriety on the .container is not strictly necessary, acting it as the unique cell of the body table:
.container {
display:table-cell;
vertical-align:middle
}
http://jsfiddle.net/9tghnydg/1/
I have the following layout.
<div class="container">
<div class="content">
<div class="post">post</div>
<div class="image">image</div>
</div>
<div class="footer">footer</div>
</div>
http://jsbin.com/xicatoq/4/edit?html,css,output
The thing I want to achieve is to make the footer stick to the bottom (I don't want to use absolute positioning) and make the .content stretch from the top to the footer, like in the image below.
Can someone explain how I can achieve this?
In your code, the div with class content is a flex container. That makes the child elements (.post and .image) flex items.
However, your div with class container is not a flex container. So .content and .footer are not flex items, and cannot accept flex properties.
So, first step, add this:
.container {
display: flex;
flex-direction: column;
}
Then use flex auto margins to stick the footer to the bottom of the container:
.footer {
margin-top: auto;
}
Here's the full code:
body {
font-family: monospace;
color: #fff;
text-align:center;
}
.container {
width: 100%;
height: 800px;
background: red;
display: flex; /* NEW */
flex-direction: column; /* NEW */
}
.content {
/* float: left; */
width: 100%;
display: flex;
align-items: center;
}
.post {
width: 70%;
background: pink;
line-height: 300px;
}
.image {
width: 30%;
height: 500px;
background: green;
}
.footer {
background: blue;
line-height: 70px;
text-align: center;
/* float: left; */
width: 100%;
margin-top: auto; /* NEW */
}
<div class="container">
<div class="content">
<div class="post">post</div>
<div class="image">image</div>
</div>
<div class="footer">footer</div>
</div>
Revised Demo
Note that I commented out the floats. They aren't working. In a flex container floats are ignored.
Learn more about auto margins here: https://stackoverflow.com/a/33856609/3597276
Check this : http://jsbin.com/dojitevoye/edit?html,css,output
body {
font-family: monospace;
color: #fff;
text-align:center;
}
.container {
width: 100%;
height: 800px;
background: red;
}
.content {
float: left;
width: 100%;
height: 100%;
display: flex;
align-items: center;
}
.post {
width: 70%;
background: pink;
line-height: 300px;
align-self: flex-start;
}
.image {
width: 30%;
height: 500px;
background: green;
align-self: flex-start;
}
.footer {
background: blue;
line-height: 70px;
text-align: center;
float: left;
width: 100%;
align-self:flex-end;
}
Set the height for the .content class to 100%, which will take the height of it's parent ( which is .container ), which will be 800px in this case.
Now align both .post and .image to the top of the parent flexbox with align-self: flex-start;
Now, similarly set the .footer to the bottom of flexbox using align-self:flex-end;
Just use height: 100%; to .content will make footer stick to bottom.
Working JSBin