Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tab system with pure CSS, anchor avoids the propagation to label

I'm making a tab system only with CSS using :target and :checked pseudoclasses, but I have an anchor inside the label, and the label doesn't trigger the :checked.

If you click in the anchor, the :checked doesn't trigger because the click is in the <a> tag, but is inside a <label> that must trigger the radio button. If you click on the border of the tab, you'll see how it triggers the :checked, but not the anchor, so the :target can't be triggered.

Here you are my code, more understandable than the words:

a {
  text-decoration: none;
}
.tabs {
  position: relative;
}
input {
  display: none;
}
.tabs .tab label {
  text-decoration: none;
  border: 1px solid black;
  padding: 2px;
  display: inline-block;
  top: 2px;
  position: relative;
  cursor: pointer;
}
.tabs .tab input:checked + label {
  background-color: white;
  border-bottom: 0;
  padding: 4px 2px;
  top: 1px;
}
.contents {
  border: 1px solid black;
  background-color: white;
}
.contents .content {
  display: none;
  padding: 20px;
}
.contents .content:target {
  display: block;
}
<div class="tabs">
  <span class="tab">
    <input type="radio" name="ch" id="check1">
    <label for="check1">
      <a href="#tab1">Tab 1</a>
    </label>
  </span>
  <span class="tab">
    <input type="radio" name="ch" id="check2">
    <label for="check2">
      <a href="#tab2">Tab 2</a>
    </label>
  </span>
  <span class="tab">
    <input type="radio" name="ch" id="check3">
    <label for="check3">
      <a href="#tab3">Tab 3</a>
    </label>
  </span>
</div>
<div class="contents">
  <div class="content" id="tab1">Contenido 1</div>
  <div class="content" id="tab2"><strong>Contenido 2</strong></div>
  <div class="content" id="tab3"><em>Contenido 3</em></div>
</div>

Is there a way to combine :checked and :target pseudoclasses to achieve a complete tab system only with CSS?

Thank you.

EDIT

Here you are the snippet without anchor. Obviously the :target will not be triggered:

a {
  text-decoration: none;
}
.tabs {
  position: relative;
}
input {
  display: none;
}
.tabs .tab label {
  text-decoration: none;
  border: 1px solid black;
  padding: 2px;
  display: inline-block;
  top: 2px;
  position: relative;
  cursor: pointer;
}
.tabs .tab input:checked + label {
  background-color: white;
  border-bottom: 0;
  padding: 4px 2px;
  top: 1px;
}
.contents {
  border: 1px solid black;
  background-color: white;
}
.contents .content {
  display: none;
  padding: 20px;
}
.contents .content:target {
  display: block;
}
<div class="tabs">
  <span class="tab">
    <input type="radio" name="ch" id="check1">
    <label for="check1">
      Tab 1
    </label>
  </span>
  <span class="tab">
    <input type="radio" name="ch" id="check2">
    <label for="check2">
      Tab 2
    </label>
  </span>
  <span class="tab">
    <input type="radio" name="ch" id="check3">
    <label for="check3">
      Tab 3
    </label>
  </span>
</div>
<div class="contents">
  <div class="content" id="tab1">Contenido 1</div>
  <div class="content" id="tab2"><strong>Contenido 2</strong></div>
  <div class="content" id="tab3"><em>Contenido 3</em></div>
</div>
like image 713
Marcos Pérez Gude Avatar asked Jan 24 '26 18:01

Marcos Pérez Gude


1 Answers

When you use input:checked, :target is not efficient cause this event is not triggered at all.

You need to put your input ahead in the flow so you can use the selector ~ to select any sibblings and their children following in the flow of the document:

example

a {
  text-decoration: none;
}
.tabs {
  position: relative;
}
input {
  display: none;
}
.tabs .tab label {
  text-decoration: none;
  border: 1px solid black;
  padding: 2px;
  display: inline-block;
  top: 2px;
  position: relative;
  cursor: pointer;
}
#check1:checked ~ .tabs label[for="check1"],
#check2:checked ~ .tabs label[for="check2"],
#check3:checked ~ .tabs label[for="check3"] {
  background-color: white;
  border-bottom: 0;
  padding: 4px 2px;
  top: 1px;
}
.contents {
  border: 1px solid black;
  background-color: white;
}
.contents .content {
  display: none;
  padding: 20px;
}
#check1:checked ~ .contents #tab1,
#check2:checked ~ .contents #tab2,
#check3:checked ~ .contents #tab3 {
  display: block;
}
<!-- begin hidden inputs for CSS tabs purpose -->
<input type="radio" name="ch" id="check1">
<input type="radio" name="ch" id="check2">
<input type="radio" name="ch" id="check3">
<!-- End hidden inputs for CSS tabs purpose -->
<div class="tabs">
  <span class="tab">
    <label for="check1">
      Tab 1
    </label>
  </span>
  <span class="tab">
    <label for="check2">
      Tab 2
    </label>
  </span>
  <span class="tab">
    <label for="check3">
      Tab 3
    </label>
  </span>
</div>
<div class="contents">
  <div class="content" id="tab1">Contenido 1</div>
  <div class="content" id="tab2"><strong>Contenido 2</strong>
  </div>
  <div class="content" id="tab3"><em>Contenido 3</em>
  </div>
</div>
like image 189
G-Cyrillus Avatar answered Jan 26 '26 10:01

G-Cyrillus



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!