Reputation: 14216
I have crafted a small css drop down button/menu which I am now trying to animate.
I had the menu initially going from display: none
to display:block
when hovering the parent, but I cannot animate this - so I have tried swapping to opacity: 0, height: 0
to opacity: 1, height: auto
but this is causing some weird functionality with the menu. Let me show you what I mean. Here is the original menu code :
HTML :
<div className="account-dropdown">
<button className="dropbtn">
<FormattedMessage
id="header.account"
defaultMessage={`Account`} />
</button>
<div className="dropdown-content">
<a>Order History</a>
<a>Settings</a>
<a onClick={logOut}>Logout</a>
</div>
</div>
The scss :
.account-dropdown {
position: relative;
display: inline-block;
&:hover {
.dropdown-content {
display: block;
}
.dropbtn {
color: red;
}
}
.dropbtn {
border: none;
cursor: pointer;
margin: 2rem 1rem;
transition: all 0.3s;
color: black;
background-color: #fff;
}
.dropdown-content {
display: none;
padding: 3rem 3rem 1rem 3rem;
position: absolute;
top: 5rem;
left: -17.6rem;
background-color: #fff;
min-width: 250px;
width: 100%;
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.2);
border: solid 1px #e8e8e8;
z-index: 1;
color: rgba(0, 0, 0, 0);
transition: all 0.3s;
&:after, &:before {
bottom: 100%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
&:after {
border-color: rgba(255, 255, 255, 0);
border-bottom-color: #ffffff;
border-width: 7px;
left: 75%;
margin-left: 26px;
}
&:before {
border-color: rgba(113, 158, 206, 0);
border-bottom-color: #e8e8e8;
border-width: 8px;
left: 75%;
margin-left: 25px;
}
a {
text-align: left;
color: black;
padding-bottom: .8rem;
text-decoration: none;
display: block;
cursor: pointer;
transition: all 0.3s;
&:hover {
color: black;
}
&:last-child {
margin-top: .4rem;
padding-top: .8rem;
border-top: solid 1px #e8e8e8;
}
}
}
}
Here it is running in a fiddle (without the rems or scss vars) https://jsfiddle.net/tqf1r0mm/7/
And here is a fiddle when I swap the display none for opacity and height -> https://jsfiddle.net/tqf1r0mm/10/ .
You can see both that the animation is janky and also if you hover below account button the menu opens (I would only like it to open when the user hovers account).
Any ideas on how to fix this to get a nice smooth animation? Any advice would be great. Thanks!
Upvotes: 0
Views: 1986
Reputation: 833
Use visibility instead of height, but use the opacity as well, because you can't animate visibility either. Also put the trigger on .dropbtn instead of .account-dropdown to avoid it activating the hover state when you hover anywhere except the button.
I don't know SCSS so I used CodePen to convert to regular CSS. Here's the code I used:
.test {
padding-left: 300px;
}
.test .account-dropdown {
position: relative;
display: inline-block;
}
.test .account-dropdown .dropbtn:hover~.dropdown-content {
visibility: visible;
opacity: 1;
}
.test .account-dropdown .dropdown-content:hover {
visibility: visible;
opacity: 1;
}
.test .account-dropdown:hover .dropbtn {
color: black;
}
.test .account-dropdown .dropbtn {
border: none;
cursor: pointer;
margin: 20px 10px;
transition: all 0.3s;
color: black;
background-color: #fff;
}
.test .account-dropdown .dropdown-content {
opacity: 0;
visibility: hidden;
padding: 3rem 3rem 1rem 3rem;
position: absolute;
top: 50px;
left: -176px;
background-color: #fff;
min-width: 250px;
width: 100%;
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.2);
border: solid 1px #e8e8e8;
z-index: 1;
color: transparent;
transition: all 0.3s;
}
.test .account-dropdown .dropdown-content:after,
.test .account-dropdown .dropdown-content:before {
bottom: 100%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
.test .account-dropdown .dropdown-content:after {
border-color: rgba(255, 255, 255, 0);
border-bottom-color: #ffffff;
border-width: 7px;
left: 75%;
margin-left: 26px;
}
.test .account-dropdown .dropdown-content:before {
border-color: rgba(113, 158, 206, 0);
border-bottom-color: #e8e8e8;
border-width: 8px;
left: 75%;
margin-left: 25px;
}
.test .account-dropdown .dropdown-content a {
text-align: left;
color: black;
padding-bottom: 8px;
text-decoration: none;
display: block;
cursor: pointer;
transition: all 0.3s;
}
.test .account-dropdown .dropdown-content a:hover {
color: black;
}
.test .account-dropdown .dropdown-content a:last-child {
margin-top: 4px;
padding-top: 8px;
border-top: solid 1px #e8e8e8;
}
<div class="test">
<div class="account-dropdown">
<button class="dropbtn">
Account
</button>
<div class="dropdown-content">
<a>Order History</a>
<a>Settings</a>
<a>Logout</a>
</div>
</div>
</div>
I also added another hover class when you hover over .dropdown-content otherwise it dissappears when you try to click on one of the links.
Upvotes: 1
Reputation: 36
you may be using the atribute transition: all and is because that the animation looks like that
but instead of using height:0; you can use: visibility:hidden; and visibility:visible on hover to avoid that animation problem
something like this
.test {
padding-left: 300px;
.account-dropdown {
position: relative;
display: inline-block;
&:hover {
.dropdown-content {
opacity: 1;
visibility:visible;
}
.dropbtn {
color: black;
}
}
.dropbtn {
border: none;
cursor: pointer;
margin: 20px 10px;
transition: all 0.3s;
color: black;
background-color: #fff;
}
.dropdown-content {
opacity: 0;
visibility:hidden;
padding: 3rem 3rem 1rem 3rem;
position: absolute;
top: 50px;
left: -176px;
background-color: #fff;
min-width: 250px;
width: 100%;
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.2);
border: solid 1px #e8e8e8;
z-index: 1;
color: rgba(0, 0, 0, 0);
transition: all 0.3s;
&:after,
&:before {
bottom: 100%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
&:after {
border-color: rgba(255, 255, 255, 0);
border-bottom-color: #ffffff;
border-width: 7px;
left: 75%;
margin-left: 26px;
}
&:before {
border-color: rgba(113, 158, 206, 0);
border-bottom-color: #e8e8e8;
border-width: 8px;
left: 75%;
margin-left: 25px;
}
a {
text-align: left;
color: black;
padding-bottom: 8px;
text-decoration: none;
display: block;
cursor: pointer;
transition: all 0.3s;
&:hover {
color: black;
}
&:last-child {
margin-top: 4px;
padding-top: 8px;
border-top: solid 1px #e8e8e8;
}
}
}
}
}
Upvotes: 2