How to keep pure-HTML-&-CSS collapsible panels open when another one is opened?


Tags: html,css

Problem :

I have the following collapsible panels written in pure HTML and CSS:

           <style>
                .collapse-panel {
                    display: block;
                    vertical-align: top;
                    height: auto !important;
                }

                .collapse-panel a {
                    font-family: "Lucida Console", Monaco, monospace;
                    font-size: 16pt;
                    font-weight: bolder;
                    text-decoration: none;
                }

                .collapse-panel-content {
                    display: none;
                    height: auto;
                }

                .show {
                    display: none;
                }

                .hide:target + .show {
                    display: inline;
                }

                .hide:target {
                    display: none;
                }

                .hide:target ~ .collapse-panel-content {
                    display: inline;
                }
            </style>
        <div>
            <div>
                <div class="collapse-panel">
                    <a href="#hide1" class="hide" id="hide1">+</a>
                    <a href="#show1" class="show" id="show1">-</a>
                    <span>Details A</span>
                    <div class="collapse-panel-content">
                        <div>Some details</div>
                    </div>
                </div>
            </div>
        </div>

        <div>
            <div>
                <div class="collapse-panel">
                    <a href="#hide2" class="hide" id="hide2">+</a>
                    <a href="#show2" class="show" id="show2">-</a>
                    <span>Details B</span>
                    <div class="collapse-panel-content">
                        <div>Some other details</div>
                    </div>
                </div>
            </div>
        </div>

How can I adapt the code so that the other collapsible panels are not closed when one is opened?



Solution :

I don't think you can, using :target.

From w3schools:

The :target selector can be used to style the current active target element.

And that's exactly what you are doing. Now, can you think of a way to have more than one :active element at a time? Because I don't know any.

But that doesn't mean you can't achieve this with CSS alone. You just need to be creative. Use elements that are capable of natively storing the current element state while exposing it to CSS selectors. For example, checkboxes:

[id^="collapseCheck-"]{
  display: none;
}
label[for^="collapseCheck-"] {
  display: block;
}
label[for^="collapseCheck-"]:before {
  content: "+";
  width: 1rem;
  text-align: center;
  display: inline-block;
}

[id^="collapsePanel-"] {
  display: none;
  padding: 1rem;
}

#collapseCheck-1:checked ~ label[for="collapseCheck-1"]:before {content: "-"}
#collapseCheck-2:checked ~ label[for="collapseCheck-2"]:before {content: "-"}
#collapseCheck-3:checked ~ label[for="collapseCheck-3"]:before {content: "-"}
/*...*/

#collapseCheck-1:checked ~ #collapsePanel-1 {display: block;}
#collapseCheck-2:checked ~ #collapsePanel-2 {display: block;}
#collapseCheck-3:checked ~ #collapsePanel-3 {display: block;}
/*...*/
<input type="checkbox" id="collapseCheck-1">
<input type="checkbox" id="collapseCheck-2">
<input type="checkbox" id="collapseCheck-3">
<!-- ... -->


<label for="collapseCheck-1">Details A</label>
  <div id="collapsePanel-1">
    <div>Some details</div>
  </div>

<label for="collapseCheck-2">Details B</label>
  <div id="collapsePanel-2">
    <div>Some details</div>
  </div>

<label for="collapseCheck-3">Details C</label>
  <div id="collapsePanel-3">
    <div>Some details</div>
  </div>

<!-- ... -->

You can generate the required list of CSS selectors using a foreach on server side, if your elements are dynamic. The limitation here is that all your control checkboxes need to be placed at the same level as the list of items (or you need to adjust the selector, of course) and they need to be placed before your elements (CSS only looks ahead, never behind).

This solution can be easily switched to "close all the other containers" by switching the type of control <input>s to radios sharing the same name attribute.


Please note this is a proof of concept. In order to make it usable in a production level environment, one should also add aria attributes to it, so it would become accessible and usable by all devices, not only screen types.


    CSS Howto..

    How to make display:flex work for responsiveness - Bootstrap?

    How to make HTML table cells expand horizontally beyond end of page?

    How can I add block colour to the CSS of my list?

    How to use bootstrap to hide one of div when zoom browser windows size smaller

    How can I make images stack on top of each other as web page scales down?

    Show/hide stuff according to checkboxes using CSS: Why this code won´t work?

    HTML/CSS - How do I make divs to size according to their contents?

    How to make CSS triangles (with borders) compatible across browsers

    How to highlight a window in JavaFX?

    How to add another two full width sections below (CSS)

    How to remove “pictureframe” in Internet Explorer?

    How to achieve two multi-step forms, one form on each side using CSS transformation

    How to update the attribute while overriding a style defined in css?

    how to make divs adjust to dynamic screen resolutions?

    how to apply css property to my first div class only

    how to give css for arranging label, textbox and text area side by side in the same line

    How to keep banner animations running while changing webpages [closed]

    How do I make an image shrink and grow according to re-sizing the browser.

    How to move some text down in a li tag?

    How do I 'freeze' a block level element?

    How do I get text to go in the middle of a div? [duplicate]

    How can I force a css flex child to be the only on its row?

    How to reduce div size in CSS using twitter bootstrap?

    CSS HTML : stumped on how to center this piece of text

    how to change text color hover

    How to override a CSS class within a content div

    How can I set a border in alignment with other borders

    How to make 3 vertical dots using CSS?

    How to link after the CSS-Animation?

    How do I organize imports in Compass/Blueprint?