Skip to content

Instantly share code, notes, and snippets.

@zeraphie
Last active July 17, 2017 13:12
Show Gist options
  • Save zeraphie/b483c3e7a8ea9ecd7f2c543855c35581 to your computer and use it in GitHub Desktop.
Save zeraphie/b483c3e7a8ea9ecd7f2c543855c35581 to your computer and use it in GitHub Desktop.
A really easy way of doing responsive accordions

Easy Accordions

This was my attempt at making a really simple accordion with minimalistic code, taking advantage of a combination of scss and javascript.

It utilizes the offsetHeight method to measure the height of all the elements inside it, even if the max-height is set to 0 on the containing element, and as such, is pretty agnostic about what's contained inside!

Here's a demo: https://codepen.io/zephyr/pen/VWNNdg

<div class="accordion">
<div class="accordion-opener">
<h2>The accordion title</h2>
</div>
<div class="accordion-content">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus aut dicta, dolor eaque incidunt ipsa magnam repellendus. Culpa ducimus eius error, esse necessitatibus nesciunt nostrum quae! Accusamus amet animi architecto aspernatur at autem, consectetur culpa dolores eligendi est ex incidunt ipsum iure magnam nam nemo nihil nulla officia quas quasi repellat reprehenderit sed sint sunt suscipit temporibus, veritatis voluptates! Eos.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus aut dicta, dolor eaque incidunt ipsa magnam repellendus. Culpa ducimus eius error, esse necessitatibus nesciunt nostrum quae! Accusamus amet animi architecto aspernatur at autem, consectetur culpa dolores eligendi est ex incidunt ipsum iure magnam nam nemo nihil nulla officia quas quasi repellat reprehenderit sed sint sunt suscipit temporibus, veritatis voluptates! Eos.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus aut dicta, dolor eaque incidunt ipsa magnam repellendus. Culpa ducimus eius error, esse necessitatibus nesciunt nostrum quae! Accusamus amet animi architecto aspernatur at autem, consectetur culpa dolores eligendi est ex incidunt ipsum iure magnam nam nemo nihil nulla officia quas quasi repellat reprehenderit sed sint sunt suscipit temporibus, veritatis voluptates! Eos.</p>
</div>
</div>
/*==============================================================================
Accordions!! - requires jQuery and ES6
==============================================================================*/
let accordions = $('.accordion');
if(!!accordions.length){
accordions.each(function(){
let accordion = $(this);
let opener = accordion.find('.accordion-opener');
let content = accordion.find('.accordion-content');
let timer;
// Toggle the opening :D
accordion.find('.accordion-opener').on('click', function(){
clearTimeout(timer);
// Have a quick calculation of the height of the elements... Even if
// the wrapper is max-height!
let height = Array.prototype.reduce.call(
content[0].childNodes,
(position, element) => {
// The 20 here is the bottom margin of the elements in this
// div.... not sure how to make this better element is all
// nodes, not necessarily just tags
// TODO: MAKE THIS BETTER.
return position + (element.offsetHeight || 0) + 20;
},
0
) + 'px';
// Always set the max height to animate properly!
content.css({
'max-height': height
});
if(!content.hasClass('active')){
// Default it to the initial height so it can remain responsive
timer = setTimeout(function(){
content.css({
'max-height': 'initial'
});
}, 310);
} else {
// Animate to nothing!
timer = setTimeout(function(){
content.css({
'max-height': 0
});
}, 10);
}
// Toggle the class so that the padding and opacity is animated via
// css
content.toggleClass('active');
});
});
}
.accordion {
position: relative;
border: 4px solid #F1F1EF;
.accordion-opener {
position: relative;
padding: 24px;
background: #fff;
text-transform: uppercase;
cursor: pointer;
transition: background 0.3s;
h2 {
margin: 0;
font-size: 20px;
font-weight: 300;
}
}
.accordion-content {
position: relative;
background: #F1F1EF;
overflow: hidden;
max-height: 0;
padding: 0 24px;
opacity: 0;
transition: max-height 0.3s, padding 0.3s, opacity 0.3s;
will-change: padding;
p:first-child {
margin-top: 0;
}
p:last-child {
margin-bottom: 0;
}
&.active {
padding-top: 24px;
padding-bottom: 24px;
opacity: 1;
}
}
+ .accordion {
margin-top: 16px;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment