Skip to content

Instantly share code, notes, and snippets.

@stewartknapman
Last active January 5, 2023 12:06
Show Gist options
  • Save stewartknapman/72ad2e4a725d96fa1a4fc2ee3c46a01e to your computer and use it in GitHub Desktop.
Save stewartknapman/72ad2e4a725d96fa1a4fc2ee3c46a01e to your computer and use it in GitHub Desktop.
Basic accordion for Shopify product
{% comment %}
<!--
Liquid will output content, split on h3s like this:
<div class="accordian">
<h5><a href="#free-shipping" data-accordian-action>Free & Fast USA Shipping <span>+</span></a></h5>
<p id="free-shipping" data-accordian-target>All orders are shipped through USPS. We pride ourselves on fast delivery. Orders typically arrive within 2-5 business days. You will receive an email with tracking information when your order is ready to ship.</p>
<h5><a href="#international-shipping" data-accordian-action>International Shipping <span>+</span></a></h5>
<p id="international-shipping" data-accordian-target>International shipping rates vary based on item(s). Shipping rates can be seen on the checkout page. International orders typically arrive within 7-10 business days, but can vary with customs clearance in each country. </p>
</div>
-->
{% endcomment %}
<div class="accordian">
{% assign description_parts = product.description | split: '<h3>' %}
{% for part in description_parts %}
{% unless part == blank %}
{% assign part_parts = part | split: '</h3>' %}
{% assign heading_handle = part_parts.first | handle %}
<h5><a href="#{{ heading_handle }}" data-accordian-action>{{ part_parts.first }} <span>+</span></a></h5>
<p id="{{ heading_handle }}" data-accordian-target>{{ part_parts.last | remove: '<p>' | replace: '</p>','<br><br>' }}</p>
{% endunless %}
{% endfor %}
</div>
<script>
var lastClick;
var accordianActions = document.querySelectorAll('[data-accordian-action]');
var accordianTargets = document.querySelectorAll('[data-accordian-target]');
var hideTargets = function () {
for (var i = 0; i < accordianTargets.length; i++) {
var accordianTarget = accordianTargets[i];
accordianTarget.style.display = 'none';
}
};
var showTarget = function (targetSelector) {
var target = document.querySelector(targetSelector);
target.style.display = 'block';
};
hideTargets();
for (var i = 0; i < accordianActions.length; i++) {
var accordianAction = accordianActions[i];
accordianAction.addEventListener('click', function (e) {
e.preventDefault();
hideTargets();
if (lastClick !== e.currentTarget) {
showTarget(e.currentTarget.getAttribute('href'));
lastClick = e.currentTarget;
} else {
lastClick = null;
}
});
}
/* jQuery version of the above code.
$(document).on('click', '[data-accordian-action]', function (e) {
e.preventDefault();
$('[data-accordian-target]').hide();
if (lastClick !== e.currentTarget) {
$(e.currentTarget.getAttribute('href')).show();
lastClick = e.currentTarget;
} else {
lastClick = null;
}
});
*/
</script>
<style>
.accordian h5 {
padding-bottom: 5px;
border-bottom: 1px solid #f0f0f0;
}
.accordian h5 span {
float: right;
}
</style>
@yeehailey
Copy link

Currently, all the tabs are closed. How to show the first tab by default? Thanks!

@duncanbirtwistle
Copy link

Great solution and instructions, thank you. A few modifications to customise here.

@natashajoann
Copy link

Hey! This works great but is there a way of having the "+" change to a "-"?

@natashajoann
Copy link

Hey! This works great but is there a way of having the "+" change to a "-"?

Actually managed to figure this one out. I added a class of "accordion" to the

and added this to the JS before the </script> tag:

$(document).ready(function() {

  var acc = document.getElementsByClassName("accordion");
var i;

for (i = 0; i < acc.length; i++) {
  acc[i].addEventListener("click", function() {
    this.classList.toggle("active");
    var panel = this.nextElementSibling;
    if (panel.style.maxHeight) {
      panel.style.maxHeight = null;
    } else {
      panel.style.maxHeight = panel.scrollHeight + "px";
    }
  });
}

});

Then I removed the elements from the html and added this to the CSS instead:

.accordian a{
width:100%;
}

.accordian h5:after {
content: '\002B';
}

.active:after {
content: "\2212" !important;
color: blue;
}

@jschuler00
Copy link

jschuler00 commented Mar 17, 2021

I would like to change the + to a - click any one have code that works?

I tried natashas above and it didn't work for me.

@natashajoann
Copy link

Hey! This works great but is there a way of having the "+" change to a "-"?

Actually managed to figure this one out. I added a class of "accordion" to the

and added this to the JS before the </script> tag:

$(document).ready(function() {

  var acc = document.getElementsByClassName("accordion");
var i;

for (i = 0; i < acc.length; i++) {
  acc[i].addEventListener("click", function() {
    this.classList.toggle("active");
    var panel = this.nextElementSibling;
    if (panel.style.maxHeight) {
      panel.style.maxHeight = null;
    } else {
      panel.style.maxHeight = panel.scrollHeight + "px";
    }
  });
}

});

Then I removed the elements from the html and added this to the CSS instead:

.accordian a{
width:100%;
}

.accordian h5:after {
content: '\002B';
}

.active:after {
content: "\2212" !important;
color: blue;
}

To clarify, I added "accordion" to the

element:

@prixxxde
Copy link

Watch fork for change + to - while open.

@binayachaudharys
Copy link

Uncaught ReferenceError: $ is not defined
at ?oseid=VDdgWAsfb4QK8KkUErCEktbF:1234

` $(document).ready(function () {
var acc = document.getElementsByClassName('accordion');
var i;

for (i = 0; i < acc.length; i++) {
  acc[i].addEventListener('click', function () {
    this.classList.toggle('active');
    var panel = this.nextElementSibling;
    console.log('hello');
    if (panel.style.maxHeight) {
      panel.style.maxHeight = null;
    } else {
      panel.style.maxHeight = panel.scrollHeight + 'px';
    }
  });
}

}); `

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment