3

I understand how it's done in Bootstrap4 but the same method isn't working in Bootstrap-vue

This is the code in my Homepage.vue file:

<template>
  <div class="forVue">
    <div>
        <b-navbar toggleable="sm" type="dark" variant="dark">

            <b-navbar-toggle target="nav-collapse"></b-navbar-toggle>

            <b-collapse id="nav-collapse" is-nav>

                <b-navbar-nav class="mx-auto">
                    <b-nav-item href="/home">Home</b-nav-item>
                    <b-nav-item href="/home">Services</b-nav-item>
                    <b-nav-item href="/home">Contact</b-nav-item>
                    <b-nav-item href="/about">About Us</b-nav-item>
                </b-navbar-nav>

            </b-collapse>

        </b-navbar>
    </div>
  </div>
</template>

The following is my CSS inside style tags in the same file

<style>
    .nav-item {
        color: red !important;
    }
</style>

This isn't working and the color remains the default. I also cannot understand how to specify the navbar to change the color of the whole navbar without using the !important tag. It works with the following code:

.navbar {
        background-color: red !important;
    }

How can I get that to work without the !important tag?

Shahmeer
  • 51
  • 1
  • 5

2 Answers2

2

To get rid of the !important you simply have to write a more specific selector than the one currently applying.

.nav-link colors seem to have a specificity of 3 × class in BoostrapVue, which means 3 × class + 1 × el will sufice:

.nav-item.nav-item.nav-item a {
  color: red;
}

Note: if you find having to repeat a class selector multiple times cumbersome and generating too much boilerplate code in your CSS, one trick I often use is artificially inflating the specificity of my selectors with 1 × id:

#app .nav-item a { color: red }

Another note on this is that you don't even need to have an ancestor id, because this would also work:

body:not(#_) .nav-item a {
  color: red;
}

... assuming your <body> element does not have id="_".

In scss it gets even simpler, as all you need to do is wrap your current code into body:not(#_) { ...current code ... }.

Over time, I've been getting some comments on this technique as being just as bad as using !important, because it also conflates the specificity and you end up in the same game of making it increasingly more difficult to write even stronger selectors when current ones need overwriting.

My response to that is that the rules of the game are actually set by how CSS works. I haven't made the rules, I'm only playing the game. But the most important part is that, by not using !important, I allow JavaScript driven styling to take precedence, which is the most important reason why usage of !important is bad practice.


A more general answer to this type of questions would be: inspect your element, figure out which rule is applying the current value and write a slightly more specific one (or an equally specific one if you place it in the <style> tag of your component, because that's applied last).


Also note your code has to be in a <style> tag that is not scoped. If it's scoped, prefixing with /deep/, ::v-deep or >>> should work but a recent bug in Vue which has not yet been resolved breaks piercing selectors in <style> tags with lang="scss", if your sass-loader is above 7.* (current latest: 8.0.2). Effectively, it means the following will work:

<style scoped lang="css">
  /deep/ .nav-item.nav-item.nav-item a {
     color: red;
  }
</style>

...(where lang="css" is optional, because it's default), while

<style scoped lang="scss">
   /deep/ .nav-item.nav-item.nav-item a {
     color: red;
  }
</style>

... will not work.

However, this is a (different) bug and it will probably get fixed soon, at which point I'll delete this part of my answer.

tao
  • 82,996
  • 16
  • 114
  • 150
  • 1
    Yes I get it! Could you let me know where you checked the output from? Could really help me in the future. Thanks!! – Shahmeer Apr 04 '20 at 16:33
  • 1
    @Shahmeer Add a test item to your component and inspect the resulting DOM. Since I didn't have a BV project, I went to `https://codesandbox.io/`, selected a Vue template, added BootstrapVue to deps and in `main.js` I've set Vue to use BV. In `HelloWorld.vue` I placed `test`. Inspected and copy/pasted resulting DOM. :) – tao Apr 04 '20 at 16:36
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/210944/discussion-between-tao-and-shahmeer). – tao Apr 04 '20 at 16:42
  • 1
    If you're asking how to inspect DOM, right-click any element in the page and select "Inspect Element". In devtools> elements you can also right-click and Edit as HTML. Arguably the best browser for development is Google Chrome, for multiple reasons (most compelling being: ***a)*** has highest market-share - so you're using what most of your users use; ***b)*** has the most complete and advanced set of inspection and audit dev tools), but that's a completely different discussion. :) – tao Apr 04 '20 at 16:47
  • 1
    You should be just able to target `.nav .nav-item a.nav-link`. It is the `a.nav-link` that you want to `color` property on. – Troy Morehouse Apr 05 '20 at 00:14