Skip to content

Instantly share code, notes, and snippets.

@Tugzrida
Last active April 20, 2020 11:41
Show Gist options
  • Save Tugzrida/b7fdafb687799ddbfe9a9dd1b67d20c6 to your computer and use it in GitHub Desktop.
Save Tugzrida/b7fdafb687799ddbfe9a9dd1b67d20c6 to your computer and use it in GitHub Desktop.
A tiny independent JS library for easily making collapsible sections.
/* uCollapse v0.2 Created by Tugzrida(https://gist.github.com/Tugzrida) */
.ucollapsible {
overflow: hidden;
transition: height 0.3s ease-in-out;
}
.ucollapsible.ucollapsed {
height: 0px;
}
.ucollapse-btn {
background: none;
border: 0;
border-bottom: 1px solid #777;
outline: 0;
width: 100%;
display: block;
text-align: left;
color: inherit;
font-size: 1em;
cursor: pointer;
padding: 0.5rem 0.75rem;
margin: 1rem 0;
}
.ucollapse-btn::after {
content: "\25b2";
float: right;
transition: transform 0.3s ease-in-out;
}
.ucollapse-btn.ucollapsed::after {
transform: rotate(180deg);
}
<link href="uCollapse.min.css" type="text/css" rel="stylesheet">
Any element can act as a control by having a data-trigger="ucollapse" attribute and a data-target attribute referencing the collapsible section by standard CSS selector.
<br><br>
The CSS includes styling for a full-width style control with the class "ucollapse-btn":
<button data-trigger="ucollapse" data-target="#collapse1" class="ucollapse-btn ucollapsed">Here is a button!</button>
<div id="collapse1" class="ucollapsible ucollapsed">
Here is some collapsible content! It's just a div with a class of "ucollapsible", and optionally "ucollapsed" if it should start collapsed.
<br>
If you add "ucollapsed" to the section, you should also add it to the button so the arrow is correctly oriented.
</div>
<script src="uCollapse.min.js" type="text/javascript"></script>
// uCollapse v0.2 Created by Tugzrida(https://gist.github.com/Tugzrida)
// A tiny independent JS library for easily making collapsible sections.
// Supports multiple buttons per collapsible section, and multiple sections
// per button(ie with a class for data-target). Synchronisation of the collapsed
// buttons and sections may not be ideal in some 'multiple' cases. There's
// no programmatic way to expand/collapse, but that shouldn't be too hard
// to add if necessary.
document.querySelectorAll("[data-trigger=ucollapse]").forEach(function(btn) {
// Listen for clicks on any data-trigger=ucollapse element.
btn.addEventListener("click", function(e) {
// Find all target elements.
document.querySelectorAll(btn.getAttribute("data-target")).forEach(function(target) {
if (target.classList.contains("ucollapsed")) {
// Expand the target. First set the full height.
target.style.height = target.scrollHeight + "px";
btn.classList.remove("ucollapsed");
target.addEventListener("transitionend", function(e) {
// Then after the expand has finished, return to auto sizing so the target is responsive.
target.classList.remove("ucollapsed");
target.style.height = null;
}, {once: true});
} else {
// Collapse the target
requestAnimationFrame(function() {
// First set the rendered height of the target, so we're not transitioning from auto.
target.style.height = target.scrollHeight + "px";
requestAnimationFrame(function() {
// Then set the height to 0.
target.style.height = "0px";
btn.classList.add("ucollapsed");
target.classList.add("ucollapsed");
});
});
}
});
});
});
/* uCollapse v0.2 Created by Tugzrida(https://gist.github.com/Tugzrida) */
.ucollapsible{overflow:hidden;transition:height .3s ease-in-out}.ucollapsible.ucollapsed{height:0}.ucollapse-btn{background:0 0;border:0;border-bottom:1px solid #777;outline:0;width:100%;display:block;text-align:left;color:inherit;font-size:1em;cursor:pointer;padding:.5rem .75rem;margin:1rem 0}.ucollapse-btn::after{content:"\25b2";float:right;transition:transform .3s ease-in-out}.ucollapse-btn.ucollapsed::after{transform:rotate(180deg)}
// uCollapse v0.2 Created by Tugzrida(https://gist.github.com/Tugzrida)
document.querySelectorAll("[data-trigger=ucollapse]").forEach(function(e){e.addEventListener("click",function(t){document.querySelectorAll(e.getAttribute("data-target")).forEach(function(t){t.classList.contains("ucollapsed")?(t.style.height=t.scrollHeight+"px",e.classList.remove("ucollapsed"),t.addEventListener("transitionend",function(e){t.classList.remove("ucollapsed"),t.style.height=null},{once:!0})):requestAnimationFrame(function(){t.style.height=t.scrollHeight+"px",requestAnimationFrame(function(){t.style.height="0px",e.classList.add("ucollapsed"),t.classList.add("ucollapsed")})})})})});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment