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

Css

Css Problem Overview


Is it possible to show and hide text using a link with only CSS -- without using JavaScript at all?

For example: On this page

Note the "More" link. When you click it, it unhides text. This particular example is JavaScript, but I am not sure if it can be done with pure CSS.

Css Solutions


Solution 1 - Css

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 - Css

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).

Solution 3 - Css

Yes, you can easily do this using CSS only. Please refer to the code below:

* {
  box-sizing: border-box;
}

body {
  background-color: #646464;
  color: #fff;
}

header {
  background-color: rgba(0, 0, 0, 0.5);
  font-size: 1.5em;
  text-align: center;
  padding: 1em;
}

.panel-wrapper {
  position: relative;
}

.btn {
  color: #fff;
  background: #000;
  border-radius: 1.5em;
  left: 30%;
  padding: 1em;
  text-decoration: none;
  width: 40%;
}

.show,
.hide {
  position: absolute;
  bottom: -1em;
  z-index: 100;
  text-align: center;
}

.hide {
  display: none;
}

.show:target {
  display: none;
}

.show:target~.hide {
  display: block;
}

.show:target~.panel {
  max-height: 2000px;
}

.show:target~.fade {
  margin-top: 0;
}

.panel {
  position: relative;
  margin: 2em auto;
  width: 70%;
  max-height: 100px;
  overflow: hidden;
  transition: max-height .5s ease;
}

.fade {
  background: linear-gradient(to bottom, rgba(100, 100, 100, 0) 0%, #646464 75%);
  height: 100px;
  margin-top: -100px;
  position: relative;
}

<!DOCTYPE html>
<html lang='en' class=''>

<head>
  <link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css'>
</head>

<body>
  <header>CSS Only: Show More</header>
  <div class="panel-wrapper">
    <a href="#show" class="show btn" id="show">Show Full Article</a>
    <a href="#hide" class="hide btn" id="hide">Hide Full Article</a>
    <div class="panel">
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. In pharetra consectetur accumsan. Vestibulum vitae ipsum euismod, tempus ligula non, tempus lacus. Phasellus at pellentesque ex. Praesent at ipsum dui. Cras lectus neque, bibendum ac diam
        a, elementum tristique felis. Sed iaculis, diam at vehicula lacinia, odio urna tincidunt felis, sit amet scelerisque urna erat non leo. Pellentesque vel leo vitae tellus bibendum viverra.</p>
      <p>Donec id ultrices mi. Suspendisse potenti. Pellentesque cursus sagittis lacinia. Mauris elit sem, eleifend nec facilisis eget, fermentum sed odio. Nam aliquam massa nec leo tincidunt rhoncus. Integer tincidunt finibus tincidunt. Maecenas aliquam
        fermentum nisi, vitae mattis neque vehicula vitae.</p>
      <p>Nam orci purus, consequat sed lorem id, lacinia efficitur lorem. Vestibulum id quam ut elit congue varius. Donec justo augue, rhoncus non nisl ut, consectetur consequat velit. In hac habitasse platea dictumst. In hac habitasse platea dictumst. Aliquam
        auctor sapien lorem, at vestibulum justo congue vel. Duis volutpat, lorem quis tincidunt ornare, felis tortor posuere tellus, nec pretium neque velit vulputate libero.</p>
      <p>Morbi tortor tortor, auctor porttitor felis in, eleifend cursus ante. Nullam pellentesque lorem ipsum, in fringilla enim suscipit cursus. Pellentesque feugiat volutpat congue. Donec ac ante elit. Quisque ornare lacus dui, id commodo tortor lacinia
        nec. Curabitur dignissim magna sagittis neque aliquam porttitor. Aenean sit amet tincidunt risus.</p>
      <p>Cras feugiat, sapien luctus congue gravida, enim enim tristique nisl, vel porta lacus ante vitae dolor. Duis at nisl sed lectus imperdiet congue. Vestibulum pellentesque finibus ligula, sit amet elementum enim dignissim eget. Nullam bibendum justo
        eros, in placerat est ullamcorper nec. Donec blandit accumsan venenatis. Vivamus nec elit arcu. Morbi ultrices blandit sapien eget aliquam. Pellentesque placerat et libero a sodales. Donec eget erat ac velit maximus ullamcorper. Nulla laoreet
        dolor in purus sollicitudin varius. Duis eu erat ut magna lobortis rhoncus ac at lacus. Nullam in mi sed sem porttitor molestie. Aenean auctor dui in neque vulputate, in mattis purus tristique. Aliquam egestas venenatis ultricies. Nam elementum
        ante libero, nec dictum erat mollis dapibus. Phasellus pharetra euismod nibh, sit amet lobortis odio.</p>
      <p>Sed bibendum dapibus leo eu facilisis. Cras interdum malesuada diam id lobortis. Phasellus tristique odio eget placerat ornare. Phasellus nisl nulla, auctor convallis turpis tempus, molestie blandit urna. Nullam accumsan tellus massa, at tincidunt
        metus imperdiet sed. Donec sed imperdiet quam, id dignissim dolor. Curabitur mollis ultricies tempor. Morbi porttitor, turpis et dignissim aliquam, nunc lacus dignissim massa, a consequat nibh est vel turpis. Pellentesque blandit, ante vehicula
        sollicitudin imperdiet, tellus urna fringilla diam, id tempor neque augue eu nisl. Quisque eu sem posuere, vehicula risus ut, ullamcorper massa. Fusce vulputate bibendum erat, vel dapibus dui consectetur nec. Donec mauris mauris, egestas non malesuada
        non, finibus nec lacus. Duis at mauris tincidunt, accumsan augue non, vestibulum libero.</p>
      <p>Vestibulum fermentum vulputate lectus, at sollicitudin diam laoreet vitae. Aliquam erat volutpat. Nulla condimentum, arcu nec suscipit ultrices, urna tortor rutrum purus, sed mollis lacus ligula vitae justo. Duis vitae malesuada sem, eget finibus
        nibh. Etiam facilisis, urna ac blandit molestie, quam velit congue nibh, ac.</p>

    </div>
    <!-- end panel -->
    <div class="fade"></div>
  </div>
  <!-- end panel-wrapper -->

</body>

</html>

Solution 4 - Css

You could hide a checkbox, but allow it to be checked/unchecked via its associated <label> element.

Based on whether the checkbox is checked or not, you can hide/show the additional text, and even change the text of the label from "More" to "Less".

I've included some additional details in the CSS so that each definition's intentions can be a bit more clear.

1. With one toggle "More" / "Less" button:

.more-text, #more-checkbox {          /* Hide the second paragraph and checkbox */
  display: none;
}

input:checked ~ .more-text {          /* Show the second paragraph when checked */
  display: block;
}

.more-label::after {                  /* Label underline, hand cursor, color */
  cursor: pointer;
  text-decoration: underline;
  color: #666;
}

input ~ .more-label::after {          /* Set label text to "More" by default */
  content: 'More';
}

input:checked ~ .more-label::after {  /* Set label text to "Less" when checked */
  content: 'Less';
}

<p>
  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ullamcorper, arcu ut facilisis interdum, lacus felis fringilla nulla, vel scelerisque massa quam vel leo.
</p>

<input type="checkbox" id="more-checkbox" />
<label class="more-label" for="more-checkbox"></label>

<p class="more-text">
  Sed a ullamcorper ex. In elementum purus ullamcorper justo gravida aliquet. Aliquam erat volutpat. Maecenas in ante quam.
</p>


2. With "More" button at the top and "Less" button at the bottom:

.more-text, #more-checkbox, .less-label {
  display: none;
}

.more-label, .less-label {          
  cursor: pointer;
  text-decoration: underline; 
  color: #666;
}

input:checked ~ .more-text, input:checked ~ .less-label {
  display: block;
}

input:checked ~ .more-label {
  display: none;
}

<p>
  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ullamcorper, arcu ut facilisis interdum, lacus felis fringilla nulla, vel scelerisque massa quam vel leo.</p>

<input type="checkbox" id="more-checkbox" />
<label class="more-label" for="more-checkbox">More</label>

<p class="more-text">
  Sed a ullamcorper ex. In elementum purus ullamcorper justo gravida aliquet. Aliquam erat volutpat. Maecenas in ante quam.
</p>

<label class="less-label" for="more-checkbox">Less</label>

Solution 5 - Css

Technically speaking, it is possible to toggle the visibility of text based on when you click on a button or link, as shown below:

.hidden-text {
  display: none;
}

.toggle-text:focus + .hidden-text {
  display: block;
}

<p>
  This is an example with no hidden content until you... <a href="#" class="toggle-text">read more</a>!
  <span class="hidden-text">Now I'm visible!!!</span>
</p>

That being said, I do strongly recommend that you familiarize yourself with JavaScript as the solution using JavaScript for something like this is much simpler and allows for additional flexibility.

Solution 6 - Css

Yes, you can do that by using HTML and CSS only.

body { padding: 20px; }

div { margin-top: 10px; border: 1px solid black; width: 200px; height: 100px;
    padding: 5px;
}
input:checked + label + div { display: none; }
input + label:after { content: " To Hide"; }
input:checked + label:after { content: " To Show"; }

label {
    background-color: yellow;
    box-shadow: inset 0 2px 3px rgba(255,255,255,0.2), inset 0 -2px 3px rgba(0,0,0,0.2);
    border-radius: 4px;
    font-size: 16px;
    display: inline-block;
    padding: 2px 5px;
    cursor: pointer;
}

<input type='checkbox' style='display: none' id=cb>
<label for=cb>Click Here</label>
<div>
    Hello. This is some stuff.
</div>

Solution 7 - Css

now you can hide/show text using only CSS too! If you are using text input and want to show/hide text based on the state of the input box, you can use the new CSS pseudo-class :placeholder-shown for <input> or <textarea>. Here is an example/demo of the above-mentioned pseudo-class!:

/* Some base style  */
.app {
  margin: 10px auto;
  padding: 10px;
}

code {
  background-color: lightgray;
  padding: 4px;
}

input {
  padding: 5px 10px;
}

input:focus {
  outline: none;
}

/* When there is something in input box give 
  it a solid blue border */

input:not(:placeholder-shown) {
  border: solid 2px #42A5F5
}

/* Hide the p initially */
p {
  background-color: #F0F4C3;
  padding: 5px;
  opacity: 0;
  transition: all 300ms ease-in-out;
}


/* Show the p when the placeholder is not shown. 
  i.e. Something is in the input box and placeholder is gone */
input:not(:placeholder-shown)+p {
  opacity: 1
}

<div class="app">
  <h1>Hide/Show Text using input's <code>:placehoder-shown</code> psuedo class!</h1>
  <label for="name">Enter your name</label>
  <input type="text" id="name" placeholder="Your Name">
  <p class="msg">Well done!</p>
</div>

Here is Link to MDN Docs.

> This is an experimental technology Check the Browser compatibility table carefully before using this in production.

Solution 8 - Css

Use "display: none;" attribute.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser3188544View Question on Stackoverflow
Solution 1 - CssRy-View Answer on Stackoverflow
Solution 2 - CssObsidian AgeView Answer on Stackoverflow
Solution 3 - CssAkashView Answer on Stackoverflow
Solution 4 - CssTyler RoperView Answer on Stackoverflow
Solution 5 - CssAdam ChubbuckView Answer on Stackoverflow
Solution 6 - CssMonir alhussiniView Answer on Stackoverflow
Solution 7 - CssHirenView Answer on Stackoverflow
Solution 8 - CssAjay MunugalaView Answer on Stackoverflow