CSS transition does not work when I toggle the class with JS

Problem: I want to slide a searchbar from top to bottom with one click. I use a clickEvent with which I toggle the class show to the search input field. The class show only contains the target position.

Goal: I want the search input field to slide down. Currently it jumps from top to bottom.

Question Why doesn’t it work and what do I have to do to make it work?

const sbtn = document.querySelector('.nav__search-btn'),
sbar = document.querySelector('.searchbar__input');
sbtn.addEventListener('click', () => {
  sbar.classList.toggle('show');
});
* {
  box-sizing: border-box;
  padding: 0;
  margin: 0;
  position: relative;
}

.nav {
  display: flex;
  justify-content: space-between;
  background: lightgray;
  height: 50px;
  align-items: center;
}

.right {
  display: flex;
  justify-content: space-between;
  align-items: center;
  text-align: center;
  gap: 20px;
  height: 100%;
}

.btn {
  background: green;
  padding: 10px;
}


.searchbar {
  position: absolute;
  top: 0px;
  left: 10%;
  width: 80%;
  transition: top 1s ease 0s;
}

.searchbar__input {
  width: 100%;
  height: 30px;
  transition: all 2s;
}

.show {
  position: relative;
  top: 50px;
}
<nav>
  <div class="nav">
    <div></div>
    <div class="right">
      <div class="btn nav__search-btn">Search</div>
    </div>
  </div>
  <div class="searchbar">
    <input class="searchbar__input"/>
  </div>
</nav>

>Solution :

.searchbar__input also needs to have a top property.

You can also add position: relative; to .searchbar__input:


Edit: You don’t need the position property on .searchbar__input since you’re adding it to all in the global rule.

const sbtn = document.querySelector('.nav__search-btn'),
sbar = document.querySelector('.searchbar__input');
sbtn.addEventListener('click', () => {
  sbar.classList.toggle('show');
});
* {
  box-sizing: border-box;
  padding: 0;
  margin: 0;
  position: relative;
}

.nav {
  display: flex;
  justify-content: space-between;
  background: lightgray;
  height: 50px;
  align-items: center;
}

.right {
  display: flex;
  justify-content: space-between;
  align-items: center;
  text-align: center;
  gap: 20px;
  height: 100%;
}

.btn {
  background: green;
  padding: 10px;
}


.searchbar {
  position: absolute;
  top: 0px;
  left: 10%;
  width: 80%;
  transition: top 1s ease 0s;
}

.searchbar__input {
  width: 100%;
  height: 30px;
  top: 0;
  transition: all 2s;
}

.show {  
  top: 50px;
}
<nav>
  <div class="nav">
    <div></div>
    <div class="right">
      <div class="btn nav__search-btn">Search</div>
    </div>
  </div>
  <div class="searchbar">
    <input class="searchbar__input"/>
  </div>
</nav>

Leave a Reply