brazilla_ray
brazilla_ray

Reputation: 53

how to conditionally style links in Nuxt/Vue

I'm building a Nuxt app and am having trouble with conditional styling. What I'm trying to do is apply a different background color to the active link depending on what page it is. I know I can use .nuxt-link-exact-active to style the active link, but I'm stuck on how to make that different on each page.

I have the links in a component that gets rendered on each page. I've tried using .nuxt-link-exact-active at the page level, but it doesn't get picked up.

Here's what I've got so far, which does change the styling depending on the page, but it does it for all the links, and I only want it on the active link. Please let me know if I can clarify anything. Thanks!

<template>
  <nav class="flex-container flex-column mt-1">
    <NuxtLink to="/about" class="link" :class="classObject">about</NuxtLink>
    <div class="mt-1 flex-container">
      <NuxtLink to="/projects" class="link" :class="classObject"
        >projects</NuxtLink
      >
    </div>
    <div class="mt-1 flex-container">
      <NuxtLink to="/contact" class="link" :class="classObject"
        >contact</NuxtLink
      >
    </div>
  </nav>
</template>

<script>
export default {
  // apply current route name as a class to the matching div
  computed: {
    classObject() {
      return {
        about: this.$route.name === 'about',
        projects: this.$route.name === 'projects',
        contact: this.$route.name === 'contact',
      }
    },
  },
}
</script>

<style lang="scss" scoped>
.about {
  background-color: $near-white;
}

.projects {
  background-color: $blue;
}

.contact {
  background-color: $yellow;
}
</style>

illustration of what I'm trying to do

Upvotes: 1

Views: 6427

Answers (3)

Timo
Timo

Reputation: 51

I think the easiest way to check if the path is active or not is $nuxt.$route.path.

<template>
    <ul>
        <li>
          <nuxt-link :to="links[0].path" :class="{'bg-black text-white': links[0].path == path }">{{ links[0].name }}</nuxt-link>
          <nuxt-link :to="links[1].path" :class="{secondStyle: links[1].path == path }">{{ links[1].name }}</nuxt-link>
        </li>
    </ul>
</template>
    
<script>
    export default {
        name: "Header",
        data() {
          return {
            path: null,
            links: [
              {path: "/link1", name: "Link 1"},
              {path: "/link2", name: "Link 2"}
            ],
          };
        },
        mounted() {
          this.path = $nuxt.$route.path;
        },
    };
</script>

Upvotes: 0

brazilla_ray
brazilla_ray

Reputation: 53

I came up with a solution— not sure if it's the best way, but it works. Each link is now preceded by a div that only gets rendered on the corresponding page, otherwise a link is rendered.

<template>
  <nav class="flex-container flex-column mt-1">
    <div v-if="currentPageName === 'about'" class="box about">
      <h2>about</h2>
    </div>
    <div v-else>
      <NuxtLink to="/about" class="link">about</NuxtLink>
    </div>
    <div v-if="currentPageName === 'projects'" class="box projects">
      <h2>projects</h2>
    </div>
    <div v-else>
      <NuxtLink to="/projects" class="link">projects</NuxtLink>
    </div>
    <div v-if="currentPageName === 'contact'" class="box contact">
      <h2>contact</h2>
    </div>
    <div v-else>
      <NuxtLink to="/contact" class="link">contact</NuxtLink>
    </div>
  </nav>
</template>

<script>
export default {
  computed: {
    currentPageName() {
      return this.$route.name
    },
  },
}
</script>

<style lang="scss" scoped>
.box {
  width: 150px;
  height: 150px;
}

.about {
  background-color: $near-white;
}

.projects {
  background-color: $blue;
}

.contact {
  background-color: $yellow;
}
</style>

Upvotes: 0

Nick Dawes
Nick Dawes

Reputation: 2244

Instead of changing .nuxt-link-exact-active at the page level, change it in the layout.

So for example, in layouts/default.vue:

<style>
.nuxt-link-exact-active {
  background: red;
}
</style>

Upvotes: 1

Related Questions