Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Toggle the status of a checkbox in the checkbox hack with a hyperlink

My colleague and I worked on a website that contains a FAQ page. After each question, there is an "Answer"(Antwoord) spoiler button. Clicking the button shows the answer below the current question, and above the next question. Clicking the button again hides the answer. This makes it easy to scroll through the list of all questions and find the question you could be interested in.

Now the problem I face is that I want to link to for example the answer of question 5, from the answer of question 1.

I could give the <div> that contains question 5 an id= property to link to that, but ideally, I want to show the answer straight away by making the hyperlink "click" the Answer button.

It turns out that I will need to modify the checkbox hack in order for this to properly work, but I face the problem that I can't have both an Hyperlink and a Label on one piece of text.

Just to be clear: I'm looking for a solution using only HTML/CSS.


My original code with just a spoiler button

.spoilerbutton {
  display: block;
  border: none;
  padding: 0px 0px;
  margin: 10px 0px;
  font-size: 150%;
  font-weight: bold;
  color: #000000;
  background-color: transparent;
  outline: 0;
}

.spoiler {
  overflow: hidden;
}

.spoiler>div {
  -webkit-transition: all 0s ease;
  -moz-transition: margin 0s ease;
  -o-transition: all 0s ease;
  transition: margin 0s ease;
}

.spoilerbutton[value="Antwoord"]+.spoiler>div {
  margin-top: -500%;
}

.spoilerbutton[value="Hide Antwoord"]+.spoiler {
  padding: 5px;
}
<strong>1. Question 1?</strong> <input class="spoilerbutton" onclick="this.value=this.value=='Antwoord'?'Verberg':'Antwoord';" type="button" value="Antwoord" />
<div class="spoiler">
  <div>
    <ul>
      <li>possible answer 1.</li>
      <li>possible answer 2.</li>
      <li>possible answer 3.</li>
    </ul>
  </div>
</div>

Trying to implement solutions from: Can I have an onclick effect in CSS?

I get the following which doesn't work:

#btnControll1 {
    display: none;
}

.spoilerbutton {
  display: block;
  border: none;
  padding: 0px 0px;
  margin: 10px 0px;
  font-size: 150%;
  font-weight: bold;
  color: #000000;
  background-color: transparent;
  outline: 0;
}

.spoiler {
  overflow: hidden;
}

.spoiler>div {
  -webkit-transition: all 0s ease;
  -moz-transition: margin 0s ease;
  -o-transition: all 0s ease;
  transition: margin 0s ease;
}

#btnControl1:checked + label {
margin-top; -500%
}
<strong>1. Question 1?</strong> <input type"chekbox" id="btnControl1" />
<label class="spoilerbutton" for="btnControl1">Antwoord</label>
<div class="spoiler">
  <div>
    <ul>
      <li>possible answer 1.</li>
      <li>possible answer 2.</li>
      <li>possible answer 3.</li>
    </ul>
  </div>
</div>

Using combinations of <label> and <a href> (also not working)

.spoilerbutton {
display: none;
}
.spoiler {
overflow: hidden;
height:2em;
}
.spoiler>div {
-webkit-transition: all 0s ease;
-moz-transition: margin 0s ease;
-o-transition: all 0s ease;
transition: margin 0s ease;
}
.spoilerbutton+.spoiler>div {
margin-top: -500%;
}
.spoilerbutton+.spoiler>label:before {
content: 'Antwoord';
font-size: 150%;
font-weight: bold;
color: #000000;
}
.spoilerbutton:checked+.spoiler>label:before {
content: 'Verberg';
}
.spoilerbutton:checked+.spoiler {
height:auto;
}
.spoilerbutton:checked+.spoiler>div {
margin-top: 0;
}
<strong>1. Question 1?</strong> <input type="checkbox" id="question1" value="checked" class="spoilerbutton">
<div class="spoiler">
<label for="question1"></label>
<div>
<ul>
<li><a href="#question5"><label for="#answer5">Open 5. link first</label></a></li>
<li><label for="question5"><a href="#answer5">Open 5. label first</a></label></li>
<li><a href="#answer5">Open 5. link only</a></li>
</ul>
</div>
</div>
<strong>2. Question 2?</strong> <input type="checkbox" id="question2" value="checked" class="spoilerbutton">
<div class="spoiler">
<label for="question2"></label>
<div>
<ul>
<li>possible answer 1.</li>
<li>possible answer 2.</li>
<li>possible answer 3.</li>
</ul>
</div>
</div>
<strong>2. Question 3?</strong> <input type="checkbox" id="question3" value="checked" class="spoilerbutton">
<div class="spoiler">
<label for="question3"></label>
<div>
<ul>
<li>possible answer 1.</li>
<li>possible answer 2.</li>
<li>possible answer 3.</li>
</ul>
</div>
</div>
<strong>2. Question 4?</strong> <input type="checkbox" id="question4" value="checked" class="spoilerbutton">
<div class="spoiler">
<label for="question4"></label>
<div>
<ul>
<li>possible answer 1.</li>
<li>possible answer 2.</li>
<li>possible answer 3.</li>
</ul>
</div>
</div>
<br>
<br>
<br>
<br><br>
<br><br>
<br><br>
<br><br>
<br><br>
<br><br>
<br><br>
<br><br>
<br><br>
<br><br>
<br>
<strong>2. Question 5?</strong> <input type="checkbox" id="question5" value="checked" class="spoilerbutton">
<div class="spoiler" id="answer5">
<label for="question5"></label>
<div>
<ul>
<li>possible answer 1.</li>
<li>possible answer 2.</li>
<li>possible answer 3.</li>
</ul>
</div>
</div>

Also related How to toggle a checkbox when a link is clicked?

There are some great suggestions there, but I'm unable to adapt the answer from Tushar to my situation.

like image 513
Luuklag Avatar asked May 13 '19 09:05

Luuklag


People also ask

What is checkbox hack?

Description. The :checked pseudo-class in CSS selects elements when they are in the selected state. It is only associated with input (input) elements of type radio and checkbox. The “Checkbox Hack” is where you use a connected label and input type="checkbox" and usually some other element you are trying to control.


2 Answers

Option 1 - Using JavaScript

Redirection only works if the element is visible, not set to display: none. In your above code snippet, both the checkbox and the list of answers are set to display: none as their initial state.

Step 1: Add id to each <strong id="question"> element.

<strong id="question1">1. Question 1?</strong> 

Step 2: We cannot check/uncheck a checkbox using CSS, we have to use JavaScript/jQuery to achieve this functionality. So I added the basics to a checkbox checked script, when a user clicks on the link.

<li><a href="#question5" onClick="var str = this.attributes['href'].value + 'Checkbox'; document.getElementById(str.replace('#', '')).checked = true;">Open 5. link first</a></li>

.spoilerbutton {
display: none;
}
.spoiler {
overflow: hidden;
height:2em;
}
.spoiler>div {
-webkit-transition: all 0s ease;
-moz-transition: margin 0s ease;
-o-transition: all 0s ease;
transition: margin 0s ease;
}
.spoilerbutton+.spoiler>div {
margin-top: -500%;
}
.spoilerbutton+.spoiler label:before {
content: 'Antwoord';
font-size: 150%;
font-weight: bold;
color: #000000;
}
.spoilerbutton:checked+.spoiler label:before {
content: 'Verberg';
}
.spoilerbutton:checked+.spoiler {
height:auto;
}
.spoilerbutton:checked+.spoiler>div {
margin-top: 0;
}
<strong id="question1">1. Question 1?</strong> 
<input type="checkbox" id="question1Checkbox" value="checked" class="spoilerbutton">
  <div class="spoiler">
    <label for="question1Checkbox"></label>
    <div>
      <ul>
        <li><a href="#question5" onClick="var str = this.attributes['href'].value + 'Checkbox'; document.getElementById(str.replace('#', '')).checked = true;">Open 5. link first</a></li>
      </ul>
    </div>
</div>
<strong id="question2">2. Question 2?</strong> 
<input type="checkbox" id="question2Checkbox" value="checked" class="spoilerbutton">
<div class="spoiler">
  <label for="question2Checkbox"></label>
  <div>
    <ul>
      <li>possible answer 1.</li>
      <li>possible answer 2.</li>
      <li>possible answer 3.</li>
    </ul>
  </div>
</div>
<strong id="question3">2. Question 3?</strong> 
<input type="checkbox" id="question3Checkbox" value="checked" class="spoilerbutton">
<div class="spoiler">
  <label for="question3Checkbox"></label>
  <div>
    <ul>
      <li>possible answer 1.</li>
      <li>possible answer 2.</li>
      <li>possible answer 3.</li>
    </ul>
  </div>
</div>
<strong id="question4">2. Question 4?</strong> 
<input type="checkbox" id="question4Checkbox" value="checked" class="spoilerbutton">
<div class="spoiler">
  <label for="question4Checkbox"></label>
  <div>
    <ul>
      <li>possible answer 1.</li>
      <li>possible answer 2.</li>
      <li>possible answer 3.</li>
    </ul>
  </div>
</div>
<br>
<br>
<br>
<br><br>
<br><br>
<br><br>
<br><br>
<br><br>
<br><br>
<br><br>
<br><br>
<br><br>
<br><br>
<br>
<strong id="question5">2. Question 5?</strong> 
<input type="checkbox" id="question5Checkbox" value="checked" class="spoilerbutton">
<div class="spoiler" id="answer5">
  <label for="question5Checkbox"></label>
  <div>
    <ul>
      <li>possible answer 1.</li>
      <li>possible answer 2.</li>
      <li>possible answer 3.</li>
    </ul>
  </div>
</div>

Option 2 - Using CSS

By using the CSS :target selector and little bit of a structure update, we can achieve the functionality by using CSS.

.spoilerbutton {
display: none;
}
.spoiler {
overflow: hidden;
height:2em;
}
.spoiler>div {
-webkit-transition: all 0s ease;
-moz-transition: margin 0s ease;
-o-transition: all 0s ease;
transition: margin 0s ease;
}
.spoilerbutton+.spoiler .listOfAnswer {
margin-top: -500%;
}
.spoilerbutton+.spoiler .labelWrap {
  display: inline-block;
  position: relative;
}
.spoilerbutton+.spoiler .labelWrap label:before {
content: 'Antwoord';
font-size: 150%;
font-weight: bold;
color: #000000;
}
.spoilerbutton:checked+.spoiler .labelWrap label:before {
content: 'Verberg';
}
.spoilerbutton:checked+.spoiler {
height:auto;
}
.spoilerbutton:checked+.spoiler .listOfAnswer {
margin-top: 0;
}

:target + .spoilerbutton + .spoiler {
height:auto;
}
:target + .spoilerbutton + .spoiler .labelWrap label:before {
content: 'Verberg';
}
:target + .spoilerbutton + .spoiler .labelWrap .resetTarget {
cursor: default;
display: block;
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
}
:target + .spoilerbutton + .spoiler .listOfAnswer {
margin-top: 0;
}
.resetTarget {
  display: none;
}
<strong class="qTitle" id="question1">1. Question 1?</strong> 
<input type="checkbox" id="question1Checkbox" value="checked" class="spoilerbutton">
  <div class="spoiler">
    <div class="labelWrap">
      <label for="question1Checkbox"></label>
      <a class="resetTarget" href="#question1Checkbox"></a>
    </div>
    <div class="listOfAnswer">
      <ul>
        <li><a href="#question5">Open 5. link first</a></li>
      </ul>
    </div>
</div>
<strong class="qTitle" id="question2">2. Question 2?</strong> 
<input type="checkbox" id="question2Checkbox" value="checked" class="spoilerbutton">
<div class="spoiler">
  <div class="labelWrap">
    <label for="question2Checkbox"></label>
    <a class="resetTarget" href="#question2Checkbox"></a>
  </div>
  <div class="listOfAnswer">
    <ul>
      <li>possible answer 1.</li>
      <li>possible answer 2.</li>
      <li>possible answer 3.</li>
    </ul>
  </div>
</div>
<strong class="qTitle" id="question3">2. Question 3?</strong> 
<input type="checkbox" id="question3Checkbox" value="checked" class="spoilerbutton">
<div class="spoiler">
  <div class="labelWrap">
    <label for="question3Checkbox"></label>
    <a class="resetTarget" href="#question3Checkbox"></a>
  </div>
  <div class="listOfAnswer">
    <ul>
      <li>possible answer 1.</li>
      <li>possible answer 2.</li>
      <li>possible answer 3.</li>
    </ul>
  </div>
</div>
<strong class="qTitle" id="question4">2. Question 4?</strong> 
<input type="checkbox" id="question4Checkbox" value="checked" class="spoilerbutton">
<div class="spoiler">
  <div class="labelWrap">
    <label for="question4Checkbox"></label>
    <a class="resetTarget" href="#question4Checkbox"></a>
  </div>
  <div class="listOfAnswer">
    <ul>
      <li>possible answer 1.</li>
      <li>possible answer 2.</li>
      <li>possible answer 3.</li>
    </ul>
  </div>
</div>
<br>
<br>
<br>
<br><br>
<br><br>
<br><br>
<br><br>
<br><br>
<br><br>
<br><br>
<br><br>
<br><br>
<br><br>
<br>
<strong class="qTitle" id="question5">2. Question 5?</strong> 
<input type="checkbox" id="question5Checkbox" value="checked" class="spoilerbutton">
<div class="spoiler" id="answer5">
  <div class="labelWrap">
    <label for="question5Checkbox">
      <a class="resetTarget" href="#question5Checkbox"></a>
    </label>    
  </div>
  <div class="listOfAnswer">
    <ul>
      <li>possible answer 1.</li>
      <li>possible answer 2.</li>
      <li>possible answer 3.</li>
    </ul>
  </div>
</div>
like image 143
Hassan Siddiqui Avatar answered Nov 15 '22 10:11

Hassan Siddiqui


Short answer

In general, yes, it is possible to accomplish this, but it has huge limitations due to the limitations of CSS (Cascading Style Sheets) so in reality the answer is no.


Long answer

The problem we face is that you won't be able to implement a solution dynamically without any JavaScript. You can see that in the possible answer you linked. In pure CSS it is only possible to target elements specified in the file. How can CSS know which checkbox to check (assuming using the checkbox hack) or which answer to extend if you click on a link? The answer is simple: It can't.

So the only way to do it without JavaScript is by doing it not dynamically. The problem is that you can't target parent elements (Cascading Style Sheets) so there isn't even a pure CSS way to even open up another element if, for example, a hyperlink is in :focus and you also can't check/uncheck checkboxes with CSS.

This brings us to JavaScript as the only possible solution with your structure of code.

.spoilerbutton {
  position: absolute;
  margin-top: 9px 0 0 -5px;
  height: 35px;
  width: 102px;
  opacity: 0;
}

.spoilerbutton:checked {
  width: 86px;
}

.spoilerbutton~.text::after {
  content: "Antwoord";
}

.spoilerbutton:checked~.text::after {
  content: "Verberg";
}

.spoilerbutton~.spoiler {
  display: none;
}

.spoilerbutton:checked~.spoiler {
  padding: 5px;
  display: block;
}
<div>
  <strong>1. Question 1?</strong>
  <p class="text"></p>
  <input class="spoilerbutton" type="checkbox" />

  <h2 class="text"></h2>

  <div class="spoiler">
    <div>
      <ul>
        <li><a onclick="document.querySelector(this.attributes['href'].value + ' .spoilerbutton').checked = true;" href="#answer3">Open answer 3</a></li>
        <li>possible answer 2.</li>
        <li>possible answer 3.</li>
      </ul>
    </div>
  </div>
</div>

<div>
  <strong>1. Question 2?</strong>
  <p class="text"></p>
  <input class="spoilerbutton" type="checkbox" />

  <h2 class="text"></h2>

  <div class="spoiler">
    <div>
      <ul>
        <li>possible answer 1.</li>
        <li>possible answer 2.</li>
        <li>possible answer 3.</li>
      </ul>
    </div>
  </div>
</div>

<div style="margin-top: 500px" id="answer3">
  <strong>1. Question 3?</strong>
  <p class="text"></p>
  <input class="spoilerbutton" type="checkbox" />

  <h2 class="text"></h2>

  <div class="spoiler">
    <div>
      <ul>
        <li>possible answer 1.</li>
        <li>possible answer 2.</li>
        <li>possible answer 3.</li>
      </ul>
    </div>
  </div>
</div>

One line of code is enough:

document.querySelector(this.attributes['href'].value + ' .spoilerbutton').checked = true;

Edit

Actually I forgot about the :target pseudo class. But Hassan Siddiqui already completed his answer with it. However, you will have to restructure your code and if you want to use the JavaScript approach (which I strongly recommend) I prefer my line of code.

like image 26
Aaron3219 Avatar answered Nov 15 '22 12:11

Aaron3219