[vue.js] How to VueJS router-link active style

The :active pseudo-class is not the same as adding a class to style the element.

The :active CSS pseudo-class represents an element (such as a button) that is being activated by the user. When using a mouse, "activation" typically starts when the mouse button is pressed down and ends when it is released.

What we are looking for is a class, such as .active, which we can use to style the navigation item.

For a clearer example of the difference between :active and .active see the following snippet:

_x000D_
_x000D_
li:active {_x000D_
  background-color: #35495E;_x000D_
}_x000D_
_x000D_
li.active {_x000D_
  background-color: #41B883;_x000D_
}
_x000D_
<ul>_x000D_
  <li>:active (pseudo-class) - Click me!</li>_x000D_
  <li class="active">.active (class)</li>_x000D_
</ul>
_x000D_
_x000D_
_x000D_


Vue-Router

vue-router automatically applies two active classes, .router-link-active and .router-link-exact-active, to the <router-link> component.


router-link-active

This class is applied automatically to the <router-link> component when its target route is matched.

The way this works is by using an inclusive match behavior. For example, <router-link to="/foo"> will get this class applied as long as the current path starts with /foo/ or is /foo.

So, if we had <router-link to="/foo"> and <router-link to="/foo/bar">, both components would get the router-link-active class when the path is /foo/bar.


router-link-exact-active

This class is applied automatically to the <router-link> component when its target route is an exact match. Take into consideration that both classes, router-link-active and router-link-exact-active, will be applied to the component in this case.

Using the same example, if we had <router-link to="/foo"> and <router-link to="/foo/bar">, the router-link-exact-activeclass would only be applied to <router-link to="/foo/bar"> when the path is /foo/bar.


The exact prop

Lets say we have <router-link to="/">, what will happen is that this component will be active for every route. This may not be something that we want, so we can use the exact prop like so: <router-link to="/" exact>. Now the component will only get the active class applied when it is an exact match at /.


CSS

We can use these classes to style our element, like so:

 nav li:hover,
 nav li.router-link-active,
 nav li.router-link-exact-active {
   background-color: indianred;
   cursor: pointer;
 }

The <router-link> tag was changed using the tag prop, <router-link tag="li" />.


Change default classes globally

If we wish to change the default classes provided by vue-router globally, we can do so by passing some options to the vue-router instance like so:

const router = new VueRouter({
  routes,
  linkActiveClass: "active",
  linkExactActiveClass: "exact-active",
})

Change default classes per component instance (<router-link>)

If instead we want to change the default classes per <router-link> and not globally, we can do so by using the active-class and exact-active-class attributes like so:

<router-link to="/foo" active-class="active">foo</router-link>

<router-link to="/bar" exact-active-class="exact-active">bar</router-link>

v-slot API

Vue Router 3.1.0+ offers low level customization through a scoped slot. This comes handy when we wish to style the wrapper element, like a list element <li>, but still keep the navigation logic in the anchor element <a>.

<router-link
  to="/foo"
  v-slot="{ href, route, navigate, isActive, isExactActive }"
>
  <li
    :class="[isActive && 'router-link-active', isExactActive && 'router-link-exact-active']"
  >
    <a :href="href" @click="navigate">{{ route.fullPath }}</a>
  </li>
</router-link>