しらべものドット宇宙HTMLコーダーが必死こいて〇〇〇を目指すブログ

jsでアコーディオン

       <details class="js-details">
<br>            <summary class="js-summary">
<br>                <span class="summary_inner">
<br>                    概要<span class="icon"></span>
<br>                </span>
<br>            </summary>
<br>            <div class="content js-content">
<br>                <div class="content_inner">折りたたまれている部分です。</div>
<br>            </div>
<br>        </details>
<br>        <details class="js-details">
<br>            <summary class="js-summary">
<br>                <span class="summary_inner">
<br>                    概要<span class="icon"></span>
<br>                </span>
<br>            </summary>
<br>            <div class="content js-content">
<br>                <div class="content_inner">折りたたまれている部分です。</div>
<br>            </div>
<br>        </details><br><script><br>'use strict';
<br>
<br>{
<br>    document.addEventListener('DOMContentLoaded', () => {
<br>        setAccordion();
<br>    });
<br>
<br>    const setAccordion = () => {
<br>        const details = document.querySelectorAll('.js-details');
<br>        const RUNNING_VALUE = 'running';
<br>        const IS_OPENED_CLASS = 'is-opened';
<br>
<br>        details.forEach(element => {
<br>            const summary = element.querySelector('.js-summary');
<br>            const content = element.querySelector('.js-content');
<br>
<br>            summary.addEventListener('click', event => {
<br>                event.preventDefault();
<br>
<br>                if (element.dataset.animStatus === RUNNING_VALUE) {
<br>                    return;
<br>                }
<br>
<br>                if (element.open) {
<br>                    element.classList.toggle(IS_OPENED_CLASS);
<br>
<br>                    const closingAnim = content.animate(
<br>                        closingAnimKeyframes(content),
<br>                        animTiming
<br>                    );
<br>
<br>                    element.dataset.animStatus = RUNNING_VALUE;
<br>
<br>                    closingAnim.onfinish = () => {
<br>                        element.removeAttribute('open');
<br>                        element.dataset.animStatus = '';
<br>                    };
<br>                } else {
<br>                    element.setAttribute('open', 'true');
<br>
<br>                    element.classList.toggle(IS_OPENED_CLASS);
<br>
<br>                    const openingAnim = content.animate(
<br>                        openingAnimKeyframes(content),
<br>                        animTiming
<br>                    );
<br>                    element.dataset.animStatus = RUNNING_VALUE;
<br>
<br>                    openingAnim.onfinish = () => {
<br>                        element.dataset.animStatus = '';
<br>                    };
<br>                }
<br>            });
<br>        });
<br>    };
<br>
<br>    const animTiming = {
<br>        duration: 400,
<br>        easing: 'ease-out',
<br>    };
<br>
<br>    // 閉じる
<br>    const closingAnimKeyframes = content => [
<br>        {
<br>            height: content.offsetHeight + 'px',
<br>            opacity: 1,
<br>        },
<br>        {
<br>            height: 0,
<br>            opacity: 0,
<br>        },
<br>    ];
<br>
<br>    // 開く
<br>    const openingAnimKeyframes = content => [
<br>        {
<br>            height: 0,
<br>            opacity: 0,
<br>        },
<br>        {
<br>            height: content.offsetHeight + 'px',
<br>            opacity: 1,
<br>        },
<br>    ];
<br>}
<br></script><br><style><br>summary {
<br>    display: block;
<br>}
<br>
<br>summary::-webkit-details-marker {
<br>    display: none;
<br>}
<br>
<br>.summary_inner {
<br>    cursor: pointer;
<br>    display: flex;
<br>    flex-direction: row;
<br>    justify-content: space-between;
<br>    align-items: center;
<br>    padding: 16px 24px;
<br>    border: 1px solid #d2beff;
<br>    font-weight: bold;
<br>    color: #002255;
<br>}
<br>
<br>.icon {
<br>    display: block;
<br>    position: relative;
<br>    width: 24px;
<br>    margin-left: 6px;
<br>    flex-shrink: 0;
<br>    transform-origin: center 43%;
<br>    transition: transform 0.4s;
<br>}
<br>
<br>details.is-opened .icon {
<br>    transform: rotate(180deg);
<br>}
<br>
<br>.icon::before,
<br>.icon::after {
<br>    content: '';
<br>    position: absolute;
<br>    display: block;
<br>    width: 15px;
<br>    height: 3px;
<br>    background-color: #7050ff;
<br>}
<br>
<br>.icon::before {
<br>    left: 0;
<br>    transform: rotate(45deg);
<br>}
<br>
<br>.icon::after {
<br>    right: 0;
<br>    transform: rotate(-45deg);
<br>}
<br>
<br>.content {
<br>    overflow: hidden;
<br>    background-color: #f0f2ff;
<br>}
<br>
<br>.content_inner {
<br>    padding: 24px 48px;
<br>    display: flex;
<br>    flex-direction: column;
<br>    gap: 16px;
<br>}
<br></style>