0

I initially had some tabs created with radio buttons and labels which are linked to corresponding divs using their IDs and was working fine. But the problem is I am now creating the radio button tabs and their corresponding divs dynamically and wish to still allow my css to know which one should be open when a radio button is checked.

My CSS:

  #tab-1:checked~.content #content-1,
  #tab-2:checked~.content #content-2,
  #tab-3:checked~.content #content-3,
  #tab-4:checked~.content #content-4,
  #tab-4:checked~.content #content-5 {
      display: block;
  }

With the above initially, when the radio button with id of tab-1 is checked, the div with id of content-1 is displayed but right now this will no longer work for me as I am now creating the radio buttons dynamically using incoming IDs from my DB like: #tab-100, #tab-101, #tab-102 and the divs as well #content-100, #content-101, #content-102. I need my CSS to be dynamic as well so when #tab-100 is checked, it automatically displays #content-100. I am aware I can do this with javascript but I want to believe that there is a way to do it with CSS.

emmaakachukwu
  • 515
  • 1
  • 7
  • 16

2 Answers2

1

You could give the tab and content elements a class (e.g. tab and tab-content) and select the desired element with the :nth-of-type selector and the corresponding number.

If for example the first tab is checked (.tab:nth-of-type(1):checked), select the first content (.tab-content:nth-of-type(1)) and make it visible (e.g. display: block).

.tab-content {
  display: none;
}

.tab:nth-of-type(1):checked ~ .tab-content:nth-of-type(1),
.tab:nth-of-type(2):checked ~ .tab-content:nth-of-type(2),
.tab:nth-of-type(3):checked ~ .tab-content:nth-of-type(3) {
  display: block;
}
<input type="radio" id="tab-231" class="tab" name="number" value="first"><label for="tab-231">First</label><br>
<input type="radio" id="tab-232" class="tab" name="number" value="second"><label for="tab-232">Second</label><br>
<input type="radio" id="tab-233" class="tab" name="number" value="third"><label for="tab-233">Third</label><br>

<div class="tab-content">First content</div>
<div class="tab-content">Second content</div>
<div class="tab-content">Third content</div>

Edit

Unfortunately, I am not aware of any CSS-only solution that would automatically provide the desired selectors for the generated elements.

But there is another way how to solve the problem. In this solution, the placement of the tab and the tab-content are dependent on each other. So - if your circumstances allow it - you must always place the tab-content after the corresponding tab, as you can see in the following example:

.wrapper {
  position: relative;
  padding-bottom: 2rem;
}
.tab-content {;
  display: none;
  position: absolute;
  bottom: 0;
}
.tab:checked ~ .tab-content {
  display: block;
}
.tab:checked ~ .tab-content ~ .tab-content {
  display: none;
}
 <div class="wrapper">
 
  <input type="radio" id="tab-231" class="tab" name="number" value="first"><label for="tab-231">First</label><br>
  <div id="tab-231" class="tab-content">First content</div>

  <input type="radio" id="tab-232" class="tab" name="number" value="second"><label for="tab-232">Second</label><br>
  <div id="tab-232" class="tab-content">Second content</div>

  <input type="radio" id="tab-233" class="tab" name="number" value="third"><label for="tab-233">Third</label><br>
  <div id="tab-233" class="tab-content">Third content</div>

</div>
  • the issue here is I am not certain of the number of data coming in so I cannot possible write the nth-type of all the incoming data hard codedly – emmaakachukwu Jun 01 '21 at 09:00
0

I later resorted to using javascript and dynamically created a style element.

HTML:

<input type="radio" id="tab-231" class="tab" name="number" value="first"><label for="tab-231">First</label><br>
<input type="radio" id="tab-232" class="tab" name="number" value="second"><label for="tab-232">Second</label><br>
<input type="radio" id="tab-233" class="tab" name="number" value="third"><label for="tab-233">Third</label><br>

<div class="tab-content" class="tabs">First content</div>
<div class="tab-content" class="tabs">Second content</div>
<div class="tab-content" class="tabs">Third content</div>

JS:

const tabs = $('.tabs') //getting all the inputs with class tab
let css = '';

   //dynamically select the tab elements
   for ( const tab of tabs ) {
      const split = tab.id.split('-');
      const id = split[split.length - 1];
      css += `
         #tab-${id}:checked~.content #content-${id},
      `;
   }

   css = css.trim().slice(0, -1) //make sure to remove the trailing ',' in the css text
   css += `
      {
         display: block;
      }
   `;

   //create style element and append to document head
   const style = document.createElement('style');
   document.head.appendChild(style);

   if (style.styleSheet)
      style.styleSheet.cssText = css;
   else
      style.appendChild(document.createTextNode(css));

this answer was helpful.

emmaakachukwu
  • 515
  • 1
  • 7
  • 16