为啥我的 Accordion 关闭动画没有触发?它打开(有动画)但没有动画关闭
Posted
技术标签:
【中文标题】为啥我的 Accordion 关闭动画没有触发?它打开(有动画)但没有动画关闭【英文标题】:Why is my Accordion closing animation not firing? It opens (with animation) but closes without animation为什么我的 Accordion 关闭动画没有触发?它打开(有动画)但没有动画关闭 【发布时间】:2021-10-31 17:46:33 【问题描述】:这是我的问题的Fiddle(单击“Werknemers”或“Verzuimdossiers”旁边的图片)。
我有一个侧边栏,其中有些项目有子内容,有些则没有。所以我用 subnav 项目制作了一个手风琴。问题是开场动画效果很好。但是,关闭动画没有被触发。
这可能是什么问题?
参考代码
openSubnav = (evt, subNavName) =>
let i, subnavContent, subnavLinks;
//Check if the current accordion is clicked again to close it.
const subNav = document.getElementById(subNavName)
if (getComputedStyle(subNav).display === 'block')
subNav.style.display = 'none'
evt.currentTarget.className = evt.currentTarget.className.replace(" subnav-isActive", "");
subNav.style.maxHeight = null;
return
//hide alle subnav content
subnavContent = document.getElementsByClassName("subnav-content");
for (i = 0; i < subnavContent.length; i++)
subnavContent[i].style.display = "none";
//delete the subnav-isActive class
subnavLinks = document.getElementsByClassName("subnav-item");
for (i = 0; i < subnavLinks.length; i++)
subnavLinks[i].className = subnavLinks[i].className.replace(" subnav-isActive", "");
//Display the content
subNav.style.display = "block";
//Add the subnav-isActive class
evt.currentTarget.className += " subnav-isActive";
//If there currently is a max-height on the element, delete it.
if (subNav.style.maxHeight)
subNav.style.maxHeight = null;
subNav.style.maxHeight = subNav.scrollHeight + "px";
*
margin: 0;
padding: 0;
box-sizing: border-box;
.root
display: flex;
font-family: 'Poppins', sans-serif;
nav
-webkit-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
-o-user-select:none;
user-select:none;
.icon-container
width: 60px;
height: 50px;
display: flex;
justify-content: center;
align-items: center;
/* .sidebar:hover
width: 250px;
overflow: visible;
*/
.sidebar
width: 250px;
.sidebar
background-color: #8dc4d9;
position:absolute;
top:0;
bottom:0;
height:100%;
left:0;
/* width:60px; */
overflow:hidden;
-webkit-transition:width .05s linear;
transition:width .05s linear;
.sidebar>ul
margin: 10px 0;
.sidebar li
width:250px;
.sidebar li>span
position: relative;
display: table;
border-collapse: collapse;
border-spacing: 0;
font-size: 14px;
transition: all .1s linear;
.sidebar .nav-text
display: table-cell;
vertical-align: middle;
/* 250px breed totaal - 60px breed icoon = 190 */
width: 190px;
.sidebar .nav-dropdown
display: table-cell;
vertical-align: middle;
cursor: pointer;
padding-right: 20px;
padding-top: 8px;
.sidebar .nav-dropdown img
transform: rotate(270deg);
transition: transform .3s ease;
.sidebar .nav-dropdown.subnav-isActive img
transform: rotate(360deg);
.user
margin-bottom: 20px;
.sidebar li:hover>span
background-color:#76abbf;
.subnav-content
display: none;
/* 17px omdat de afbeelding 24x24 is en de breedte van de sidebar 60px.
Met de afbeelding houd je dus 17px aan beiden kanten over. */
padding: 10px 17px;
background-color:#76abbf;
list-style: none;
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;
.content
width: calc(50% - 30px);
background-color: #f3f6f9;
.preview
width: calc(50% - 30px);
background-color: #f3f6f9;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
<title>Sidebar</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&display=swap" rel="stylesheet">
</head>
<body>
<div class="root">
<nav class="sidebar">
<ul>
<li class="user">
<span>
<div class="icon-container">
<img class="nav-icon" src="./icons24/user32.png" >
</div>
<span class="nav-text">
Mijn account
</span>
</span>
</li>
<li>
<span>
<div class="icon-container">
<img class="nav-icon" src="./icons24/bureaublad24.png" >
</div>
<span class="nav-text">
Dashboard
</span>
</span>
</li>
<li class="has-subnav">
<span>
<div class="icon-container">
<img class="nav-icon" src="./icons24/werknemers24.png" >
</div>
<span class="nav-text">
Werknemers
</span>
<span class="nav-dropdown subnav-item" onclick="openSubnav(event, 'Werknemers')">
<img src="./icons24/DropdownArrow16.png">
</span>
</span>
<ul id="Werknemers" class="subnav-content">
<li>kaas</li>
<li>brood</li>
<li>eieren</li>
</ul>
</li>
<li>
<span>
<div class="icon-container">
<img class="nav-icon" src="./icons24/verzuimdossiers24.png" >
</div>
<span class="nav-text">
Verzuimdossiers
</span>
<span class="nav-dropdown subnav-item" onclick="openSubnav(event, 'Verzuimdossiers')">
<img src="./icons24/DropdownArrow16.png">
</span>
</span>
<ul id="Verzuimdossiers" class="subnav-content">
<li>boter</li>
<li>friet</li>
<li>pasta</li>
</ul>
</li>
<li>
<span>
<div class="icon-container">
<img class="nav-icon" src="./icons24/trajecten24.png" >
</div>
<span class="nav-text">
Trajecten
</span>
</span>
</li>
<li>
<span>
<div class="icon-container">
<img class="nav-icon" src="./icons24/projecten24.png" >
</div>
<span class="nav-text">
Projecten
</span>
</span>
</li>
</ul>
</nav>
<div class="content">
Content
</div>
<div class="preview">
Preview
</div>
</div>
</body>
</html>
【问题讨论】:
【参考方案1】:您需要在display: none
之前设置超时,以便有时间执行结束动画。
就像这段代码:
const subNav = document.getElementById(subNavName)
if (getComputedStyle(subNav).display === 'block')
evt.currentTarget.className = evt.currentTarget.className.replace(" subnav-isActive", "");
subNav.style.maxHeight = null;
setTimeout(function()subNav.style.display = 'none';, 100);
return
这里你有完整的正确代码(idk 为什么,但你需要展开 sn-p 才能看到它的工作,点击 Run code sn-p 然后 Full page 链接):
openSubnav = (evt, subNavName) =>
let i, subnavContent, subnavLinks;
//Check if the current accordion is clicked again to close it.
const subNav = document.getElementById(subNavName)
if (getComputedStyle(subNav).display === 'block')
evt.currentTarget.className = evt.currentTarget.className.replace(" subnav-isActive", "");
subNav.style.maxHeight = null;
setTimeout(function()subNav.style.display = 'none';, 100);
return
//hide alle subnav content
subnavContent = document.getElementsByClassName("subnav-content");
for (i = 0; i < subnavContent.length; i++)
subnavContent[i].style.display = "none";
//delete the subnav-isActive class
subnavLinks = document.getElementsByClassName("subnav-item");
for (i = 0; i < subnavLinks.length; i++)
subnavLinks[i].className = subnavLinks[i].className.replace(" subnav-isActive", "");
//Display the content
subNav.style.display = "block";
//Add the subnav-isActive class
evt.currentTarget.className += " subnav-isActive";
//If there currently is a max-height on the element, delete it.
if (subNav.style.maxHeight)
subNav.style.maxHeight = null;
subNav.style.maxHeight = subNav.scrollHeight + "px";
*
margin: 0;
padding: 0;
box-sizing: border-box;
.root
display: flex;
font-family: 'Poppins', sans-serif;
nav
-webkit-user-select:none;
-moz-user-select:none;
-ms-user-select:none;
-o-user-select:none;
user-select:none;
.icon-container
width: 60px;
height: 50px;
display: flex;
justify-content: center;
align-items: center;
/* .sidebar:hover
width: 250px;
overflow: visible;
*/
.sidebar
width: 250px;
.sidebar
background-color: #8dc4d9;
position:absolute;
top:0;
bottom:0;
height:100%;
left:0;
/* width:60px; */
overflow:hidden;
-webkit-transition:width .05s linear;
transition:width .05s linear;
.sidebar>ul
margin: 10px 0;
.sidebar li
width:250px;
.sidebar li>span
position: relative;
display: table;
border-collapse: collapse;
border-spacing: 0;
font-size: 14px;
transition: all .1s linear;
.sidebar .nav-text
display: table-cell;
vertical-align: middle;
/* 250px breed totaal - 60px breed icoon = 190 */
width: 190px;
.sidebar .nav-dropdown
display: table-cell;
vertical-align: middle;
cursor: pointer;
padding-right: 20px;
padding-top: 8px;
.sidebar .nav-dropdown img
transform: rotate(270deg);
transition: transform .3s ease;
.sidebar .nav-dropdown.subnav-isActive img
transform: rotate(360deg);
.user
margin-bottom: 20px;
.sidebar li:hover>span
background-color:#76abbf;
.subnav-content
display: none;
/* 17px omdat de afbeelding 24x24 is en de breedte van de sidebar 60px.
Met de afbeelding houd je dus 17px aan beiden kanten over. */
padding: 10px 17px;
background-color:#76abbf;
list-style: none;
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;
.content
width: calc(50% - 30px);
background-color: #f3f6f9;
.preview
width: calc(50% - 30px);
background-color: #f3f6f9;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
<title>Sidebar</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&display=swap" rel="stylesheet">
</head>
<body>
<div class="root">
<nav class="sidebar">
<ul>
<li class="user">
<span>
<div class="icon-container">
<img class="nav-icon" src="./icons24/user32.png" >
</div>
<span class="nav-text">
Mijn account
</span>
</span>
</li>
<li>
<span>
<div class="icon-container">
<img class="nav-icon" src="./icons24/bureaublad24.png" >
</div>
<span class="nav-text">
Dashboard
</span>
</span>
</li>
<li class="has-subnav">
<span>
<div class="icon-container">
<img class="nav-icon" src="./icons24/werknemers24.png" >
</div>
<span class="nav-text">
Werknemers
</span>
<span class="nav-dropdown subnav-item" onclick="openSubnav(event, 'Werknemers')">
<img src="./icons24/DropdownArrow16.png">
</span>
</span>
<ul id="Werknemers" class="subnav-content">
<li>kaas</li>
<li>brood</li>
<li>eieren</li>
</ul>
</li>
<li>
<span>
<div class="icon-container">
<img class="nav-icon" src="./icons24/verzuimdossiers24.png" >
</div>
<span class="nav-text">
Verzuimdossiers
</span>
<span class="nav-dropdown subnav-item" onclick="openSubnav(event, 'Verzuimdossiers')">
<img src="./icons24/DropdownArrow16.png">
</span>
</span>
<ul id="Verzuimdossiers" class="subnav-content">
<li>boter</li>
<li>friet</li>
<li>pasta</li>
</ul>
</li>
<li>
<span>
<div class="icon-container">
<img class="nav-icon" src="./icons24/trajecten24.png" >
</div>
<span class="nav-text">
Trajecten
</span>
</span>
</li>
<li>
<span>
<div class="icon-container">
<img class="nav-icon" src="./icons24/projecten24.png" >
</div>
<span class="nav-text">
Projecten
</span>
</span>
</li>
</ul>
</nav>
<div class="content">
Content
</div>
<div class="preview">
Preview
</div>
</div>
</body>
</html>
【讨论】:
【参考方案2】:原因是因为你的动画需要一些时间来执行,但是你在你的动画有机会被渲染之前分配了display: none
。
【讨论】:
以上是关于为啥我的 Accordion 关闭动画没有触发?它打开(有动画)但没有动画关闭的主要内容,如果未能解决你的问题,请参考以下文章
为啥我的 AngularJS ajax 自动触发,即使我没有调用它?