Can tabs be created without the use of javascript?

I'm currently working on implementing a tabbed box layout, and while I've come across several tutorials that use JavaScript to switch between tabs, I'm wondering if there is a way to achieve the same functionality without relying on JavaScript. Is it possible to have tabbed content without using JavaScript?

Answer №1

UPDATE: In 2020, this method is still effective for linking tabs; however, if you need multiple tab sets on one page, consider using @chulian's approach with input[type=radio] instead of :target.

You can find an archive of the defunct html5rockstars.com demo here: https://web.archive.org/web/20121118201357/http://htmlrockstars.com/blog/using-css-to-create-a-tabbed-content-area-no-js-required/

A more comprehensive explanation of the same technique can be found here: http://www.sitepoint.com/css3-tabs-using-target-selector/

The key concept is utilizing the CSS3 :target selector to display the currently selected tab. While this works well for a single set of tabs on a page and fully supports browser back buttons, it requires specific conditions to function correctly. Here's an example structure:

<ul id="menu">
    <li><a href="#tab1">First tab</a></li>
    <li><a href="#tab2">Second tab</a></li>
    <li><a href="#tab3">Third tab</a></li>
</ul>
<div id="tab1" class="tab-content">Content of first tab</div>
<div id="tab2" class="tab-content">Content of second tab</div>
<div id="tab3" class="tab-content">Content of third tab</div>

In your stylesheet, define the following rules:

.tab-content {
    display: none;
}
.tab-content:target {
    display: block;
}

However, keep in mind that no content will show until a tab link is clicked unless explicitly directed to a specific tab (e.g., page.html#tab1). The suggested workaround by the second link involves the following adjustments:

.tab-content {
    z-index: 0;
    background-color: white;
    position: absolute;
    top: 100px;
    width: 100%;
    height: 300px;
}
.tab-content:first-child {
    z-index: 1;
}
.tab-content:target {
    z-index: 2;
}

This solution may seem unconventional as it relies on absolute positioning.

Alternatively, if having the default tab placed last in the HTML structure isn't an issue, you can opt for this layout:

<ul id="menu">
    <li><a href="#tab1">First tab</a></li>
    <li><a href="#tab2">Second tab</a></li>
    <li><a href="#tab3">Third tab</a></li>
</ul>
    <div class="tab-folder">
    <div id="tab2" class="tab-content">Content of second tab</div>
    <div id="tab3" class="tab-content">Content of third tab</div>
    <div id="tab1" class="tab-content">Content of first tab</div>
</div>

CSS styling for this structure would be:

.tab-folder > .tab-content:target ~ .tab-content:last-child, .tab-folder > .tab-content {
    display: none;
}
.tab-folder > :last-child, .tab-folder > .tab-content:target {
    display: block;
}

Considered by many as the most elegant solution, especially when accessibility and CSS support are crucial factors to consider.

Answer №2

Discovered this valuable resource that could potentially address your inquiry

http://css-tricks.com/functional-css-tabs-revisited/

Check out the demo here: http://css-tricks.com/examples/CSSTabs/radio.php

<div class="tabs">

   <div class="tab">
       <input type="radio" id="tab-1" name="tab-group-1" checked>
       <label for="tab-1">Tab One</label>

       <div class="content">
           content goes here
       </div> 
   </div>

   <div class="tab">
       <input type="radio" id="tab-2" name="tab-group-1">
       <label for="tab-2">Tab Two</label>

       <div class="content">
           content goes here
       </div> 
   </div>

    <div class="tab">
       <input type="radio" id="tab-3" name="tab-group-1">
       <label for="tab-3">Tab Three</label>

       <div class="content">
           content goes here
       </div> 
   </div>

</div>

CSS Styles

.tabs {
  position: relative;   
  min-height: 200px; /* This part sucks */
  clear: both;
  margin: 25px 0;
}
.tab {
  float: left;
}
.tab label {
  background: #eee; 
  padding: 10px; 
  border: 1px solid #ccc; 
  margin-left: -1px; 
  position: relative;
  left: 1px; 
}
.tab [type=radio] {
  display: none;   
}
.content {
  position: absolute;
  top: 28px;
  left: 0;
  background: white;
  right: 0;
  bottom: 0;
  padding: 20px;
  border: 1px solid #ccc; 
}
[type=radio]:checked ~ label {
  background: white;
  border-bottom: 1px solid white;
  z-index: 2;
}
[type=radio]:checked ~ label ~ .content {
  z-index: 1;
}

Answer №3

A unique approach is taken with this method, which differs slightly from the :target method by using overflow and named anchors instead. One of the advantages is that your CSS doesn't need to have any knowledge about dynamic content. The generated markup only needs to align with:

<a href="#myFirstTab">Tab A</a>
in the navigation, accompanied by

<a name="myFirstTab"></a>
inside the tab itself (preferably at the end).

An interesting aspect of this method is that it relies on three simple CSS selectors, all of which are classes. This eliminates the strict requirements associated with IDs.

The concept involves creating a viewport with specific dimensions, positioned relatively or absolutely somewhere on the page. This viewport serves as the display area for the tabs. Rather than using display: none, overflow clipping is utilized to hide all tabs except the first one.

There are some challenges to overcome with this technique, such as ensuring proper content placement without partial scrolling. This is achieved by including a "clearance" div at the end of each tab to hold the named anchor. Any necessary adjustments are typically minor and straightforward.

For added functionality, the navigation links can be integrated into radio buttons to detect the "checked" status. Alternatively, the navigation can be duplicated in each tab with varying active classes. While redundant, this approach offers a dynamic navigation experience, potentially creating a 2D space. For practicality, toggling a class in the navigation with jQuery.toggle() is often sufficient.

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

Creating an alert message in React to notify users of incorrect data being uploaded to an array

Just getting started with React and looking to ensure that the csv data uploaded by users follows the specified standard of “currency, amount, price, timestamp”. If the user uploads data that doesn't meet this standard, an error alert is triggered ...

What is the preferred method for updating a variable value - Ajax or PHP?

I'm in the process of creating a dropdown survey for new visitors using cookies to collect data, but I'm a bit confused on how to implement it. If a button is clicked, the onClick event will trigger var answer1 = answer1 + 1 , or something simil ...

IE8 does not support Jquery ajax() for cross domain requests to remote servers

My current script includes an ajax request to a remote server that provides a plain text response. This setup functions properly in all browsers with the exception of IE8, which is not surprising. The script snippet looks like this: $.ajax({ url: &apos ...

"Implementing AngularJS bidirectional data binding to dynamically link user inputs with corresponding fields

Having trouble automatically outputting data with angularJS. One of the great features of angular is two-way data binding, but I can't seem to bind input with a JSON file. What I want to achieve is if the user's input matches a key, the correspon ...

Utilizing *ngfor in Angular 7 to Group and Display Data

I currently have incoming data structured like this in my Angular application Visit this link to see the data format https://i.stack.imgur.com/jgEIw.png What is the best way to group and sort the data by State and County, and present it in a table as sh ...

Is there a way to access a comprehensive list of all the font names stored on my personal computer?

I'm currently working on a project that requires using local fonts only. Since I am using a Mac, I have located the fonts in /Library/Fonts. However, I have encountered an issue when trying to use a font named 华文黑体 directly in my CSS property: ...

Exploring the use of barcodes with node.js

Having some issues with generating a barcode using a barcode module from NPMJS called npm i barcode. I am getting an error message res is not defined even after following the instructions. Can someone please guide me in the right direction? Here is my code ...

Issue with ThreeJs raycaster not returning correct event.clientY value when header bar is visible

Here's the issue: I'm trying to place a sphere on a 3D model when I click on it using ThreeJs raycaster. It works fine when the canvas covers the entire page, but if I add a header bar to the page, the positioning is off. Here are some visual ex ...

Is it better to conceal modals or completely eliminate them from the DOM when working with React?

I am currently developing a React application that involves multiple modals, with only one active at a time and no nested modals. I am torn between two approaches for handling the showing and hiding of these modals: The first approach involves having a b ...

The dimensions of the glyph icon placed inside a tab

http://jsfiddle.net/r9dunwzs/1/ <ul id="myTab" class="nav nav-tabs"> <li class="active"><a href="#home" data-toggle="tab">one</a></li> <li> <a href="#profile" data-toggle="tab"> ...

Error: An unexpected token '<' was encountered during the React Webpack build process

My ReactJs project is using Webpack4 and @babel/core 7. However, when I attempt to build the project, I encounter the following error in the terminal: ERROR in ./src/views/Pages/Login/Login.js Module build failed (from ./node_modules/babel-loader/lib ...

Angular allows for a maximum time span of 60 days between two date inputs

I am looking to implement a validation in JavaScript or TypeScript for Angular where the start date cannot be more than 60 days after the end date is entered. The requirement is to enforce a "maximum range of 60 days" between the two input dates (dateFro ...

Cannot find WoopraTracker within the custom event data

I am currently working on implementing Woopra custom event data upon page load by following their guidelines. I have attempted to push events when the page is ready, however, it keeps returning an error that woopratracker is not defined. Strangely, when ...

The Popover style from React-Bootstrap seems to be missing when applied to my component

Attempting to incorporate a Popover with overlay trigger from React - Bootstrap has proven to be quite the challenge. If you check this image, you'll see what it's supposed to look like. This is the code I used: var {Button, Overlay, OverlayTr ...

elements of bootstrap overlapping one another

I have created a website using Bootstrap, which can be accessed at this link. The homepage is experiencing alignment issues, with sections colliding with each other. To prevent this collision, I had to add margin-top like the example below: ...

Having difficulty launching a new window within an app built with Electron and Nexjs (Nextron)

Attempting to launch a (Nextjs-generated) page in a new window is causing an error message to appear: Uncaught ReferenceError: global is not defined Here is the full error: react-refresh.js?ts=1665849319975:10 Uncaught ReferenceError: global is not de ...

The SVG image does not display in browsers other than Internet Explorer (IE)

I am encountering an issue with adding a menu toggle image in SVG format to my HTML. Unfortunately, the image is not displaying as expected. Here are screenshots for comparison between Explorer and Chrome: https://i.stack.imgur.com/74sqh.png https://i. ...

The parent node is returning a child element

Currently working on a website using Vue 3.0 and Element+ and encountering an inconsistency. There is a div displayed on the page (an array of objects) and the goal is to remove the object from the array when a button is clicked. The issue arises when som ...

Steps for recreating a Jquery Mobile form element with the same name after destroying it

As I delve into Jquery Mobile, I encounter a scenario where I must dynamically generate form fields (select, input, etc) using the following approach: $fieldInput = $('<input type="text" name="' + fieldName + '" />'); Initially, ...

The table is refusing to align itself in the center

I've been struggling to center the text inside this table despite trying various solutions. Any help would be greatly appreciated. Here's the HTML code I have: <div id="paccount"> <table style="margin: 0 auto;"> <tr&g ...