A 'collapsible' is content whose visibility can be toggled. Here is an example:
This is the body of the collapsible. Its visibility can be toggled using the 'click me' button.
Here we will learn how to make such a collapsible without using JavaScript.
In this article, we'll look at how to make one.
Important update: This article talks about a hacky solution to
make a collapsible without using JavaScript.
I recently (September 2020) found a much simpler, cleaner and semantic solution
using the <details>
tag.
Skeleton¶
Let's first create the basic structure without collapsibility.
HTML:
<div class="collapsible">
<div class="collapsor-lbl"> Click me </div>
<div class="collapsible-content">
This is the body of the collapsible.
</div>
</div>
CSS (for beautification):
.collapsible {
max-width: 40em;
border: 1px solid black;
border-radius: 0.5rem;
}
.collapsor-lbl:hover {
background-color: rgba(0, 0, 0, 0.1);
}
.collapsor-lbl {
text-align: center;
padding: 0.5rem 1rem;
}
.collapsible-content {
padding: 0.5rem;
border-top: 1px solid black;
}
This is what the output looks like:
Collapsibility¶
To add collapsibility, we're going to use a checkbox. I read about it on the blog post 'Implementing A Pure CSS Collapsible' by alligator.io.
- A checkbox maintains state about whether it's checked or not. We can use that to maintain state about whether our collapsible has been clicked or not.
- We can use the CSS style
display:none
to make the checkbox disappear, but still retain its functionality. - We can use the CSS pseudo-selector
:checked
to select a checked checkbox. - We will make sure that
.collapsible-content
is a sibling of the checkbox. Then we can use the CSS sibling combinator '~
' to select it. When used together with:checked
on checkbox, we can select.collapsible-content
only when the checkbox is checked.
Change the HTML to this:
<div class="collapsible">
<input id="checkbox1" class="collapsor" type="checkbox" />
<label for="checkbox1" class="collapsor-lbl"> Click me </label>
<div class="collapsible-content">
This is the body of the collapsible.
</div>
</div>
Add this CSS:
.collapsor-lbl {
display: block;
}
.collapsor, .collapsible-content {
display: none;
}
.collapsor:checked ~ .collapsible-content {
display: block;
}
Output:
Accessibility¶
Web accessibility is the inclusive practice of ensuring there are no barriers that prevent interaction with, or access to websites, by people with disabilities.
I once had a mouse that sometimes stopped functioning, so I can feel a bit of the pain of users who cannot use a mouse. Also, some people like using the keyboard for navigation and it would be bad to force them to use a mouse.
I don't know much about web accessibility standards and what it takes for my websites to be fully accessible, but the least I can do is make my pages keyboard-navigable.
The blog post by alligator.io says how to make a collapsible using only CSS, but to make it accessible they had to use JavaScript. I, however, have a way of doing it without JavaScript.
When navigating a web page using the tab key, certain HTML elements have the potential of receiving focus.
This generally includes links (<a>
tags) and form elements (<input>
tags).
When an element receives focus, it gets the :focus
CSS pseudo-class.
Also, that element and all its descendants get the :focus-within
class.
We will therefore wrap .collapsible-content
within a <div>
.
We will make that <div>
capable of receiving focus via tab by setting the attribute tabindex
to "0"
.
Then whenever that div has the :focus-within
pseudo-class set,
we will set display: block
on .collapsible-content
.
Change the HTML to this:
<div class="collapsible">
<label for="checkbox2" class="collapsor-lbl"> Click me </label>
<div class="focus-capturer" tabindex="0">
<input id="checkbox2" class="collapsor" type="checkbox" />
<div class="collapsible-content">
<p>This is the body of the collapsible.<p>
<ul>
<li><a href="">link1</a></li>
<li><a href="">link2</a></li>
<li><a href="">link3</a></li>
</ul>
</div>
</div>
</div>
Add this CSS:
.focus-capturer:focus-within .collapsible-content {
display: block;
}
Output:
Try using the tab key to navigate all the 3 links in the collapsible. When the focus moves out of the collapsible, it closes (unless you had clicked on it to open it).