Can text be hidden and shown using just CSS (no JavaScript code)? [closed]

Solution 1:

There’s the <details> element, which isn’t yet built into Edge:

<details>
  <summary>more <!-- a bad summary --></summary>
  <p>Some content</p>
</details>

I’m not sure how hard it is to style consistently across browsers.

There’s a common checkbox hack (where the checkbox can be hidden and the label can be styled to look like anything):

#more:not(:checked) ~ #content {
  display: none;
}
<input id="more" type="checkbox" /> <label for="more">more</label>

<p id="content">Some content</p>

but it’s not always (maybe ever? hmm) appropriate to use it; you can usually just fall back on showing the content when JavaScript fails to load, and have the “more” link link to it.

There’s also :target, but it’s probably even less appropriate, since it's harder to build in the closing mechanism.

#content {
  display: none;
}

#content:target {
  display: block;
}

#less {
  display: none;
}

#content:target ~ #less {
  display: block;
}
<a href="#content" id="more">More</a>
<p id="content">Lorem ipsum</p>
<a href="#" id="less">Less</a>

Solution 2:

This is possible with pure HTML, through use of the <details> element. However, note that this element is not supported in Internet Explorer (as of IE 11).

Fear not though, as this is also possible to achieve with CSS, by exploiting the fact that the combination of HTML and CSS is Turing complete. You're able to click on an element by making use of a checkbox's :checked attribute in combination with a <label> element's for attribute.

Because the checkbox can be unchecked, you can use this to toggle visibility by simply adding visibility: hidden (or display: none) to an element stemming from :checked. This works because once the checkbox is clicked again, this pseudo-selector will become invalid, and the CSS selector will no longer match the target.

This can be extended to a <label> with use of the for attribute, so that you can completely hide the checkbox itself, and apply your own styling to the <label> directly.

The following makes use of the adjacent sibling combinator (+) to toggle the class toggle when the <label> element is clicked:

input[type="checkbox"] {
  display: none; /* Hide the checkbox */
}

/* This is tied to the invisible checkbox */
label {
    background-color: #4CAF50;
    border: 2px solid black;
    border-radius: 20px;
    color: white;
    padding: 15px 32px;
    text-align: center;
    font-size: 16px;
    display: inline-block;
    margin-bottom: 20px;
    cursor: pointer;
    user-select: none;
}

/* The target element to toggle */
input[type="checkbox"]:checked + label + .toggle {
  visibility: hidden;
}
<input type="checkbox" id="checkbox" />
<label for="checkbox">Click me to toggle the content</label>
<div class="toggle">Visible by default</div>

Note that if you wish to hide the content by default, that you need to apply the inverse rule to the content by default. There is no :unchecked pseudo-selector, though you can chain the :not and :checked pseudo-selectors together as :not(:checked).

input[type="checkbox"] {
  display: none; /* Hide the checkbox */
}

/* This is tied to the invisible checkbox */
label {
    background-color: #4CAF50;
    border: 2px solid black;
    border-radius: 20px;
    color: white;
    padding: 15px 32px;
    text-align: center;
    font-size: 16px;
    display: inline-block;
    margin-bottom: 20px;
    cursor: pointer;
    user-select: none;
}

/* The target element to toggle */
input[type="checkbox"]:checked + label + .toggle {
  display: block;
}

/* The element should be hidden by default */
input[type="checkbox"]:not(:checked) + label + .toggle {
  display: none;
}
<input type="checkbox" id="checkbox" />
<label for="checkbox">Click me to toggle the content</label>
<div class="toggle">Invisible by default</div>

Finally, if you have a situation where the content cannot immediately proceed the toggle, you can use the general sibling combinator (~). Note that the content must be a sibling or child element, as there is no parent selector in CSS3 (though one is proposed for CSS4).