How to VueJS router-link active style
Asked Answered
B

7

147

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.

Bove answered 6/9, 2017 at 19:45 Comment(4)
router.vuejs.org/en/api/options.html#linkexactactiveclassAbsentee
Hi @Bert, thanks for your comment. I've tried <router-link-exact-active> instead of <router-link>, but doesn't work yet.Bove
That's not where you specify it. You specify linkExactActiveClass as a property of your router (where you add the routes).Absentee
TY @KateYeeumLee for this question. Was just getting ready to build something like this and come to realize that it should be its own component - not part of TheHeader.vue :)Crackling
O
320

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.


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>
Orgeat answered 6/9, 2017 at 23:3 Comment(4)
Sorry but the names are not that self-explanatory to me :) What about normal links that aren't active or "exact"? In my case, my normal links get styled in an unwanted way by Vue. Changing the active or exact styles has no effect.Differentia
This is answer deserve an award for taking time to explainMagnetograph
I want to set only one breadcrumb link to active, for the current route, and just this worked: <router-link :to="{ name: 'about' }" class="active">About</router-linkSince
any idea why scroll-click (middle click) stops working as soon as you access v-slot on router-link by v-slot="{ isActive }"? The DOM element is being changed to span from anchor. Why is it so? Setting tag="a" doesn't change anythingLindalindahl
S
40

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>
Soberminded answered 20/11, 2017 at 2:46 Comment(4)
but why also generate class nuxt-link-exact-active, please check my question in here #54030294Mag
good reference. the the exact attribute is relevant to avoid false triggeringAnissaanita
simplest answerCienfuegos
The exact prop has been removed... see: router.vuejs.org/guide/migration/…Dinka
A
35

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.

Absentee answered 6/9, 2017 at 20:6 Comment(2)
This works well, but in my app, it's always considering / as active (since URLs like /about contain it).Vaishnava
@Vaishnava if I understand correctly, just remove the linkActiveClass codepen.io/Kradek/pen/zWQKYpAbsentee
T
7

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;
}
Tomato answered 6/3, 2020 at 18:52 Comment(1)
how to make this work if your design needs a different colour per menu item when its active ?Porscheporsena
E
6

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

Editorialize answered 30/1, 2020 at 22:43 Comment(0)
G
4

For anyone using Tailwind, you can work with the active class and exact active classes in this way:

<router-link
    :active-class="'bg-gray-100 bg-opacity-50 hover:bg-gray-200'"
    :exact-active-class="'bg-red-100 bg-opacity-50 hover:bg-red-200'"
    class="bg-gray"
>
    ...
</router-link>

Using the above, the default class is bg-gray. When the link is clicked, it will have the exact-active-class. If a child route is clicked, the element will take on the active class.

Gentlemanfarmer answered 1/7, 2023 at 15:37 Comment(0)
H
3

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

Herrick answered 13/1, 2021 at 1:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.