Frontend Development 13 min read

Implementing Expandable Content with Pure CSS Using :target and :checked

This article explains how to create a "show more" effect without JavaScript by leveraging CSS pseudo‑classes like :target and :checked, detailing the required HTML structure, CSS rules, code examples, and the advantages and drawbacks of each approach.

Ctrip Technology
Ctrip Technology
Ctrip Technology
Implementing Expandable Content with Pure CSS Using :target and :checked

Many websites hide extra content behind a "more" or "expand" link, traditionally using JavaScript to change the container height. The simplest JS method sets height: auto , but the author explores a pure‑CSS solution for developers who prefer not to write JS.

The author first examines CSS pseudo‑classes that provide limited interactivity, focusing on :target (used with anchor links) and :checked (used with checkboxes). Other pseudo‑classes such as :hover , :active , and :focus are mentioned but deemed unsuitable for this use case.

Using the :target Approach

The HTML structure places the expandable content inside a div with an id="more" , followed by a control block containing two links: one pointing to #more ("more") and another pointing to # ("shrink").

<div class="box" id="more">
    <p>...content to show...</p>
</div>
<div class="detail_ctrl">
    <a href="#more">更多</a>
<a href="#">缩小</a>
</div>

The accompanying CSS sets a fixed height for .box and hides overflow. When the target is activated, the rule #more:target { height: auto; } expands the box. Additional sibling selectors toggle the visibility of the two links.

body {font-size:20px;}
.box {height:2em; overflow:hidden; width:10em; margin-bottom:.5em; line-height:1em; border:1px solid #000;}
#more:target {height:auto;}
.detail_ctrl a {display:inline;}
.detail_ctrl a + a {display:none;}
#more:target + .detail_ctrl a {display:none;}
#more:target + .detail_ctrl a + a {display:inline;}

While functional, this method can cause page jumps, relies on an id that may clash with other scripts, and exposes the anchor in the URL.

Using the :checked Approach

Here a hidden checkbox controls the expansion. The HTML includes an input type="checkbox" id="more_c"> followed by the content box and a label for="more_c">更多 that acts as the toggle.

<input type="checkbox" id="more_c">
<div class="box">
    <p>...content to show...</p>
</div>
<label for="more_c">更多</label>

The CSS expands the box when the checkbox is checked and uses sibling selectors to change the label text via :after content, hide the original label, and style the label as a clickable element.

#more_c:checked + .box {height:auto;}
#more_c:checked ~ label[for="more_c"]:after {content:"闭合"; position:absolute; top:0; left:0; right:0; bottom:0; background:#fff; z-index:2;}
label {position:relative; cursor:pointer;}
#more_c {position:absolute; z-index:-1;}

To keep the checkbox invisible, it is positioned off‑screen and given opacity:0 . The author notes that this method keeps the URL clean and works without JavaScript, but it still introduces a form element into the markup.

Summary and Considerations

The author concludes that CSS should primarily handle presentation, not complex interaction, and that both :target and :checked solutions have trade‑offs regarding maintainability, cross‑team communication, and especially browser compatibility. While the techniques are clever, they may not be suitable for production code without careful evaluation.

frontendcsstargetexpandablecheckedno-JS
Ctrip Technology
Written by

Ctrip Technology

Official Ctrip Technology account, sharing and discussing growth.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.