Search code examples
javascripthtmlcssvue.jsbootstrap-4

How to change bars icon in the navbar into cross (xmark) in responsive view using Font Awesome in Vue?


I'm trying to change 'bars' icon in the navbar into 'xmark' icon when clicked. But I don't want to use tripple or tripple while doing this. I just want to change 2 icons (bars and xmark) with each other when menu is opened or closed in responsive view. In order to fix this issue, I can use CSS, BootStrap or JavaScript. As I mentioned, I also use Vue.js framework. (Also, I took some pieces of my code from my previous little project.) Navbar in responsive view

Here is the whole code (including HTML, CSS and JavaScript):

<template>
    <nav class="navbar navbar-expand-lg navbar-light sticky-top set-nav">
        <div class="container">
            
            <nuxt-link to="/" class="brand">
                <img class="img-fluid desktop logo" height="auto" width="auto" src="~/assets/images/logo.png" alt="Logo"/>
                <img class="img-fluid mobile" height="120" width="120" src="~/assets/images/logo.png" alt=""/>
            </nuxt-link>

            <button
                class="navbar-toggler d-flex d-lg-none flex-column justify-content-around"
                type="button"
                data-bs-toggle="collapse"
                data-bs-target="#navbarSupportedContent"
                aria-controls="navbarSupportedContent"
                aria-expanded="false"
                aria-label="Toggle navigation">
                <i><fa :icon="['fas', 'bars']" class="icon toggle alt fa-3x burger-bars" /></i>
            </button>

            <div class="collapse navbar-collapse" id="navbarSupportedContent">
                <ul class="nav ml-auto">
                    <li class="nav-item active">
                        <nuxt-link class="nav-link" :to="{ path: '/', hash: '' }" exact>Home</nuxt-link>
                    </li>
                    <li class="nav-item">
                        <nuxt-link class="nav-link" :to="{ path: '/', hash: '' }" exact>Hire A Bike</nuxt-link>
                    </li>
                    <li class="nav-item">
                        <nuxt-link class="nav-link" :to="{ path: '/', hash: '' }" exact>About</nuxt-link>
                    </li>
                    <li class="nav-item">
                        <nuxt-link class="nav-link" :to="{ path: '/', hash: '' }" exact>Contact</nuxt-link>
                    </li>
                </ul>
            </div>
            </div> 
            <div class="header">
                <div class="container">
                    <ul class="header-links">
                        <li class="header-link terms">
                            <fa :icon="['fas', 'hand-point-up']" class="terms-icon fa-2x" style="color:orange" />
                            <nuxt-link class="header-nuxt terms-link" :to="{ path: '/', hash: '' }" exact>Terms & Conditions</nuxt-link>
                        </li>
                        <li class="header-link phone-number">
                            <fa :icon="['fas', 'phone']" class="phone-icon fa-2x" style="color:orange" />
                            <nuxt-link class="header-nuxt phone-link" :to="{ path: '/', hash: '' }" exact>(+90) 533 505 50 50</nuxt-link>
                        </li>
                    </ul>
                </div>
                </div>
           
    </nav>
</template>

<script>

export default {
  data: {},

  name: "Navbar",
  data: () => ({
    windowSize: "mobile",
  }),
  beforeMount() {
    window.addEventListener("resize", this.onResize.bind(this));
  },
  methods: {
    onResize() {
      if (window.innerWidth >= 320) this.windowSize = "mobile";
    },
  },
};
</script>

<style>
    .set-nav{
        height: 15rem;
        background-color: var(--color-dark-blue);
        margin-bottom:10rem;
    }
    .container{
        width: 80%;
    }
    .logo{
        height: 25rem;
    }
    .nav-link{
         font-size: 2.5rem;
         font-weight: bold;
         margin: 2rem;
         list-style-type: none;
         color: orange !important;
    }
    .nav-link:hover{
        color: white !important;
        transition: 0.3s ease-in-out;
    }
    .header{
        position: absolute;
        top: 100%;
        left: 0;
        right: 0;
        background-color: #3e80c3;
        width: 100%;
    }
    .header-links{
        list-style-type: none;
        margin-left: auto;
        margin-top: 1rem;
    }
    .header-link{
        display: inline-block;
    }
    .header-nuxt{
        font-size: 2.5rem;
        color: orange !important;
        margin: 2rem;
        /*display: flex;
        justify-content: center;
        align-items: center;*/
    }
    .terms:hover .terms-icon, .terms:hover .terms-link,
    .phone-number:hover .phone-icon, .phone-number:hover .phone-link{
        color: white !important;
        text-decoration: none;
        transition: 0.3s ease-in-out;
    }
    
    @media (max-width: 992px) and (min-width: 320px) {
  img.desktop {
    display: none;
  }
  #navbarSupportedContent .nav {
    width: 100%;
  }
  .nav {
    align-items: left;
    flex-direction: column;
    position: relative;
    background-color: var(--color-dark-blue);
    
  }
  .nav-link {
    height: 6rem;
  }
  .nav-item {
    height: auto;
    text-align: center;
  }
  /* .nav-part {
    align-items: left;
    flex-direction: column;
  } */
  .navbar-toggler {
    width: 4rem;
    align-items: center;
    margin-top: -1rem;
    margin-right: 3rem;
    cursor: pointer;
    border: none;
    background-color: transparent !important;
  }

    }
@media (max-width: 1400px) and (min-width: 992px) {
  img.mobile {
    display: none;
  }
}
@media (max-width: 320px) and (min-width: 0px) {
  img.mobile {
    display: none;
  }
  img.desktop {
    display: none;
  }
}
@media (min-width: 1400px) {
  img.mobile {
    display: none;
  }
}
</style>

I tried little JS and CSS code I found on the Internet but it didn't work. I also tried triple to see, again it didn't work and don't want to use or to fix that issue. Maybe, I am using codes I found in the wrong place. Thanks for all!


Solution

  • One solution it's you create a data and method to do this and use on the template, like this:

    data:

    data: () => ({
        menuOpen: false,
      }),
    

    methods:

    methods: {
      toggleMenu() {
        this.menuOpen = !this.menuOpen;
      },
    

    template:

    <button
      class="navbar-toggler d-flex d-lg-none flex-column justify-content-around"
      type="button"
      data-bs-toggle="collapse"
      data-bs-target="#navbarSupportedContent"
      aria-controls="navbarSupportedContent"
      aria-expanded="false"
      aria-label="Toggle navigation"
      @click="toggleMenu"
    >
      <i v-if="!menuOpen">
        <fa :icon="['fas', 'bars']" class="icon toggle alt fa-3x burger-bars" />
      </i>
      <i v-else>
        <fa :icon="['fas', 'times']" class="icon toggle alt fa-3x burger-times" />
      </i>
    </button>