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):
isSearchBarOpen
is true
or false
.true
—that is, if the search bar is open—, an inline style is added (display:none
) hiding the bar.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…
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.
And, in addition, the .search-bar-open
class is added.
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 :-(
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")