Pure CSS disclosure elements

Create an accordion-style disclosure without JavaScript

This technique, similar to my tabbed interface, uses checkboxes to show or hide other elements on the page. The difference between this version and a javaScript version is that disclosed elements must be explicitly opened or closed by the user. In some cases, it makes sense to let the user choose which items they want to see. In others, it makes sense to only show one element's contents at a time. In that case, the JavaScript solution is a better choice.

Disclosure Example

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Reprehenderit hic adipisci id, sit, nulla placeat harum iure enim! Quia amet pariatur illum a veritatis doloremque corporis possimus, voluptates dicta magnam!

Robusta arabica black steamed cream aroma cappuccino beans kopi french. Milk iced rich go as kopi a pot irish. Shot strong milk turkish origin con saucer pot au instant cultivar et carajillo. Affogato espresso go mug cappuccino fair latte doppio lait americano decaffeinated bar seasonal percolator au. Au con cream chicory barista caramelization instant flavour affogato café id mountain.

Froth brewed skinny dripper black cinnamon single siphon latte espresso. Mazagran irish con medium aftertaste qui variety foam robusta brewed saucer grinder frappuccino siphon fair. Macchiato con body qui con mountain whipped mug milk cup. Go cup roast sweet lungo con caffeine cappuccino single qui blue. And panna half au spice steamed aromatic white and.

Sugar froth grounds kopi spice trade dark body ut that. Robust aged eu redeye body lait au sit espresso roast cream skinny aromatic. Aromatic shop coffee mocha aromatic so sweet cup at black café americano carajillo latte. Et trade percolator black galão aroma steamed doppio. Acerbic mug milk viennese mug breve turkish as bar froth coffee filter.

Au steamed as carajillo medium trifecta ristretto single espresso trade mazagran qui. Doppio cup sit robusta trade steamed mocha dripper flavour cortado spice body latte. Fair kopi id go latte trade sit skinny aroma single milk at irish. Affogato organic espresso au mocha single seasonal con caffeine bar go cinnamon organic grounds mazagran. Shot affogato dripper medium and whipped brewed affogato turkish pot coffee dark.

Aftertaste irish instant luwak coffee extra galão french cortado sweet. Turkish roast aromatic sugar espresso aromatic affogato café cup bar spice turkish lait single acerbic. Cinnamon dripper steamed skinny mazagran brewed skinny rich bar grinder. Rich steamed organic ristretto robust trifecta percolator barista a sit. Affogato variety foam trifecta redeye irish body white pumpkin barista.

Code

<input type="checkbox" name="ex1" id="ex1" class="disclosure">
<label for="ex1"> this example</label>
<div class="disclosure">
    ---content ---
</div>
input.disclosure {
    display: none;
}

input.disclosure + label {
    font-size: .8em;
    cursor: pointer;
    display: inline-block;
}

input.disclosure + label::before {
    content: 'Show';
}

input.disclosure:checked + label::before {
    content: 'Hide';
}

input.disclosure + label::after {
    content:'';
    width: .5em;
    height: .5em;
    border: 1px solid #444;
    border-left: none;
    border-bottom: none;
    position: relative;
    display: inline-block;
    right: -.5em;
    top: -.15em;
    transform: rotate(45deg);
    transition: transform .3s;
}

input.disclosure:checked + label::after{
    transform: rotate(135deg);
}

input.disclosure + label + div.disclosure {
    max-height: 0;
    overflow: hidden;
    display: grid;
    opacity: 0;

    transition: all .4s;
}

input.disclosure:checked + label + div.disclosure {
    max-height: 100vh;
    opacity: 1;
}

The concept is pretty simple: hide the checkbox, and use the label to trigger whether the checkbox is checked or not. Depending on the checked state of the checkbox, show or hide the content. Then, add a little css transition so the content grows and fades in when shown, and fades out and shrinks on hide.

I'm using a pseudo-element ::before the label to change the wording from "Show" (line 12) to "Hide" (line 16), and another pseudo-element ::after for the disclosure triangle (line 19).

The secret to growing and shrinking the content is by using overflow: hidden in combination with max-height. Setting height to 0 to hide the content works, but the browser needs a specified height for the element to use on a transition. Using max-height is a great workaround. Setting max-height: 100vh will probably work in most cases, unless there's a lot of content that's being hidden, and it's being viewed on a smaller screen like a phone or tablet. In that case, just increasing the max-height will probably work just fine.