Reputation: 3537
I'm trying to code a responsive button which can be placed multiple times in the same line, showing its content always below the line containing the button.
In the snippet there is a working code, but it has a small flaw: since the pseudo-class focus
is used, once the button is opened it's enough to click anywhere on the screen to close it.
The usual behaviour for a button is that to close it you have to click on it, so is it possibile to get this behaviour also for this one?
I used other pseudo-classes but without success, I guess only a javascript can do the job.
.container {
position: relative;
margin: 2em;
}
.details {
display: none;
}
.collapsible:focus {
margin-bottom: 1.5em;
pointer-events: none;
}
.collapsible:focus + .details
{
display: block;
margin-top: -1.15em;
position: absolute;
left: 0;
right: 0;
background: yellow;
}
<div class=container>
You can <button class="collapsible">place</button><span class=details>yes</span> more than <button class="collapsible">one</button><span class=details>nice</span> per line, they are responsive and the content is always shown just <button class="collapsible">below</button><span class=details>cool</span> the line containing the button.
But once opened, you can close it with a click <button class="collapsible">everywhere</button><span class=details>not good</span> on the screen
</div>
<script type="text/javascript">
var coll = document.getElementsByClassName("collapsible");
var i;
for (i = 0; i < coll.length; i++) {
coll[i].addEventListener("click", function() {
this.classList.toggle("active");
var content = this.parentElement.nextElementSibling;
if (content.style.maxHeight){
content.style.maxHeight = null;
} else {
content.style.maxHeight = content.scrollHeight + "px";
}
});
}
</script>
Upvotes: 0
Views: 76
Reputation: 12112
Implementation of the idea was a bit more complicated so I'll just answer.
This uses an old trick whereby a label, associated with a hidden checkbox, is used as the click target. Since clicking on a label checks or unchecks the checkbox, and there is a pseudo-class for the checked state of the checkbox, we can use that to persist the state of our styles. Credit to TylerH for his answer to the similar question Can I have an onclick effect in CSS?.
I've implemented it here by using a partial attribute selector, so in this example any checkboxes have to have an ID that begins with "demo". The checkboxes do have to have an ID for the for
attribute of the label
to hook onto.
.container {
position: relative;
margin: 2em;
}
.collapsible:focus {
margin-bottom: 1.5em;
pointer-events: none;
}
label {
display: inline-block;
background: lightgrey;
}
[id^="demo"] {
display: none;
}
/* details that are next to labels that are next to unchecked checkboxes are hidden */
[id^="demo"]:not(:checked)+label+.details {
display: none;
}
/* details that are next to labels that are next to checked checkboxes are displayed */
[id^="demo"]:checked+label+.details {
display: block;
position: absolute;
left: 0;
right: 0;
background: yellow;
}
/* labels that are next to unchecked checkboxes have a different color
so you can track which ones are "on" */
[id^="demo"]:checked+label {
background: blue;
color: white;
}
<div class=container>
You can <input type="checkbox" id="demo01" /><label for="demo01" >place</label><span class=details>yes</span> more than <input type="checkbox" id="demo02" /><label for="demo02">one</label><span class=details>nice</span> per line, they are responsive and the content is always shown just <input type="checkbox" id="demo03" /><label for="demo03">below</label><span class=details>cool</span> the line containing the button. But once opened, you can close
it with a click <input type="checkbox" id="demo04" /><label for="demo04">everywhere</label><span class=details>not good</span> on the screen
</div>
Upvotes: 1