Highlighting the current header link in Astro
Within this post, I aim to guide you through the steps to effectively highlight the navigation link associated with the current page in Astro. By the end of this article, you’ll have a clear understanding of how to enhance user navigation by ensuring the active page’s link stands out prominently.
Various methods exist, and I will delve into three of them. It’s essential to note that the code examples provided are crafted specifically for Astro Components, with a file extension of .astro
.
1. The JavaScript Way
The following code shows you, how to incorporate plain JavaScript within a script tag. This instructs Astro to deliver this code block directly to the browser, allowing it to function in a conventional manner.
// src/components/Header.astro
<nav>
<a class="active" href="/">Home</a>
<a href="/posts">Blog</a>
<a href="/works">Works</a>
<a href="/about">About</a>
</nav>
<script>
const navAnchors = document.querySelectorAll('nav a')
navAnchors.forEach((anchor) => {
// remove active class from all anchors
anchor.classList.remove('active')
// remove the first `/` in pathname using slice method
const currentPath = window.location.pathname.slice('1')
// we split the href by `/` and get the last item in the array
const hrefArray = link.href.split('/')
const thisPath = hrefArray[hrefArray.length - 1]
// add active class if the currentPath is the same as thisPath
if (currentPath === thisPath) {
anchor.classList.add('active')
}
})
</script>
2. The Astro Way
We take advantage of Astro’s Runtime API and get the pathname in Astro components’ component script
// src/components/Header.astro
---
const pathname = new URL(Astro.request.url).pathname;
const currentPath = pathname.slice(1); // remove the first "/"
---
<nav>
<a class={currentPath === "" ? "active" : ""} href="/">Home</a>
<a class={currentPath === "portfolio" ? "active" : ""} href="/posts">Blog</a>
<a class={currentPath === "works" ? "active" : ""} href="/works">Works</a>
<a class={currentPath === "about" ? "active" : ""} href="/about">About</a>
</nav>
3. Combining components
// src/components/HeaderLink.astro
---
import type { HTMLAttributes } from 'astro/types'
type Props = HTMLAttributes<'a'>
const { href, class: className, ...props } = Astro.props
const { pathname } = Astro.url
const isActive = href === pathname || href === pathname.replace(/\/$/, '') //
grep replace the first '/'
---
<a href={href} class:list={[className, { active: isActive }]} {...props}>
<slot /> <!-- This is where the content of the component is rendered -->
</a>
<style>
a {
display: inline-block;
text-decoration: none;
}
a.active {
font-weight: bolder;
text-decoration: underline;
}
</style>
then
// src/components/HeaderLink.astro --- import HeaderLink from
'./HeaderLink.astro' // the above component ---
<div class="internal-links">
<HeaderLink href="/">Home</HeaderLink>
<HeaderLink href="/posts">Blog</HeaderLink>
<HeaderLink href="/works">Works</HeaderLink>
<HeaderLink href="/about">About</HeaderLink>
</div>