Reputation: 3176
I'm struggling to rotate an icon in this accordion when the accordion is open. I've done most of the work, but I'm missing something.
How do I rotate the SVG icon by 180deg when it's open? And then back to its origin when closed?
If you'd prefer a Codepen, it is here.
This is the snippet I'm using to rotate the icon.
[...document.querySelectorAll('.acc-icon')].forEach(function(item) {
item.addEventListener('click', function() {
this.classList.toggle('down');
})
})
function initAccordion() {
function handlePanelClick(event) {
showPanel(event.currentTarget);
}
function showPanel(panelHeader) {
let isActive,
panel = panelHeader.parentNode,
expandedPanel = document.querySelector(".panel.active");
isActive =
expandedPanel && panel.classList.contains("active") ? true : false;
if (expandedPanel) {
expandedPanel.querySelector(".acc-body").style.height = null;
expandedPanel.classList.remove("active");
}
if (panel && !isActive) {
panel.classList.add("active");
}
}
let allPanelElements = document.querySelectorAll(".panel");
for (let i = 0; i < allPanelElements.length; i++) {
allPanelElements[i]
.querySelector(".acc-trigger")
.addEventListener("click", handlePanelClick);
}
showPanel(allPanelElements);
}
[...document.querySelectorAll('.acc-icon')].forEach(function(item) {
item.addEventListener('click', function() {
this.classList.toggle('down');
})
})
initAccordion(document.getElementsByClassName("accordion"));
.wrapper {
margin: 50px auto;
display: flex;
flex-direction: column
}
.wrapper a {
text-decoration: none
}
.wrapper button {
border-style: none;
background: #fff
}
.wrapper button::-moz-focus-inner {
border: 0
}
@media (min-width:768px) {
.wrapper {
flex-direction: row
}
.accordion {
flex: 1
}
}
.wrapper .accordion {
margin: 0 .1rem
}
.wrapper .accordion .panel {
min-height: 4rem;
margin: 0 .1rem
}
.wrapper .accordion .panel .acc-trigger {
display: block;
font-weight: 400;
margin: 0;
padding: .5em 1em;
position: relative;
text-align: left;
width: 100%;
cursor: pointer;
background: 0 0
}
.wrapper .accordion .panel .acc-trigger .acc-title {
display: flex;
align-items: center;
border: transparent 2px solid;
outline: 0
}
.wrapper .accordion .panel .acc-trigger .acc-title h4 {
font-weight: 600;
color: #000a70;
font-size: 1.25rem;
justify-content: space-between;
margin-right: 1rem;
outline: 0
}
.wrapper .accordion .panel .acc-trigger .acc-title svg.acc-icon {
cursor: pointer;
pointer-events: none;
margin-left: auto;
z-index: 3;
}
.acc-title svg.acc-icon {
transition: all 0.2s ease-in-out;
}
.acc-title svg.acc-icon.down {
transform: rotate(180deg);
}
.wrapper .accordion .panel .acc-body {
height: 0;
opacity: 0;
overflow: hidden;
visibility: hidden;
transition: height .2s ease-out, opacity .2s ease-out;
}
.wrapper .accordion .panel.active .acc-body p {
font-size: 16px;
line-height: 24px;
margin-bottom: 24px;
}
.wrapper .accordion .panel.active .acc-body p a {
color: #005fec;
}
.wrapper .accordion .panel.active .acc-body p a:hover {
text-decoration: underline;
text-decoration-color: #005fec;
}
.wrapper .accordion .panel.active .acc-body p a:hover {
text-decoration: underline;
text-decoration-color: #005fec;
}
.wrapper .accordion .panel .acc-body ol.custom-list {
list-style-type: none;
-webkit-margin-before: 0;
margin-block-start: 0;
-webkit-margin-after: 0;
margin-block-end: 0;
counter-reset: my-awesome-counter;
}
.wrapper .accordion .panel .acc-body ol.custom-list li {
counter-increment: my-awesome-counter;
padding-left: 1.125rem;
margin: 2rem 0;
font-size: 1rem;
line-height: 1.5rem;
color: #000a70
}
.wrapper .accordion .panel .acc-body ol.custom-list li::before {
content: counter(my-awesome-counter) ". ";
color: #005fec
}
.wrapper .accordion .panel .acc-body ol.custom-list li:first-child {
margin-top: 0
}
.wrapper .accordion .panel .acc-body ol.custom-list li:last-child {
margin-bottom: 2rem;
}
.wrapper .accordion .panel .acc-body ol.custom-list li a,
.wrapper .accordion .panel .acc-body ul.custom-list li a {
color: #005fec
}
.wrapper .accordion .panel .acc-body ol.custom-list li a:hover,
.wrapper .accordion .panel .acc-body ul.custom-list li a:hover {
text-decoration: underline;
text-decoration-color: #005fec;
}
.wrapper .accordion .panel .acc-body ul.custom-list {
list-style-type: none;
-webkit-margin-before: 0;
margin-block-start: 0;
-webkit-margin-after: 0;
margin-block-end: 0
}
.wrapper .accordion .panel .acc-body ul.custom-list li {
background-image: url(/assets/svg/bullet.svg);
background-position: 0 .5rem;
background-repeat: no-repeat;
padding-left: 1.125rem;
margin: 2rem 0;
font-size: 1rem;
line-height: 1.5rem
}
.wrapper .accordion .panel .acc-body ul.custom-list li:first-child {
margin-top: 0
}
.wrapper .accordion .panel .acc-body ul.custom-list li:last-child {
margin-bottom: 2rem;
}
.wrapper .accordion .panel.active .acc-body {
opacity: 1;
height: auto;
padding: .5rem 1rem;
visibility: visible
}
.wrapper .accordion .panel .acc-trigger .acc-title {
border-bottom: 1px solid #000a70;
padding-bottom: .5rem;
transition: all .2s ease;
}
.wrapper .accordion .panel.active .acc-trigger .acc-title {
border-bottom: 0;
}
.wrapper .accordion .panel.active p:last-child {
border-bottom: 1px solid #000a70;
padding-bottom: .5rem
}
.wrapper .accordion .panel .acc-trigger .acc-title h4:hover,
.wrapper .accordion .panel.active .acc-trigger .acc-title h4 {
color: #005fec
}
<div class="wrapper">
<div class="accordion">
<div class="panel">
<button aria-expanded="false" class="acc-trigger">
<span class="acc-title">
<h4>Question One</h4>
<svg class="acc-icon" width="16" height="11" viewBox="0 0 16 11" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 2.82813L2 0.828126L8 6.82813L14 0.828126L16 2.82813L8 10.8281L0 2.82813Z" fill="#000A70" />
</svg>
</span>
</button>
<div class="acc-body">
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Saepe harum eaque quis, unde neque quo minima porro praesentium cum id.</p>
<p>Doloremque facere deserunt dolore minus repellat. Quas impedit nihil, deserunt a laboriosam animi ullam quidem earum commodi, rerum assumenda incidunt.</p>
<p>Quo nihil beatae pariatur. Porro vitae eius hic harum aliquam asperiores voluptatem assumenda, iure quae maiores quis possimus error itaque!</p>
</div>
</div>
<div class="panel">
<button aria-expanded="false" class="acc-trigger">
<span class="acc-title">
<h4>Question Two</h4>
<svg class="acc-icon" width="16" height="11" viewBox="0 0 16 11" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 2.82813L2 0.828126L8 6.82813L14 0.828126L16 2.82813L8 10.8281L0 2.82813Z" fill="#000A70" />
</svg>
</span>
</button>
<div class="acc-body">
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Saepe harum eaque quis, unde neque quo minima porro praesentium cum id.</p>
<p>Doloremque facere deserunt dolore minus repellat. Quas impedit nihil, deserunt a laboriosam animi ullam quidem earum commodi, rerum assumenda incidunt.</p>
<p>Quo nihil beatae pariatur. Porro vitae eius hic harum aliquam asperiores voluptatem assumenda, iure quae maiores quis possimus error itaque!</p>
</div>
</div>
</div>
</div>
Upvotes: 0
Views: 179
Reputation: 14629
You can get the svg from the clicked panel and rotate it using a css transform: rotate
function initAccordion() {
function handlePanelClick(event) {
showPanel(event.currentTarget);
}
function showPanel(panelHeader) {
let isActive,
panel = panelHeader.parentNode,
expandedPanel = document.querySelector(".panel.active");
isActive =
expandedPanel && panel.classList.contains("active") ? true : false;
if (expandedPanel) {
expandedPanel.querySelector(".acc-body").style.height = null;
expandedPanel.classList.remove("active");
const svg = panel.querySelector("svg");
svg.style.transform = 'rotate(0deg)'
}
if (panel && !isActive) {
panel.classList.add("active");
const svg = panel.querySelector("svg");
svg.style.transform = 'rotate(180deg)'
}
}
let allPanelElements = document.querySelectorAll(".panel");
for (let i = 0; i < allPanelElements.length; i++) {
allPanelElements[i]
.querySelector(".acc-trigger")
.addEventListener("click", handlePanelClick);
}
showPanel(allPanelElements);
}
[...document.querySelectorAll('.acc-icon')].forEach(function(item) {
item.addEventListener('click', function() {
this.classList.toggle('down');
})
})
initAccordion(document.getElementsByClassName("accordion"));
.wrapper {
margin: 50px auto;
display: flex;
flex-direction: column
}
.wrapper a {
text-decoration: none
}
.wrapper button {
border-style: none;
background: #fff
}
.wrapper button::-moz-focus-inner {
border: 0
}
@media (min-width:768px) {
.wrapper {
flex-direction: row
}
.accordion {
flex: 1
}
}
.wrapper .accordion {
margin: 0 .1rem
}
.wrapper .accordion .panel {
min-height: 4rem;
margin: 0 .1rem
}
.wrapper .accordion .panel .acc-trigger {
display: block;
font-weight: 400;
margin: 0;
padding: .5em 1em;
position: relative;
text-align: left;
width: 100%;
cursor: pointer;
background: 0 0
}
.wrapper .accordion .panel .acc-trigger .acc-title {
display: flex;
align-items: center;
border: transparent 2px solid;
outline: 0
}
.wrapper .accordion .panel .acc-trigger .acc-title h4 {
font-weight: 600;
color: #000a70;
font-size: 1.25rem;
justify-content: space-between;
margin-right: 1rem;
outline: 0
}
.wrapper .accordion .panel .acc-trigger .acc-title svg.acc-icon {
cursor: pointer;
pointer-events: none;
margin-left: auto;
z-index: 3;
}
.acc-title svg.acc-icon {
transition: all 0.2s ease-in-out;
}
.acc-title svg.acc-icon.down {
transform: rotate(180deg);
}
.wrapper .accordion .panel .acc-body {
height: 0;
opacity: 0;
overflow: hidden;
visibility: hidden;
transition: height .2s ease-out, opacity .2s ease-out;
}
.wrapper .accordion .panel.active .acc-body p {
font-size: 16px;
line-height: 24px;
margin-bottom: 24px;
}
.wrapper .accordion .panel.active .acc-body p a {
color: #005fec;
}
.wrapper .accordion .panel.active .acc-body p a:hover {
text-decoration: underline;
text-decoration-color: #005fec;
}
.wrapper .accordion .panel.active .acc-body p a:hover {
text-decoration: underline;
text-decoration-color: #005fec;
}
.wrapper .accordion .panel .acc-body ol.custom-list {
list-style-type: none;
-webkit-margin-before: 0;
margin-block-start: 0;
-webkit-margin-after: 0;
margin-block-end: 0;
counter-reset: my-awesome-counter;
}
.wrapper .accordion .panel .acc-body ol.custom-list li {
counter-increment: my-awesome-counter;
padding-left: 1.125rem;
margin: 2rem 0;
font-size: 1rem;
line-height: 1.5rem;
color: #000a70
}
.wrapper .accordion .panel .acc-body ol.custom-list li::before {
content: counter(my-awesome-counter) ". ";
color: #005fec
}
.wrapper .accordion .panel .acc-body ol.custom-list li:first-child {
margin-top: 0
}
.wrapper .accordion .panel .acc-body ol.custom-list li:last-child {
margin-bottom: 2rem;
}
.wrapper .accordion .panel .acc-body ol.custom-list li a,
.wrapper .accordion .panel .acc-body ul.custom-list li a {
color: #005fec
}
.wrapper .accordion .panel .acc-body ol.custom-list li a:hover,
.wrapper .accordion .panel .acc-body ul.custom-list li a:hover {
text-decoration: underline;
text-decoration-color: #005fec;
}
.wrapper .accordion .panel .acc-body ul.custom-list {
list-style-type: none;
-webkit-margin-before: 0;
margin-block-start: 0;
-webkit-margin-after: 0;
margin-block-end: 0
}
.wrapper .accordion .panel .acc-body ul.custom-list li {
background-image: url(/assets/svg/bullet.svg);
background-position: 0 .5rem;
background-repeat: no-repeat;
padding-left: 1.125rem;
margin: 2rem 0;
font-size: 1rem;
line-height: 1.5rem
}
.wrapper .accordion .panel .acc-body ul.custom-list li:first-child {
margin-top: 0
}
.wrapper .accordion .panel .acc-body ul.custom-list li:last-child {
margin-bottom: 2rem;
}
.wrapper .accordion .panel.active .acc-body {
opacity: 1;
height: auto;
padding: .5rem 1rem;
visibility: visible
}
.wrapper .accordion .panel .acc-trigger .acc-title {
border-bottom: 1px solid #000a70;
padding-bottom: .5rem;
transition: all .2s ease;
}
.wrapper .accordion .panel.active .acc-trigger .acc-title {
border-bottom: 0;
}
.wrapper .accordion .panel.active p:last-child {
border-bottom: 1px solid #000a70;
padding-bottom: .5rem
}
.wrapper .accordion .panel .acc-trigger .acc-title h4:hover,
.wrapper .accordion .panel.active .acc-trigger .acc-title h4 {
color: #005fec
}
<div class="wrapper">
<div class="accordion">
<div class="panel">
<button aria-expanded="false" class="acc-trigger">
<span class="acc-title">
<h4>Question One</h4>
<svg class="acc-icon" width="16" height="11" viewBox="0 0 16 11" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 2.82813L2 0.828126L8 6.82813L14 0.828126L16 2.82813L8 10.8281L0 2.82813Z" fill="#000A70" />
</svg>
</span>
</button>
<div class="acc-body">
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Saepe harum eaque quis, unde neque quo minima porro praesentium cum id.</p>
<p>Doloremque facere deserunt dolore minus repellat. Quas impedit nihil, deserunt a laboriosam animi ullam quidem earum commodi, rerum assumenda incidunt.</p>
<p>Quo nihil beatae pariatur. Porro vitae eius hic harum aliquam asperiores voluptatem assumenda, iure quae maiores quis possimus error itaque!</p>
</div>
</div>
<div class="panel">
<button aria-expanded="false" class="acc-trigger">
<span class="acc-title">
<h4>Question Two</h4>
<svg class="acc-icon" width="16" height="11" viewBox="0 0 16 11" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 2.82813L2 0.828126L8 6.82813L14 0.828126L16 2.82813L8 10.8281L0 2.82813Z" fill="#000A70" />
</svg>
</span>
</button>
<div class="acc-body">
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Saepe harum eaque quis, unde neque quo minima porro praesentium cum id.</p>
<p>Doloremque facere deserunt dolore minus repellat. Quas impedit nihil, deserunt a laboriosam animi ullam quidem earum commodi, rerum assumenda incidunt.</p>
<p>Quo nihil beatae pariatur. Porro vitae eius hic harum aliquam asperiores voluptatem assumenda, iure quae maiores quis possimus error itaque!</p>
</div>
</div>
</div>
</div>
Upvotes: 1