Pure CSS tab system that prevents label propagation using anchors

I am in the process of creating a tab system using only CSS with the help of the :target and :checked pseudo classes. However, I have encountered an issue where an anchor inside the label is not triggering the :checked.

When clicking on the anchor, the :checked does not trigger because the click occurs within the <a> tag. The anchor is nested inside a <label> that should be triggering the radio button. Clicking on the border of the tab triggers the :checked but not the anchor, making it impossible to trigger the :target.

Below is my code which provides a clearer understanding:

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">Content 1</div>
  <div class="content" id="tab2"><strong>Content 2</strong></div>
  <div class="content" id="tab3"><em>Content 3</em></div>
</div>

Is there a way to effectively combine the :checked and :target pseudo classes to create a fully functional tab system using just CSS?

Thank you.

EDIT

Here is a version of the snippet without the anchor. As expected, 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">Content 1</div>
  <div class="content" id="tab2"><strong>Content 2</strong></div>
  <div class="content" id="tab3"><em>Content 3</em></div>
</div>

Answer №1

When utilizing input:checked, it is important to note that :target may not be efficient as this event might not be triggered at all.

To effectively use the selector ~ to select any siblings and their subsequent children in the document flow, you should position your input element ahead in the flow:

For 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">Content 1</div>
  <div class="content" id="tab2"><strong>Content 2</strong>
  </div>
  <div class="content" id="tab3"><em>Content 3</em>
  </div>
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How can I activate the fancy box from a specific div element?

There are plenty of variations to this question, but none of them seem to help. I am looking for a way to trigger fancybox from a div. Here is the div in question: <div class="port web">Website</div> This particular div has some CSS styles ap ...

Customizing the attribute of an HTML tag using EJS or jQuery

Within my express server, I am rendering a page with the following data: app.get('/people/:personID', function (req, res) { res.render("people/profile", {person: req.person }); }); Inside my profile.ejs file, I can display the data within an ...

The error code 405 (Method Not Allowed) occurs in Ajax when the action field is empty or identical to the current page

Special thanks to @abc123 for sharing the code below in one of their posts: <!DOCTYPE html> <html> <head> <script src="http://code.jquery.com/jquery-1.9.1.js"></script> </head> <body> <form id="formoid" a ...

Gather information from every user and display their user ID in an HTML table, allowing for updates through a button

Can anyone help me create a table like the one shown here: The table should fetch data from my firebase database. Here is the structure of my requests database: . I've been trying to modify some code I found in a previous question. However, as you c ...

Presenting XML data in HTML using a customized CSS stylesheet

I've explored various methods for showcasing an XML file on a web page using HTML, but I haven't yet encountered one that incorporates a CSS style sheet. The XML file I have already includes a CSS style sheet. When viewed in a web browser, the . ...

EJS: Warning when the "<%= %>" tag is used multiple times within the code

I am currently working on incorporating EJS with Node.js and Express.js. I have defined an array variable called "kindOfDay" containing the names of days as strings, such as "Sun", "Mon"... Within the EJS views folder, there is a file named list.ejs. The i ...

"Troubleshooting: Issues with jQuery Counter Functionality

Hey there, I'm new to JavaScript and jQuery! I've got this form set up with Bootstrap's disabled class: Note: the 'disabled' class in bootstrap properly disables and enables the button based on conditions. <form action="" met ...

Display additional tiles within a compact container

I'm attempting to replicate the user interface used by foursquare! Positioning the map slightly off center like they have . I've figured out how to do one part but struggling with the second part. Initially, I loaded the map in a small div (t ...

Implementing a Scroll Bar within a Stack Component in Material UI

I've developed a component and now I'm looking to enable scrolling when it expands beyond the screen width <Stack direction="row"> <Stack gap={1} overflow="auto"> {fields.map((el, i) => ( ...

How can I make CSS text-overflow ellipsis trigger a pop-up to display lengthy text when clicked?

I'm encountering an issue with a lengthy sentence in a table cell which I've truncated using text-overflow to display ellipsis. Is there a way to enable users to click on the dots (...) and view the full text in a popup window? table { wi ...

How can I create an HTML form input slider/range that accepts non-numeric values?

<input type="range" min="2" max="52" value="4" step="1"/> Is it possible to have an input range with non-numeric intervals, such as "Yes," "maybe," and "no"? Appreciate any guidance on this. Thank you. ...

Solving the issue of IE7 div overflow-y: scroll causing content to be obscured by the scrollbar

I am facing an issue with a table inside a div (#body) that scrolls along the y-axis. Specifically, in Internet Explorer, the scrollbar is hiding part of the last table cell behind it, causing a shift in the layout of the table columns. This problem does n ...

Creating a banner using four grid elements, with each element containing four child elements, is a simple process that can

Can you assist me in recreating my idea from an image? I am having trouble understanding how to select and place other elements, and then return them to their original positions after deselecting... I attempted to use a grid but it did not work properly. ...

Converting Excel values to Exponential format using Python

I'm struggling to find a solution for extracting the Invoice Number in Python from an Excel sheet without turning it into exponential form. Expected Value: 8000030910 Result: 8.00002e+09 Python Result Excel sheet d1.append(sheet.cell_value(j,0)) ...

Using AJAX to dynamically load content from a Wordpress website

Currently, I have been experimenting with an AJAX tutorial in an attempt to dynamically load my WordPress post content onto the homepage of my website without triggering a full page reload. However, for some reason, when clicking on the links, instead of ...

Show a directional indicator on hover in the date selection tool

I am currently using a datepicker that looks like this: When I hover over it, three arrows appear to change days or show the calendar. However, I would like to remove these arrows. Here is the code snippet: link: function (scope, element, attr, ngModel ...

PHP Unable to Locate the header.html File Within the Specified Directory

Currently, I am facing an issue while trying to use PHP to incorporate the same header, navigation, and footer elements on all my website pages. The problem arises when the .php file fails to recognize the header.html file for an include("/header.html") op ...

How to extract the YouTube video source using jQuery from an iframe snippet

Currently, I am attempting to extract the YouTube source from an iframe embed code and store it as a variable. Suppose my YouTube embed code looks like this: <iframe width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://w ...

Combining various functions into a single button

I am currently working on creating a full-screen menu that functions like a modal. Everything seems to be working fine, except for the fadeOut animation. Can someone please help me understand what is causing issues with my scripts/codes? I want the content ...

The Selenium element cannot be interacted with due to having the same id

I have a main page class structure defined as follows: public class BasePage{ @FindBy(id = "select2-ccnl-container") protected WebElement ccnlSelect; public void clickSettingCcnl(){ ccnlSelect.click(); } } After that, I ...