ACF Accessible Accordion Query

Adaptiert von: https://codepen.io/Webactually/pen/wvNmMq

  • JQuery in Vanilla JS umgewandelt
  • JS und CSS angepasst, für Slide Animation when Accordion Panel geöffnet
  • Eingebunden in WP Query -> Code am Ende
HTML
<div class="accordion">
    <div class="accordion-item">
        <h3 class="panel-title">ACCORDION TITEL</h3>
        <div class="panel-content">ACCORDION INHALT</div>
    </div>
</div>
CSS
.panel-title {
  margin: 0;
}

.panel-title a {
  border-bottom: none;
  color: #292929;
  display: block;
  padding: 1.25em 0;
  position: relative;
  text-decoration: none;
  transition: color 200ms ease 0s;
  width: 100%;
}

.panel-title a .icon {
  color: #9e9e9e;
  position: absolute;
  right: 0;
  transition: all 200ms ease 0s;
}

.panel-title a:hover,
.panel-title a:focus {
  color: #37474f;
}

.panel-title a:hover .icon,
.panel-title a:focus .icon {
  color: #ec407a;
}

.panel-title a.active {
  color: #37474f;
}

.panel-title a.active .icon {
  color: #ec407a;
  transform: rotate(45deg);
}

.accordion {
  border-bottom: 1px solid #ececec;
  margin: 2em 0;
}

.accordion .panel-title a {
  border-top: 1px solid #ececec;
}

[id^="panel-"] {
  padding-bottom: 2em;
}

.panel-content {
  max-height: 0; /* standardmässig versteckt */
  overflow: hidden;
  transition: max-height 0.3s ease, padding 0.3s ease;
  padding: 0; /* standardmässig kein padding */
}

.panel-content[aria-hidden="false"] {
  max-height: 1000px; /* maximaler wert, wenn accordion content geöffnet */
  padding: 0 0 24px 0; /* füge padding hinzu, wenn geöffnet */
}
JavaScript
// Hiding the panel content. If JS is inactive, content will be displayed.
document.querySelectorAll('.panel-content').forEach(panel => {
    panel.style.maxHeight = '0'; // Initially hidden
    panel.setAttribute('aria-hidden', 'true');
    panel.style.overflow = 'hidden'; // Hide overflowing content
    panel.style.transition = 'max-height 0.3s ease, padding 0.3s ease'; // Smooth transition
    panel.style.padding = '0'; // No padding initially
});


// Update the markup of accordion container
document.querySelectorAll('.accordion').forEach(accordion => {
    accordion.setAttribute('role', 'tablist');
    accordion.setAttribute('multiselectable', 'true');
});

// Adding ID, aria-labelledby, role, and aria-labelledby attributes to panel content
document.querySelectorAll('.panel-content').forEach((panel, index) => {
    const panelId = `panel-${index}`;
    const controlId = `control-panel-${index}`;
    panel.setAttribute('id', panelId);
    panel.setAttribute('aria-labelledby', controlId);
    panel.setAttribute('role', 'tabpanel');
});

// Wrapping panel title content with a <a href="">
document.querySelectorAll('.panel-title').forEach((title, index) => {
    const targetId = title.nextElementSibling.id; // Identify the next sibling panel content
    const link = document.createElement('a');
    link.setAttribute('href', `#${targetId}`);
    link.setAttribute('aria-expanded', 'false');
    link.setAttribute('aria-controls', targetId);
    link.setAttribute('id', `control-${targetId}`);
    link.innerHTML = title.innerHTML + '<span class="icon">+</span>'; // Include optional icon
    title.innerHTML = ''; // Clear the title content
    title.appendChild(link); // Append the link to the title
});

// Adding click event for toggling
document.querySelectorAll('.panel-title a').forEach(link => {
    link.addEventListener('click', function (e) {
        e.preventDefault();

        const panelContent = this.parentElement.nextElementSibling;
        const isExpanded = this.getAttribute('aria-expanded') === 'true';

        if (!isExpanded) {
            // Accordion effect: Close all other panels in the same container
            const accordion = this.closest('.accordion');
            accordion.querySelectorAll('[aria-expanded="true"]').forEach(openLink => {
                openLink.setAttribute('aria-expanded', 'false');
                openLink.classList.remove('active');
                const openPanel = openLink.parentElement.nextElementSibling;
                openPanel.setAttribute('aria-hidden', 'true');
                openPanel.style.maxHeight = '0';
                openPanel.style.padding = '0';
            });

            // Open the current panel
            this.setAttribute('aria-expanded', 'true');
            this.classList.add('active');
            panelContent.setAttribute('aria-hidden', 'false');
            panelContent.style.maxHeight = panelContent.scrollHeight + 'px'; // Dynamically set height
            panelContent.style.padding = '0 0 24px 0'; // Restore padding
        } else {
            // Close the current panel
            this.setAttribute('aria-expanded', 'false');
            this.classList.remove('active');
            panelContent.setAttribute('aria-hidden', 'true');
            panelContent.style.maxHeight = '0';
            panelContent.style.padding = '0'; // Remove padding
        }
    });
});

Falls du das via WP Query einbinden willst:

PHP
<?php
// Query for posts in the 'allgemein' category
$args = array(
    'post_type' => 'post',
    'posts_per_page' => 10,
    'orderby' => 'menu_order',
    'order' => 'DESC',
    'category_name' => 'allgemein',
);

$query = new WP_Query($args);

if ($query->have_posts()) : ?>
    <div class="accordion">
        <?php while ($query->have_posts()) : $query->the_post(); ?>
            <div class="accordion-item">
                <h3 class="panel-title"><?php the_title(); ?></h3>
                <div class="panel-content">
                    <?php the_content(); ?>
                </div>
            </div>
        <?php endwhile; ?>
    </div>
    <?php
    // Reset post data
    wp_reset_postdata();
else :
    echo '<p>No posts found in the Allgemein category.</p>';
endif;
?>