How to fix footer at the bottom of a component in react? - css

I'm trying to put a footer at the end of my homepage component. In my website, the overflow is made auto only for mobile view with a media query, so the scroll remains hidden for desktop view. I have used all the solutions I could find but nothing helps, the footer is perfectly aligned in desktop view at the bottom, but for mobile view, it is aligned at the end of the screen (not the page). I have no clue how to fix this.
website: https://shivamaima.netlify.com/
git: https://github.com/darwin619/portfolio
.homepage {
text-align: center;
width: 100%;
position:relative;
padding:0;
margin:0;
min-height:100vh;
top:0;
#media screen and (max-width: 600px) {
overflow: auto;
height: 100vh;
}
.footer {
position: absolute;
right: 0;
bottom: 0;
left: 0;
padding: 1rem;
text-align: center;
}

There's a couple solutions here. Instead of bottom: 0 use:
margin-top: 100vh;
This will set the footer at the bottom of the viewport height.
However, your page has quite a few layout issues, and this is really a band-aid. You should consider utilizing flexbox, min-height, or grid to create a sticky footer.
That being said, the solutions for this using react are what they would be in most any circumstance.
The following solutions are preferable because they are "true" dynamic sticky footers. Meaning, the footer stays at the bottom until the main content extends beyond that area, at which point the footer will begin adjusting its position downward:
The min-height Solution
nav {
height: 40px;
padding: 10px;
background: lightblue;
}
main {
padding: 20px;
background: purple;
min-height: calc(100vh - 170px);
}
footer {
background: magenta;
padding: 10px;
height: 50px;
}
<html>
<body>
<nav>
Navigation
</nav>
<main>
Page content
</main>
<footer>
Footer that stays put
</footer>
</body>
</html>
As can be seen, we set the minimum height of the content to 100vh minus whatever the combined height (plus padding) happens to be of your nav and content containers.
This results in a footer that sticks, along with the ability to drop further if the content exceeds the min-height value.
The same effect can be accomplished using flexbox, which is arguably a more dynamic solution. However, it comes at the expense of an extra container element. We could apply flex to body, but that is rarely a proper solution:
The flex box solution
.container {
display: flex;
min-height: calc(100vh - 40px);
flex-direction: column;
}
nav {
height: 40px;
padding: 10px;
background: lightblue;
}
main {
padding: 20px;
background: purple;
flex: 1;
}
footer {
background: magenta;
padding: 10px;
height: 50px;
}
<body>
// Use className instead of class for react (jsx)
<div class="container">
<nav>
Navigation
</nav>
<main>
Main Content Area
</main>
<footer>
Footer that stays put
</footer>
</div>
</body>
The CSS Grid Solution with min-height
.container {
display: grid;
grid-gap: 1em 0;
grid: auto auto 1fr / 10vw 1fr 10vw;
margin: 0;
min-height: calc(100vh - 40px);
}
nav {
background-color: lightblue;
grid-column: 2;
padding: 20px;
}
main {
background-color: purple;
display: grid;
grid-column: 2;
padding: 20px;
}
footer {
background-color: magenta;
align-self: end;
grid-column: 2;
padding: 20px;
}
// Use className instead of class for react (jsx)
<div class="container">
<nav>
Navigation
</nav>
<main>
Main Content Area
</main>
<footer>
Footer that stays put
</footer>
</div>
Note: Change class to className if you're working on a react project.

Related

Css-Grid / Flexbox aside and main not growing 100%

I am creating a css-grid / flexbox template and it's all working as it should.
It has a header, aside, main and footer.
I just need the asign and main row to stretch so it takes the whole page minus the header and footer height.
I want to do this without having to use the "vh"
Here is the full current code:
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
body {
padding: 0;
margin: 0;
width: 100%;
height: 100%;
display: grid;
grid-template-columns: 30% auto;
grid-template-rows: auto 1fr auto;
grid-template-areas: "header header"
"sidebar main"
"footer footer"
}
header,
aside,
main,
footer {
padding: 16px;
text-align: center;
}
header {
background: purple;
grid-area: header;
}
aside {
background: blue;
grid-area: sidebar;
}
main {
background: green;
grid-area: main;
}
footer {
background: orange;
grid-area: footer;
}
How can I get the asign and main to auto stretch?
You can use :root{} for that and calc() with variables to calculate the height. Sorry for re-coding your attempt, but I think it was better to start from zero to show you a new approach.
Try the following snippet
* {box-sizing: border-box;padding: 0;margin: 0}
:root{
--nav-height: 80px;
--footer-height: 80px;
}
.grid-container{
display: grid;
grid-template-columns: 30% 70%;
height:calc(100vh - var(--nav-height) - var(--footer-height));
}
.grid-item{
border:1px solid black;
padding:10px;
}
.nav{
width:100%;
height:var(--nav-height);
border:1px solid black;
padding:10px;
}
footer{
width:100%;
height:var(--footer-height);
border:1px solid black;
padding:10px;
}
<body>
<div class="nav">nav content</div>
<div class="grid-container">
<div class="grid-item">body content one</div>
<div class="grid-item">body content two</div>
</div>
<footer>footer content</footer>
</body>
In order to make it the correct browser height, the view height (vh) property would be required.
You could alternatively use a fixed pixel height, or make it relative to the width for a specific aspect ratio, but neither of these would be responsive to 100% browser height.
Is there any reason you don't want to use vh?
One way to do it strictly with flex-box would be to wrap both the aside and main in a div, and set flex property of the div to 1
<div class="container">
<aside>aside</aside>
<main>main</main>
</div>
.container {
display: flex;
flex: 1;
}
but in order for that to work you would probably have to make the entire body a flex-box
body {
display: flex;
flex-direction: column;
}

CSS grid dimensions

I'd like to know if there is a way to limit the dimensions of a grid (not the element to which it's applied, the grid itself). I explain :
Let's say we've got a footer, with a dark background, spanning all the width of your page.
This footer contains 2 sub-blocks, classnames .footer__1 and .footer__2, and we want them to occupy 2/3 and 1/3 of the available width, with a 2rem gutter.
Is there a way to give the grid containing the two sub-blocks a grid-max-width (yes, i made that up) of 60rem, without changing the block width (remember, it has a background which must be full width), without using a wrapper ?
So, the occupied width (.footer__1 + gap + .footer__2) should be 60rem max, centered horizontally.
<footer>
<div class="footer__1">foo</div>
<div class="footer__2">whatever</div>
</footer>
.footer {
display: grid;
grid-template_columns: 2fr 1fr;
grid-column-gap: 2rem;
/* grid-max-width: 60rem */
}
Thanks
You have to wrap it with an additional element and limit the width to the additional element.
footer {
background-image: linear-gradient(20deg, red, pink);
}
.container {
display: grid;
grid-template-columns: 2fr 1fr;
grid-column-gap: 2rem;
/* just for demo purpose */
max-width: 300px;
margin: 0 auto;
min-height: 150px;
background: white;
}
<footer>
<div class="container">
<div class="footer__1">foo</div>
<div class="footer__2">whatever</div>
</div>
</footer>
Without another container, I think it is not possible.
However, you can mimic it by making the footer width: 60rem and set the background as a pseudo-element and expand it.
footer {
position: relative;
z-index: 1;
width: 60rem;
margin: 0 auto;
}
footer:before {
content: '';
position: absolute;
top: 0;
left: 50%;
z-index: -1;
transform: translateX(-50%);
width: 9999px;
height: 100%;
background: green;
}
<footer>
<div class="footer__1">foo</div>
<div class="footer__2">whatever</div>
</footer>
The best approach, as I think, is to add div.footer__inner that will hold the two divs - .footer__1 and .footer__2.

CSS Stick Footer to Bottom

Here is my code to stick the footer to bottom of the page:
#footer {
background-color: #0F2157;
width: 100%;
bottom: 0px;
min-height: 35px;
padding-top: 5px;
}
When I'm doing it with height it works perfectly fine, but when I'm trying to set the minimum height it leaves a little space under the footer. Any guess how to fix that?
First of all, the height of body, html and container (see element with class 'container') has to have height: 100%;
In this solution I have used flex box. It is supported by all modern browsers and IE11.
It's necessary to add the following properties to container:
display: flex;
flex-direction: column; /*the flex items are placed in column, by default it is in row*/
To move footer to bottom, just add to flex item
margin-top: auto; /* it grabs all free space between flex items and put it before this flex item */
html, body {
height: 100%;
}
.container {
height: 100%;
background-color: green;
display: flex;
flex-direction: column;
}
.header {
height: 20%;
background-color: yellow;
}
.content {
background-color: white;
}
.footer {
min-height: 20%;
background-color: blue;
margin-top: auto;
}
<div class="container">
<div class="header">Header</div>
<div class="content">It's content</div>
<div class="footer">Footer in bottom</div>
</div>
What about using Flexbox? It is supported by IE>=10.
To use that, you have to split your page at least in two separated elements: The "upper"-one (.content) with the whole content of your page and the footer.
The "upper"-one gets the value flex: 1, which is a shorthand for:
flex-grow: 1
flex-shrink: 1
flex-basis: auto
This means, that the "upper"-element could grow to the maximum, while the footer reserves only it's actually required space.
Code snippet
html {
height: 100%;
}
body {
min-height: 100%;
margin: 0;
display: flex;
flex-direction: column;
}
.content {
flex: 1;
}
<!doctype html>
<html>
<head>
</head>
<body>
<div class="content"></div>
<footer class="footer">
Hey footer!
</footer>
</body>
</html>
You used min height 35 px. I think your content's height inside of footer is more than 35px. So check the margin or padding of all footer elements.
It will be better, if you can make a jsfiddle demo.
[SOLVED]
I found this to be working for my example:
#footer {
position: absolute;
bottom: 0;
width: 100%;
}

Flexbox - can't keep divs in content area from overlapping footer

I have a web page using a column flexbox, with fixed size header and footer, and a content area which takes up the remaining space. This works fine.
The content area is a row flexbox, and I have 2 square divs side by side. I am making them square by using padding-bottom. This works fine, unless the window is >2x the content area height. Then my squares start bleeding into the footer, because padding is based on element width.
I would like the squares to never overlap the footer. I'm ok with there just being dead space to the right of the squares. I would like to stick with flexbox and avoid floats if possible. Only modern browsers need be supported.
Is this possible with only CSS? Or is this a job for JS.
Fiddle
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#box {
display: flex;
flex-flow: column;
height: 100%;
}
div {
border: 1px solid tomato;
box-sizing: border-box;
margin: 0;
padding: 2px;
}
#header {
flex: 0 0 5em;
}
#footer {
flex: 0 0 5em;
}
#content {
background: blue;
display: flex;
flex: 1 1 auto;
flex-flow: row wrap;
min-height: 30%;
}
#content > div {
background: tomato;
border-color: black;
flex: 1 0 auto;
max-height: 50%;
padding-bottom: 50%;
}
<div id="box">
<div id="header">
<p><b>header</b>
</p>
</div>
<div id="content">
<div id='am'></div>
<div id='pm'></div>
</div>
<div id="footer">
<p><b>footer</b>
</p>
</div>
</div>
TIA!
Simple soluton:
#box
{
display: flex;
flex-flow: column;
min-height: 100%; /* this*/
}
JSfiddle Demo
Note: This assumes you want the page to overflow...but I didn't see any reference to containing the page height to the viewport.

How to create div to fill all space between header and footer div

I'm working on moving from using tables for layout purposes to using divs (yes, yes the great debate). I've got 3 divs, a header, content and footer. The header and footer are 50px each. How do I get the footer div to stay at the bottom of the page, and the content div to fill the space in between? I don't want to hard code the content divs height because the screen resolution can change.
Flexbox solution
Using flex layout we can achieve this while allowing for natural height header and footer. Both the header and footer will stick to the top and bottom of the viewport respectively (much like a native mobile app) and the main content area will fill the remaining space, while any vertical overflow will be scrollable within that area.
See JS Fiddle
HTML
<body>
<header>
...
</header>
<main>
...
</main>
<footer>
...
</footer>
</body>
CSS
html, body {
margin: 0;
height: 100%;
min-height: 100%;
}
body {
display: flex;
flex-direction: column;
}
header,
footer {
flex: none;
}
main {
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
flex: auto;
}
To summarize (and this came from the CSS Sticky Footer link provided by Traingamer), this is what I used:
html, body
{
height: 100%;
}
#divHeader
{
height: 100px;
}
#divContent
{
min-height: 100%;
height: auto !important; /*Cause footer to stick to bottom in IE 6*/
height: 100%;
margin: 0 auto -100px; /*Allow for footer height*/
vertical-align:bottom;
}
#divFooter, #divPush
{
height: 100px; /*Push must be same height as Footer */
}
<div id="divContent">
<div id="divHeader">
Header
</div>
Content Text
<div id="divPush"></div>
</div>
<div id="divFooter">
Footer
</div>
To expand on Mitchel Sellers answer, give your content div height: 100% and give it a auto margin.
For a full explanation and example, see Ryan Fait's CSS Sticky Footer.
Since you know the size (height) of your header, put it inside the content div (or use margins).
Position absolute will give you problems if your content is larger (taller) than the window.
A way to do this using CSS Grid:
index.html
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="main.css" rel="stylesheet">
</head>
<body>
<main>
<header>Header</header>
<section>Content</section>
<footer>Footer</footer>
</main>
</body>
</html>
main.css
body {
margin: 0;
}
main {
height: 100%;
display: grid;
grid-template-rows: 100px auto 100px;
}
section {
height: 100%;
}
Use CSS grid instead it is supported by nearly all the browser
html{
height: 100%;
}
body{
margin: 0;
padding: 0;
height: 100%;
}
.main-body{
display: grid;
/* let content auto to occupy remaining height and pass value in fit-content with min-height for header and footer */
grid-template-rows: fit-content(8rem) auto fit-content(8rem);
grid-template-areas: "header" "main" "footer";
}
.main-header{
background-color: yellow;
grid-area: header;
}
.main-content{
grid-area: main;
}
.main-footer{
background-color: green;
grid-area: footer;
}
<body class="main-body">
<header class="main-header">
HEADER
</header>
<main class="main-content">
this is content
</main>
<footer class="main-footer">
this is footer
</footer>
</body>
HTML
<body>
<header>
</header>
<main>
...
</main>
<footer>
</footer>
</body>
CSS
html, body {
height: 100%;
margin: 0px;
padding: 0px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
header {
height: 10px;
background: red;
width: 100%;
}
footer {
height: 10px;
background: red;
width: 100%;
}
This css to body will make sure that header and footer are always on top and bottom respectively.
Put all the content in main.
going further you can make header or footer sticky as per your requirement.
Check the working example here
https://codepen.io/vishal657/pen/MWBOErq?editors=1100
if you are trying to maximize the height of your content div, in the CSS add
height: 100%;
#footer {
clear: both;
}

Resources