cssreactjsjsxstyled-jsx

What exactly is the problem with this :before Pseudo element?


So, I was trying to create a basic hover animation in my navbar for a React app using pseudo elements of CSS. When I tried to implement the code, this problem showed and I don't understand the exact reason behind it.

I have used Bootstrap to create a basic layout and then tried to implement my own CSS.

JSX code:

<div className="collapse navbar-collapse" id="navbarSupportedContent">
  <ul className="navbar-nav me-auto mb-2 mb-lg-0">
    <li className="nav-item">
      <a className="menu nav" aria-current="page" href="#">Home</a>
    </li>
    <li className="nav-item">
      <a className="menu nav" href="#">Products</a>
    </li>
  </ul>
</div>

CSS code:

#navbarSupportedContent {
  position    : relative;
  top         : 5.78px;
  margin-left : .4em;
  }
.nav{
  font-family     : var(--font-1);
  font-size       : 1.2em;
  color           : var(--color-1);
  text-decoration : none;
  }
#navbarSupportedContent ul li:not(:last-child) {
  margin-right : 1em;
  }
.menu::before{
  content       : "";
  position      : absolute;
  bottom        : 0;
  left          : 0;
  width         : 0;
  height        : 4px;
  background    : var(--color-1);
  border-radius : 50px;
  transform     : translateY(-4px);
  transition    : width .5s ease;
  }
.menu:hover::before {
  width : 100%;
  }

I was expecting:

I got:

What is the error? How can I fix it?


Solution

  • You need to use :after pseudo class instead, remove position: absolute and add display: inline-block to the pseudo element and add the pseudo element after the li instead of the .menu class. I also added the required media query to make it look right when the navbar is collapsed. The changes:

    ul li::after{            
        /* position: absolute; */
        display: inline-block;
    }
    
    ul li:hover::after{
        width : 100%;
    }
    
    @media screen and (max-width: 992px){
        nav ul.navbar-nav{
            display: inline-flex;
            flex-direction: column;
        }
    }
    

    #navbarSupportedContent {
        position    : relative;
        top         : 5.78px;
        margin-left : .4em;
    }
    .nav{
        font-family     : var(--font-1);
        font-size       : 1.2em;
        color           : var(--color-1);
        text-decoration : none;
    }
    #navbarSupportedContent ul li:not(:last-child) {
        margin-right : 1em;
    }
    ul li::after{
        content       : "";
        /* position      : absolute; */
        display: inline-block;
        bottom        : 0;
        left          : 0;
        width         : 0;
        height        : 4px;
        background    : var(--color-1);
        background: red;
        border-radius : 50px;
        transform     : translateY(-4px);
        transition    : width .5s ease;
    }
    
    ul li:hover::after {
        width : 100%;
    }
    
    @media screen and (max-width: 992px){
        nav ul.navbar-nav{
            display: inline-flex;
            flex-direction: column;
        }
    }
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-4bw+/aepP/YC94hEpVNVgiZdgIC5+VKNBQNGCHeKRQN+PtmoHDEXuppvnDJzQIu9" crossorigin="anonymous">
    
    <nav class="navbar navbar-expand-lg bg-body-tertiary">
        <div class="container-fluid">
          <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
          </button>
    
            <div class="collapse navbar-collapse" id="navbarSupportedContent">
                <ul class="navbar-nav me-auto mb-2 mb-lg-0">
                    <li class="nav-item">
                        <a class="menu nav" aria-current="page" href="#">Home</a>
                    </li>
                    <li class="nav-item">
                        <a class="menu nav" href="#">Products</a>
                    </li>
                </ul>
            </div>
    
        </div>
    </nav>
    
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-HwwvtgBNo3bZJJLYd8oVXjrBZt8cqVSpeBNS5n7C8IVInixGAoxmnlMuBnhbgrkm" crossorigin="anonymous"></script>