Cengiz
Cengiz

Reputation: 1060

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

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?

Upvotes: 3

Views: 750

Answers (3)

tao
tao

Reputation: 90038

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.

Upvotes: 4

Raeesh Alam
Raeesh Alam

Reputation: 3480

You can do this via input type="checkbox" when checked. This will work on every browsers.

.collapse-panel{
			border: 1px solid #ccc;
			list-style-type: none;
			padding-left: 0px;
			font-family: "Arial";
		}
		.collapse-panel li{
			position: relative;
			margin-bottom: 1px;
		}
		.collapse-panel li:last-child{margin-bottom: 0px;}
		.collapse-panel li label{
			padding: 7px 7px 7px 32px;
			background: #eee;
			display: block;
		}
		.collapse-panel li label:hover{
			background: #ddd;
		}
		.collapse-panel li input{
			position: absolute;
			top: 0px;
			visibility: hidden;
		}
		.collapse-panel li span{
			position: absolute;
			width: 15px;
			height: 15px;
			border:1px solid #999;
			border-radius: 50%;
			z-index: 2;
			top: 9px;
			left: 7px;
		}
		.collapse-panel li span:before{
			content: '+';
			position: absolute;
			top: -1px;
			left: 3px;
			line-height: 15px;
			font-size: 15px;
			color: green;
			font-weight: bold;
		}
		.collapse-panel li p{
			padding: 7px;
			font-size: 14px;
			color: #555;
			margin: 0px;
			display: none;
		}
		.collapse-panel li input:checked ~ p{
			display: block;
		}
		.collapse-panel li input:checked ~ span:before{
			content: '-';
			position: absolute;
			top: -2px;
			left: 5px;
			color: red;
		}
<ul class="collapse-panel">
	<li>
		<label for="col1">Details A</label>
		<input type="checkbox" name="" id="col1"><span></span>
		<p>
			Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
			tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
			quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
			consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
			cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
			proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
		</p>
	</li>
	<li>
		<label for="col2">Details B</label>
		<input type="checkbox" name="" id="col2"><span></span>
		<p>
			Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
			tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
			quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
			consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
			cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
			proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
		</p>
	</li>
	<li>
		<label for="col3">Details C</label>
		<input type="checkbox" name="" id="col3"><span></span>
		<p>
			Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
			tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
			quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
			consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
			cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
			proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
		</p>
	</li>
	<li>
		<label for="col4">Details D</label>
		<input type="checkbox" name="" id="col4"><span></span>
		<p>
			Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
			tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
			quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
			consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
			cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
			proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
		</p>
	</li>
</ul>

Upvotes: 2

t_dom93
t_dom93

Reputation: 11466

Very easy you can do that with tags details and summary. But before you go any further, you should know that currently browsers IE, Edge, Opera doesn't support that elements ( Mozzila from version 49 ). Check this link : http://caniuse.com/#feat=details

The <details> tag can be used to create an interactive widget that the user can open and close. Any sort of content can be put inside the tag.

The <summary> tag defines a visible heading for the element. The heading can be clicked to view/hide the details.

Your code now:

summary::-webkit-details-marker {
  display: none
}

summary:after {	  
  float: left; 	
  width: 20px;
  content: "+";
}

details[open] summary:after {
  content: "-";
}
<article>
  <details>
    <summary>details A</summary>        		      			
    <span>Some content</span> 		        
  </details>
</article>

<article>
  <details>
    <summary>details B</summary>       			
    <span>Some other content</span>
  </details>
</article>

Upvotes: 3

Related Questions