Home > Software design >  Reveal div by clicking a link, make it hidden again by clicking another
Reveal div by clicking a link, make it hidden again by clicking another

Time:06-11

I'm pretty new to html and css, so this may be a stupid question, but I want an area where there is a text you can click on that reveals an entire div full of text, with another clickable text at the bottom to hide it again, completely JQuery and Javascript free, only using html and css. Not only that but I need several of them one on top of the other. This is what I've got so far:

.horizontal-box{
  display: inline-flex;
  flex-direction: column;
}
.displayable-text{
  display: none;
}
#one.show:target ~ #one.displayable-text{
  display: inline-block;
}
#one.hide:target ~ #one.displayable-text{
  display: none;
}
#two.show:target ~ #two.displayable-text{
  display: inline-block;
}
#two.hide:target ~ #two.displayable-text{
  display: none;
}
<div >
  <div>
    Bla bla bla
    <a href="#one" >show text</a>
    <div id="one" >
      Bla bla bla
      <a href="#one" >hide text</a>
    </div>
  </div>
  <div>
  Bla bla bla
    <a href="#two" >show text</a>
    <div id="two" >
      Bla bla bla
      <a href="#two" >hide text</a>
    </div>
  </div>
</div>

Could someone please explain to me what I've done wrong or tell me how to do it? I have no idea of why it doesn't work.

CodePudding user response:

This is the only way I can think of without using JS. I'm using the labels for attribute to target a hidden checkbox's ID. In the CSS I'm using the input:checked selector to hide and show the div with the hidden content.

.hidden {
  display: none;
}
.pointer {
 cursor: pointer;
}
.horizontal-box {
  display: inline-flex;
  flex-direction: column;
}
.displayable-text {
  display: none;
}
input:checked ~ div {
  display: inline-block;
}
input:checked ~ label {
  display: none;
}
<div >
  <div>
    Bla bla bla
    <input type="checkbox" id="one" >
    <label for="one" ><strong>show text</strong></label>
    <div >
      Bla bla bla
      <label for="one" ><strong>hide text</strong></label>
    </div>
  </div>
  <div>
    Bla bla bla
    <input type="checkbox" id="two" >
    <label for="two" ><strong>show text</strong></label>
    <div >
      Bla bla bla
      <label for="two" ><strong>hide text</strong></label>
    </div>
  </div>
</div>

CodePudding user response:

#one only targets elements with id="one" not href="#one".
#one.show and #one.hide makes no sense as show/hide buttons don't have an id. And the id needs to be unique, so you can't have them on multiple elements.

And usage of ~ also makes no sense as .hide and .displayable-text are child and parent and not siblings.


The solution is a lot more simple.

There is no need to write CSS with selector targeting specific ids.

Just show elements that are targeted and make the hide button clear the target.

.horizontal-box{
  display: inline-flex;
  flex-direction: column;
}
.displayable-text{
  display: none;
}
.displayable-text:target {
  display: inline-block;
}
<div >
  <div>
    Bla bla bla One
    <a href="#one" >show text</a>
    <div id="one" >
      More Bla bla bla One
      <a href="#" >hide text</a>
    </div>
  </div>
  <div>
    Bla bla bla Two
    <a href="#two" >show text</a>
    <div id="two" >
      More Bla bla bla Two
      <a href="#" >hide text</a>
    </div>
  </div>
</div>

Note: With :target you can only have one div open, since you can only have one target at a time.

  • Related