skip to Main Content

CSS transitions aren’t working for me when I try to execute them through JavaScript.

let isSearchBarOpen = false;

function toggleSearchBar() {
  if (isSearchBarOpen) {
    searchBar.style.display = "none";
  } else {
    searchBar.style.display = "flex";
    searchBar.classList.add("search-bar-open")
  }
  isSearchBarOpen = !isSearchBarOpen;

  toggleSearchIcon();
}
.search-bar {
  display: none;
  background-color: #000;
  color: #fff;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  padding: 10px 5px;
  z-index: 1000;
  margin: 0 auto;
  transition: top 2s ease-in;
}

.search-bar-open {
  top: 90px;
}
<div class="search-icon">
  <i class="fas fa-search search-icon-header"></i>
  <img src="images/close-icon.svg" alt="close-icon-search" class="close-icon-search">
</div>
<div class="search-bar" id="search-bar">
  <div class="search-container">
    <form class="search-form">
      <input type="text" placeholder="Search...">
      <button type="submit"><i class="fas fa-search search-icon-action"></i></button>
    </form>
  </div>
</div>

When the search button is clicked, the following things happen (or should happen if I am not wrong):

  1. The function checks if isSearchBarOpen is true or false.
  2. If true —that is, if the search bar is open—, an inline style is added (display:none) hiding the bar.
  3. If it is false — that is, if the search bar is closed — an inline style is added (display:flex) so that it show up. And, in addition, a class is added (.search-bar-open).

From there, if we look at the CSS…

  1. The search bar, when opened (when it shows up), loads the .search-bar-open class and the display:flex inline style. On the one hand, said inline style overrides the display:none CSS property applied through the .search-bar class by specificity.

  2. And, in addition, the .search-bar-open class is added.

  3. Now, I assume that, when the .search-bar-open class is applied, the transition stipulated within .search-bar should occur, that is:

a. I’m in top:0;

b. And in 2 seconds with ease-in

c. I am set top:90px;.

Something I must’ve misunderstood, since it is not working 🙁

3

Answers


  1. If you use JS to make an element visible AND add a class to trigger a transition, it will not work because JS does both those actions at the same time. A transition will trigger if a property is changed on an element, but done like this, the top property is never changed, it was already there when the element was made visible.

    You can add a JS action in between to trigger a browser ‘reflow’. That way the browser makes the element visible first, draws that element on the page, and then adds the class to trigger the transition.

    searchBar.style.display = "flex";
    searchBar.offsetWidth;
    searchBar.classList.add("search-bar-open")
    
    Login or Signup to reply.
  2. the problem is that transitions does not work for display: none properties,
    instead of doing display none to flex, just do something to hide search bar without doing display: none;

    one possible solution is to give negative top value to remove from visible window
    like top: -50px (or you can give exact value as the height of your searchbar)

    let isSearchBarOpen = false;
    
        function toggleSearchBar() {
              if (isSearchBarOpen) {
                searchBar.style.top= "-50px";   //here used top instead of display
              } else {
                 searchBar.classList.add("search-bar-open")
              }
              isSearchBarOpen = !isSearchBarOpen;
                
              toggleSearchIcon();
          }
    
    .search-bar {
        display: flex;      //here let it to be flex
        background-color: #000;
        color: #fff;
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        padding: 10px 5px;
        z-index: 1000; 
        margin: 0 auto;
        transition: top 2s ease-in;
    }
    
    .search-bar-open {
        top:90px; 
    }
    
    Login or Signup to reply.
  3. The transition not work for display:none. So, instead of transition use animation.

    example code:

    CSS:

           .search-bar {
                display: none;
                background-color: #000;
                color: #fff;
                position: absolute;
                top: 0;
                left: 0;
                right: 0;
                padding: 10px 5px;
                z-index: 1000;
                margin: 0 auto;
                animation: toggleOnAnimation 2s ease-in;
            }
    
            .search-bar-open {
                top: 90px;
            }
    
            @keyframes toggleOnAnimation {
                0% {
                    top: 0
                }
    
                100% {
                    top: 90px
                }
            }
    

    Javascript:

            let isSearchBarOpen = false;
            let searchBar = document.getElementById("search-bar");
            function toggleSearchBar() {
                if (isSearchBarOpen) {
                    searchBar.style.display = "none";
                } else {
                    searchBar.style.display = "flex";
                    searchBar.classList.add("search-bar-open")
                }
                isSearchBarOpen = !isSearchBarOpen;
    
            }
    

    HTML:

        <div class="search-icon">
            <i class="fas fa-search search-icon-header"></i>
            <!-- <img src="images/close-icon.svg" alt="close-icon-search" class="close-icon-search"> -->
            <button onclick="toggleSearchBar()">Click</button>
        </div>
        <div class="search-bar" id="search-bar">
            <div class="search-container">
                <form class="search-form">
                    <input type="text" placeholder="Search...">
                    <button type="submit">
                        Submit
                    </button>
                </form>
            </div>
        </div>
    

    Here, I used animation instead of transition. Hope you undertand 🙂

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search