Chris.luChris.lu header image, displaying an 80s style landscape and sunset

Styling the navigation and using next/font

Now that our Navigation is working, we will add a few touches of color and use next/font (which is built in Next.js 15, so NO additional package is needed) to add a custom web font to our project

next/font to use an open source font

When using next/font, you can use any font available on google fonts or use your own local font(s), the best part about using next/font is that it will optimize the loading of the font and make sure that there are zero layout shifts, also when using next/font we are self-hosting the font(s), which means we will NOT need to make an external network request to fetch the font, which will decrease loading times but also increase privacy as NO request is made to google servers

Because we are using the font for our navigation, let's start by editing our layout.tsx file (that is in the app folder) and import the font from there:

/app/layout.tsx
import './global.css'
import { Metadata } from 'next'
import HeaderNavigation from '@/components/header/Navigation'
import { Kablammo } from 'next/font/google'
 
export const metadata: Metadata = {
    title: 'Next.js',
    description: 'Generated by Next.js',
}
 
const kablammo = Kablammo({
    subsets: ['latin'],
    variable: '--font-kablammo',
    weight: ['400'],
    display: 'swap',
})
 
export default function RootLayout({
    children,
}: {
    children: React.ReactNode
}) {
    return (
        <html lang="en" className={kablammo.variable}>
            <body>
                <header>
                    <HeaderNavigation />
                </header>
                <main>{children}</main>
                <footer>
                    <p>My Footer</p>
                </footer>
            </body>
        </html>
    )
}

Line 4: we import the font called Kablammo from next/font, you can find Kablammo on google fonts

Lines 11 to 16: we set some options for the font:

Tip

Because the fonts are fully typed, you can just type an option name and will get a list of values that you can choose from

Line 24: we add the font style to our HTML element

Next, we are going to add a stylesheet for our Navigation component and use the new font for the navigation items

Create a new navigation.module.css file in the /components/header folder and insert the following content:

/components/header/navigation.module.css
.navigation {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 60px;
    background-color: hsl(var(--background-dark-value) / 0.9);
    border-bottom: 1px solid hsl(var(--text-dark-value) / 0.5);
    position: fixed;
    top: 0;
}
 
.link {
    padding: 0 var(--spacing);
    font-size: xx-large;
    text-decoration: none;
    font-family: var(--font-kablammo);
}
 
.active {
    font-weight: bold;
}

Line 17: we use the --font-kablammo variable we defined when setting the options for the font in the layout.tsx file

The final step is to edit our Navigation.tsx file in the /components/header folder and start using the styles we just created, like so:

/components/header/Navigation.tsx
'use client'
 
import { usePathname } from 'next/navigation'
import type { Route } from 'next'
import Link from 'next/link'
import styles from './navigation.module.css'
 
interface IMainMenuItem {
    pathname: string
    text: string
}
 
const HeaderNavigation: React.FC = () => {
 
    const currentPagePathname = usePathname()
 
    const mainMenuItems: IMainMenuItem[] = [
        { pathname: '/', text: 'Home' },
        { pathname: '/blog', text: 'Blog' },
    ]
 
    const isActiveCheck = (menuItemPathname: string) => {
 
        let isActiveClass = ''
 
        if (menuItemPathname.length > 1) {
            if (currentPagePathname.startsWith(menuItemPathname)) {
                isActiveClass = styles.active
            }
        } else {
            // exception for homepage path which is "/"
            // in that case the page path needs to be equal
            if (currentPagePathname === menuItemPathname) {
                isActiveClass = styles.active
            }
        }
 
        return isActiveClass
    }
 
    return (
        <>
            <nav id="navigation" className={styles.navigation}>
                {mainMenuItems.map((menuItem) => {
                    return (
                        <Link
                            href={menuItem.pathname as Route}
                            key={menuItem.pathname}
                            className={`${isActiveCheck(menuItem.pathname)} ${styles.link}`}
                            title={menuItem.text}
                        >
                            {menuItem.text}
                        </Link>
                    )
                })}
            </nav>
        </>
    )
}
 
export default HeaderNavigation

Line 6: we import the new CSS Module containing the Navigation component stylesheet

Lines 28 / 34 / 43 and 49: we use the 3 CSS rules, the .active rule will be used to make the Navigation entry that matches the current pathname bold, and the .navigation rule uses position fixed so that the navigation bar will always stay on top and finally the .link rule adds the new Kablammo font all the links of the navigation

There is one more change we need to do, because we made the navigation to have a fixed position, it is now as if it was not part of the document anymore, meaning it will NOT take up space anymore, as it will be floating above the content. This will cause the page content to move up and eventually be under the navigation

This is why we will edit our global.css file and edit the body class:

/app/global.css
body {
    /* remove any margin that browsers add to body */
    margin: 0;
    /* compensate for the fixed navigation height */
    padding-top: 60px;
}

Lines 36 to 37: we add a padding-top property and set its value to the same size as the height of the navigation, this will ensure that when the page has loaded, there is no content displayed under the navigation because the content of the body will have been pushed down a bit (later when scrolling the content will move under the navigation)

Now launch the dev server if it isn't already running (using the npm run dev command), then open your browser and go to the project's homepage at http://localhost:3000/ to see the styled navigation which is using our custom font instead of the default browser font, for yourself

Congratulations 🎉 you now have a much better-looking navigation component and learned how to use next/font

If you liked this post, please consider buying me a coffee ☕ or sponsor ❤️ me on GitHub, as it will help me create more content and keep it free for everyone