I've often wanted to make a website/webapp that satisfies some or all of the following criteria:
- has body contents that will overflow the screen size if there's lots of content
- has a header that stays locked in place at the top of the screen.
- has a footer that is always either at the bottom of the screen, or the bottom of the page.
The following is my general purpose solution for achieving this...
virtues:
- uses the body to scroll, no need for nested
<div>
s withoverflow: auto
- compartmentalizes the
header
,footer
andmain
asap -
creates a new stacking context for header and footer
- optimises animations that only affect the header or the footer
- means you don't have to mess around with
z-index
to keep them above<main/>
Pure HTML
<html>
<head>
<title>Scrollable site - fixed navigation</title>
</head>
<body>
<header>This is the header</header>
<main>This is the content</main>
<footer>This is the footer</footer>
</body>
</html>
html,
body {
height: 100%;
margin: 0;
min-height: 100%;
}
body {
overflow-y: scroll;
--header-height: 30px;
--footer-height: 30px;
}
header {
background-color: red;
left: 0;
max-height: var(--header-height);
min-height: var(--header-height);
position: fixed;
right: 0;
top: 0;
}
main {
padding-top: var(--header-height);
padding-bottom: var(--footer-height);
}
footer {
background-color: blue;
bottom: 0;
left: 0;
max-height: var(--footer-height);
min-height: var(--footer-height);
position: fixed;
right: 0;
}
With React
You can use react to create a solution identical to the above, but in some situations, the following idea might be more suitable
import React from "react";
import styled from "@emotion/styled";
const sharedStyled = ({ theme }) => ({
minHeight: theme.headerHeight,
backgroundColor: theme.headerColor,
});
// a component to take up space above the Main, that exists as part of the flow
const HeaderSpacer = styled.div(sharedStyled, { width: "100%" });
// a component with the same dimensions that exists above the flow.
const HeaderFixed = styled.div(sharedStyled, {
position: "fixed",
top: 0,
left: 0,
right: 0,
});
const Header = () => (
<React.Fragment>
<HeaderSpacer />
<HeaderFixed />
</React.Fragment>
);
const App = () => (
<React.Fragment>
<Header />
<main />
</React.Fragment>
);
//follow the same logic to make a Footer