Reputation: 2166
I am following this code example found here to create a collapsible panel using css/html/javascript:
function toggleCollapsibleSectionWithAnimation() {
this.classList.toggle("collapsible-active");
var buttonId = this.id;
var sectionId = buttonId.replace("button","section");
var content = document.getElementById(sectionId);
if (content.style.maxHeight) {
content.style.maxHeight = null;
} else {
content.style.maxHeight = content.scrollHeight + "px";
}
}
/* Style the button that is used to open and close the collapsible content */
.collapsible {
background-color: transparent;
color: #444;
cursor: pointer;
width: auto;
border: none;
text-align: left;
outline: none;
font-size: 15px;
}
/* Add a background color to the button if it is clicked on (add the .active class with JS), and when you move the mouse over it (hover) */
.collapsible-active, .collapsible:hover {
text-decoration: underline;
}
/* Style the collapsible content. Note: hidden by default */
.collapsible-content {
max-height: 0;
padding: 10px;
overflow: hidden;
transition: max-height 0.2s ease-out;
}
/* Style the collapsible content. Note: shown by default */
.collapsible-content-shown-by-default {
max-height: 100%;
padding: 10px;
overflow: hidden;
transition: max-height 0.2s ease-out;
}
<button class="collapsible" id="collapsible-button-0" onclick="toggleCollapsibleSectionWithAnimation.call(this)"><b>Model</b> (show/hide)</button>
<div class="collapsible-content" id="collapsible-section-0">
<h1>
content
</h1>
</div>
This code works, by default the collapsible section will be hidden.
I wanted to reverse this so my panel is shown by default, but it should behave in the exact same way, clicking the collapsible button will toggle the section below open or closed.
Unsure on how to reverse the starting variables. When it starts hidden, we need to start with max-height of 0 on the content panel. In the javascript this is changed to content.scrollHeight to open the panel up.
Here is a JSfiddle example: https://jsfiddle.net/trbk5vwg/9/
In the JSfiddle, if you swap the div class between the "collapsible-content" and "collapsible-content-shown-by-default", you will see the toggle only works one way.
I was unsure how i would get the scrollHeight in css, and therefore unsure on how to initialize the maxHeight for the panel to be showed by default (100% didn't work).
Upvotes: 4
Views: 7772
Reputation: 304
Quick and easy solution:
Using the logic explained below (bottom of answer), we can solve the problem by simply adding an inline declaration of max-height to the "collapsible-content" div:
<div class="collapsible-content" id="collapsible-section-0" style="max-height: 100%">
Javascript Solution:
Working code is:
/* Style the button that is used to open and close the collapsible content */
.collapsible {
background-color: transparent;
color: #444;
cursor: pointer;
width: auto;
border: none;
text-align: left;
outline: none;
font-size: 15px;
}
/* Add a background color to the button if it is clicked on (add the .active class with JS), and when you move the mouse over it (hover) */
.collapsible-active, .collapsible:hover {
text-decoration: underline;
}
/* Style the collapsible content. Note: hidden by default */
.collapsible-content {
max-height: 100%;
padding: 10px;
overflow: hidden;
transition: max-height 0.2s ease-out;
}
/* Style the collapsible content. Note: shown by default */
.collapsible-content-shown-by-default {
max-height: 100%;
padding: 10px;
overflow: hidden;
transition: max-height 0.2s ease-out;
}
<script>
function toggleCollapsibleSectionWithAnimation() {
this.classList.toggle("collapsible-active");
var buttonId = this.id;
var sectionId = buttonId.replace("button","section");
var content = document.getElementById(sectionId);
var mHeight = window.getComputedStyle(content).maxHeight;
if (mHeight !== "0px"){
content.style.maxHeight = "0px";
} else {
content.style.maxHeight = "100%";
}
}</script>
<button class="collapsible" id="collapsible-button-0" onclick="toggleCollapsibleSectionWithAnimation.call(this)"><b>Model</b> (show/hide)</button>
<div class="collapsible-content" id="collapsible-section-0">
<h1>
content
</h1>
</div>
Why these work:
The reason you can't just change max-height to 100% in the css file: in your original JSFiddle, the first "if statement" when the button clicked is reading content.style.maxHeight
. .style
actually reads the inline css, which in the original case, meant it read maxHeight as null. When changing the external css (not inline) to 100%, the .style.maxHeight
function still reads maxHeight as null.
To fix this in html/css, we simply need to set the initial inline css to "max-height: 100%", thus the content.style.maxHeight
function will return the correct value.
To fix this in JS, we can use window.getComputedStyle(content).maxHeight
, which will read the computed style (including inline and external css). Because we cannot change the computed style directly, we can then edit the inline css to override the external css originally declared (max-height: 100%
). When the next "if statement" is called on the button click, the computed style will return the inline css.
Upvotes: 3
Reputation: 454
Try this
<script>
function toggleCollapsibleSectionWithAnimation() {
this.classList.toggle("collapsible-active");
var buttonId = this.id;
var sectionId = buttonId.replace("button","section");
var content = document.getElementById(sectionId);
var isDefaultMode = content.classList.contains('collapsible-content-shown-by-default');
if (isDefaultMode) {
content.classList.remove("collapsible-content-shown-by-default");
content.style.maxHeight = 0;
}
if (content.style.maxHeight) {
content.style.maxHeight = null;
} else {
content.style.maxHeight = content.scrollHeight + "px";
}
}</script>
<button class="collapsible collapsible-active" id="collapsible-button-0" onclick="toggleCollapsibleSectionWithAnimation.call(this)"><b>Model</b> (show/hide)</button>
<div class="collapsible-content collapsible-content-shown-by-default" id="collapsible-section-0">
<h1>
content
</h1>
</div>
I have set it as essentially in the mode of post click.
Upvotes: 1