How to VueJS router-link active style

vue.jsVue RouterRouterlink

vue.js Problem Overview


My page currently has Navigation.vue component. I want to make the each navigation hover and active. The hover works but active doesn't.

This is how Navigation.vue file looks like :

<template>
  <div>
    <nav class="navbar navbar-expand-lg fixed-top row">
      <router-link tag="li" class="col" class-active="active" to="/" exact>TIME</router-link>
      <router-link tag="li" class="col" class-active="active" to="/CNN" exact>CNN</router-link>
      <router-link tag="li" class="col" class-active="active" to="/TechCrunch" exact>TechCrunch</router-link>
      <router-link tag="li" class="col" class-active="active" to="/BBCSport" exact>BBC Sport</router-link>
    </nav>
  </div>
</template>

And the following is the style.

<style>
nav li:hover,
nav li:active {
  background-color: indianred;
  cursor: pointer;
}
</style>

This is how hover looks like now and expected exactly same on active.

This is how hover looks like now and expected exactly same on active.

I would appreciate if you give me an advice for styling router-link active works. Thanks.

vue.js Solutions


Solution 1 - vue.js

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:

li:active {
  background-color: #35495E;
}

li.active {
  background-color: #41B883;
}

<ul>
  <li>:active (pseudo-class) - Click me!</li>
  <li class="active">.active (class)</li>
</ul>


Vue-Router

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


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.


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",
})

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>

Solution 2 - vue.js

When you are creating the router, you can specify the linkExactActiveClass as a property to set the class that will be used for the active router link.

const routes = [
  { path: '/foo', component: Foo },
  { path: '/bar', component: Bar }
]

const router = new VueRouter({
  routes,
  linkActiveClass: "active", // active class for non-exact links.
  linkExactActiveClass: "active" // active class for *exact* links.
})

This is documented here.

Solution 3 - vue.js

https://router.vuejs.org/en/api/router-link.html add attribute active-class="active" eg:

<ul class="nav navbar-nav">
    <router-link tag="li" active-class="active" to="/" exact><a>Home</a></router-link>
    <router-link tag="li" active-class="active" to="/about"><a>About</a></router-link>
    <router-link tag="li" active-class="active" to="/permission-list"><a>Permisison</a></router-link>
</ul>

Solution 4 - vue.js

Just add to @Bert's solution to make it more clear:

    const routes = [
  { path: '/foo', component: Foo },
  { path: '/bar', component: Bar }
]

const router = new VueRouter({
  routes,
  linkExactActiveClass: "active" // active class for *exact* links.
})

As one can see, this line should be removed:

linkActiveClass: "active", // active class for non-exact links.

this way, ONLY the current link is hi-lighted. This should apply to most of the cases.

David

Solution 5 - vue.js

As mentioned above by @Ricky vue-router automatically applies two active classes, .router-link-active and .router-link-exact-active, to the <router-link> component.

So, to change active link css use:

.router-link-exact-active {
  //your desired design when link is clicked
  font-weight: 700;
}

Solution 6 - vue.js

Let's make things simple, you don't need to read the document about a "custom tag" (as a 16 years web developer, I have enough this kind of tags, such as in struts, webwork, jsp, rails and now it's vuejs)

just press F12, and you will see the source code like:

<div>
  <a href="#/topologies" class="luelue">page1</a> 
  <a href="#/" aria-current="page" class="router-link-exact-active router-link-active">page2</a> 
  <a href="#/databases" class="">page3</a>
</div>

so just add styles for the .router-link-active or .router-link-exact-active

If you want more details, check the router-link api: https://router.vuejs.org/guide/#router-link

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiondoobeanView Question on Stackoverflow
Solution 1 - vue.jsRickyView Answer on Stackoverflow
Solution 2 - vue.jsBertView Answer on Stackoverflow
Solution 3 - vue.jsVi Quang HòaView Answer on Stackoverflow
Solution 4 - vue.jsus_davidView Answer on Stackoverflow
Solution 5 - vue.jsDilip GautamView Answer on Stackoverflow
Solution 6 - vue.jsSiweiView Answer on Stackoverflow