Dynamic partiallyActive Link in Gatsby
Gatsby offers you to use activeClassName
where you can adjust the
style of your link to indicate that a user is "under" that module or
section of your page. In other words, it helps people to understand
where they are.
<Linkto="/about-me"className={styles.menuLink}activeClassName={styles.menuLinkActive}>About me</Link>
Styles defined for styles.menuLinkActive
in the example above are then applied and everything is cool.
Say, the link is red when a user accesses the/about-me
page.
But what if you have a scenario like mine, where the "Blog" link should be active when people access /posts/:title
and
blog is my homepage as well (path /
)?
Well, the first thought is about partiallyActive
attribute and using it like that:
<Linkto="/"className={styles.menuLink}activeClassName={styles.menuLinkActive}partiallyActive={true}>Blog</Link>
But in that case, it will mean that the "Blog" link is active all the time. /
matches every other URL.
Fortunately, there is a way to make it more dynamic. Just use a function and fire it immediately.
Gatsby's <Link>
doesn't support passing a function so we still need to pass a boolean
. Hence, the
immediately called function.
<Linkto="/"className={styles.menuLink}activeClassName={styles.menuLinkActive}partiallyActive={(() => {if (typeof window !== 'undefined') {const pathName = window.location.pathname;return pathName === '/' || pathName.includes('/posts/');}})()}>Blog</Link>
What happens here? We read pathname
from the current location and return true
when we deal with
homepage (/
) or the pathname includes /posts
.
Please notice the if
statement where we check if window
object is there. That's needed for building process in Gatsby that happens in non-browser environment.
The page is server-rendered so it doesn't have a context of browser when building.
But that's ok. Once, in the browser we will get the context and improve the experience.
It works on my blog, so it should work in your case as well.
If you'd like to see more content like this, please follow me on Twitter: tomekdev_. I usually write about interfaces in the real life. So where the design meets implementation.