Toggling element visibility in CSS

Sometimes you'll want items hidden until a particular element is clicked, such as a side pop-out, or a "click here to expand this section" option - and think that JavaScript is the only way to handle that kind of situation. Naturally, there's another way:

Lorem ipsum dolor sit amet, consectetur adipiscing 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.

The pain itself is the love of the pain, the main ecological problems, but I give this kind of time to fall down, so that some great pain and pain. In order that for the most part, any one of us will come to the exercise of any kind of employment except to take advantage of the objectives from it. But the pain in the film is irure to condemn, in pleasure it wants to escape from the pain of being cillum in pain, no result. They are the exceptions the blinds yearn for, they do not see, they are the ones who abandon their responsibilities to the fault that is soothing the soul's hardships.

In the above example, we make use of a hidden checkbox element, combined with a clickable label and the CSS selector :checked. We tie the label to the checkbox, and have the toggleable element be directly after the checkbox, to ensure that we can use the CSS "+" selector to reference that specific element:

p.border { padding: 0.5em; border: 1px solid #333333; }
label.expand { display: inline-block; padding: 0.5em; border: 1px solid #333333; cursor: pointer; }
input#expand1 { display: none; visibility: hidden; }
input#expand1 + p { display: none; margin-top: 4px; }
input#expand1:checked + p { display: block; }
<p class="border">First paragraph</p>

<label for="expand" class="expand">View English translation</label>
<input type="checkbox" name="expand" value="" id="expand" />

<p class="border">Second paragraph</p>

Expanding the concept

Using this method, more options are available, including animations:

Peter Piper picked a pick of pickled peppers

If Peter Piper picked a pick of pickled peppers, where's the peck of pickled peppers Peter Piper picked?

In this example, rather than having the second paragraph hidden, we're setting the height to zero, turning the border invisible (simply turning the border off and on looks far more out of place; trust me) and doing the same to the text content. Once toggled, the border and text are returned to their default colours, and a new height is set. The CSS transition property allows for a smooth change between the two states, making it look more natural.

There is a downside to this method - the transition property does not apply to properties that have no fixed value. This means that if we were to set the height of the revealed element to auto, the transition would simply not apply to the height, and while the border and text will fade in, the height will simply snap in, ruining the transition. This makes life difficult if you're revealing content of varying size, and the only real workaround to this is JavaScript, which can record the natural size of an element and return this later upon clicking the "reveal" label.

Side-popouts using this method

Lorem ipsum dolor sit amet, consectetur adipiscing 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.

To the left is an example of a popout - click the tab and it pops out over the top of the page, and pops back again when clicked a second time. This uses the same principles as previously shown, albeit with a more complex structure and style attached:

div.test_container { position: relative; }
div.popout_left { position: fixed; top: 5em; left: 0; z-index: 100; }

div.popout_left > input { display: none; visibility: hidden; }
div.popout_left > input + div { z-index: 0; position: absolute; top: 0; left: calc(-17em - 12px); width: 20em; height: 20em; transition: left 0.5s; }
div.popout_left > input + div > label { z-index: 1; position: absolute; top: 0; right: calc(-8em + 8px); line-height: 1em; padding: 8px 1em; border: 1px solid #333333; border-bottom-color: #FFFFFF; border-radius: 0.5em 0.5em 0 0; white-space: nowrap; font-weight: bold; background-color: #FFFFFF; cursor: pointer; user-select: none; transform: rotate(90deg); transform-origin: 0 0; }
div.popout_left > input + div > div { margin: 0 calc(2em + 2px) 0 0; padding: 1em; border: 1px solid #333333; border-left: none; border-radius: 0 0 0.5em 0; overflow: auto; background-color: #FFFFFF; }

div.popout_left > input:checked + div { left: 0; }
<div class="test_container">
	<div class="popout_left">
		<input type="checkbox" name="popout_left" value="" id="popout_left" />
		<div>
			<label for="popout_left">Pop me out</label>
			<div>Popout content</div>
		</div>
	</div>
</div>

The test_container div shown here serves only as an anchor point for the top of the popout - if the popout will be in a fixed position on the page, this element can be omitted.