Published on

The sticky footer and Next.js 13

Last Modified on
Last modified on
Authors
The sticky footer and Next.js 13
Photo by skitterphoto on Pexels

I have talked about the sticky footer in various scenarios, and now I am going to talk about it in Next.js 13.

I just updated an events app I am working on to Next.js 13. And one really cool thing about that version is that we no longer have to use the class based Document component there. We can use a function component!

My business site (this one), is not yet on Next.js 13. I actually use a starter blog for it, but am starting to think that maybe I want to re-create my site from scratch. Not using Tailwind.css. But creating my own thing. It’s time I do that. But it won’t start until towards the end of the year. Here, I am using 12.1.4. Not too shabby, but I want to use 13! And not have to deal with the hassle of a framework-like structure which has so many things that need to be updated in conjunction with each other, and could also cause conflicts. It won’t be that crazy, but it will take a bit of time and patience to refactor.

But let’s get back to the topic at hand! So previously, pre-Next.js 13, we defined our _document.js file in something like the following way:

import Document, { Html, Head, Main, NextScript } from 'next/document'
import { ServerStyleSheet } from 'styled-components'

class MyDocument extends Document {
	render() {
		return (
			<Html lang="en" className="scroll-smooth">
				<Head>
					<link
						rel="apple-touch-icon"
						sizes="76x76"
						href="/static/favicons/apple-touch-icon.png"
					/>
					<link
						rel="icon"
						type="image/png"
						sizes="32x32"
						href="/static/favicons/favicon-32x32.png"
					/>
					<link
						rel="icon"
						type="image/png"
						sizes="16x16"
						href="/static/favicons/favicon-16x16.png"
					/>
					<link
						rel="manifest"
						href="/static/favicons/site.webmanifest"
					/>
					<link
						rel="mask-icon"
						href="/static/favicons/safari-pinned-tab.svg"
						color="#5bbad5"
					/>
					<meta name="msapplication-TileColor" content="#000000" />
					<meta name="theme-color" content="#000000" />
					<link
						rel="alternate"
						type="application/rss+xml"
						href="/feed.xml"
					/>
				</Head>
				<body className="bg-white text-black antialiased dark:bg-gray-900 dark:text-white">
					<Main />
					<NextScript />
				</body>
			</Html>
		)
	}
	static async getInitialProps(ctx) {
		const sheet = new ServerStyleSheet()
		const originalRenderPage = ctx.renderPage

		try {
			ctx.renderPage = () =>
				originalRenderPage({
					enhanceApp: (App) => (props) =>
						sheet.collectStyles(<App {...props} />),
				})

			const initialProps = await Document.getInitialProps(ctx)
			return {
				...initialProps,
				styles: (
					<>
						{initialProps.styles}
						{sheet.getStyleElement()}
					</>
				),
			}
		} finally {
			sheet.seal()
		}
	}
}

export default MyDocument

Now, we create it in the following way (different app):

import { Html, Head, Main, NextScript } from 'next/document'

function Document() {
	return (
		<Html lang="en">
			<Head />
			<body>
				<div className="site-content-wrapper">
					<Main />
				</div>
				<footer class="site-credits">
					<p>© 2022 InterEvents</p>
				</footer>
				<NextScript />
			</body>
		</Html>
	)
}

export default Document

I like this approach, because I prefer functional components, and it also keeps things even visually consistent. And because we can do this kind of thing in _document.js (we could add other HTML elements before), it makes it easy to add sticky footer styling using Flexbox here as well. And the following is all I needed to add to my globals.css file inside my styles folder to create a sticky footer:

body {
	margin: 0;
	font-family: 'Open Sans', 'Lato', sans-serif;
	color: #414141;
	background-color: #e4f1f1;
	/* sticky footer styling related */
	display: flex;
	flex-direction: column;
	min-height: 100vh;
}

/* sticky footer styling related */
.site-content-wrapper {
	flex: 1;
	width: 100%;
}

And of course I made sure to add the following reset to the top of the file:

* {
	margin: 0;
	padding: 0;
	box-sizing: border-box;
}

Only box-sizing: border-box; was there by default. If I had not added the margin and padding properties, the footer would not completely stick to the bottom as I wanted, due to the extra margin and padding added by the user agent stylesheet.

Happy sticky footering with Next.js 13!