A Step-by-Step Guide to Creating Vertical Tabs Using Flexbox in CSS

I have been experimenting with CSS to create vertical tabs without altering the HTML structure. The current CSS solution I am using works perfectly for horizontal tabs. Is it possible to tweak the CSS code to achieve the desired layout change?

[role=tablist] {
  display: flex;
  flex-direction: column;
  background: #eee;
  width: 400px;
  margin: auto;
}

label {
  border: 1px solid #ddd;
  padding: 1em;
  cursor: pointer;
  display: block;
  width: 70px;
}

[role=tabpanel] {
  order: 9999;
  display: none;
  padding: 1em;
}

label:has(:checked) + [role=tabpanel] {
  display: block;
}
<div role="tablist">
    <label>
        Tab 1
        <input name="tablist" type="radio" checked="">
    </label>
    <div role="tabpanel">
        Tab 1 content. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
    </div>
    <label role="tab">
        Tab 2
        <input name="tablist" type="radio">
    </label>
    <div role="tabpanel">
        Tab 2 content. Invidunt ut labore et dolore magna aliquyam erat
    </div>
    <label role="tab">
        Tab 3
        <input name="tablist" type="radio">
    </label>
    <div role="tabpanel">
        Tab 3 content. Lorem ipsum dolor sit amet, consetetur sadipscing elitr
    </div>
</div>

Is there a way to position the tab panels on the top right without resorting to absolute positioning? I want to maintain their height. Alternatively, can flex-grow, shrink, basis, or use of <i>xxxx</i>-self properties help in achieving this layout adjustment for the tabs or tab panels?

An additional challenge would be aligning the tabs to the right while keeping the tab panels on the left side.

Answer №1

When creating a grid interface, consider the following CSS:

[role="tablist"] {
  /* Create a grid layout with 2 columns and 3 rows, where the right part is marked as "d" */
  display: grid;
  grid-template-columns: 1fr 3fr;
  grid-auto-rows: 1fr;
  grid-template-areas:
    'a d'
    'b d'
    'c d';
}

label {
  grid-column: 1;
}

[role="tabpanel"] {
  /* Assign any visible panel to the "d" area */
  grid-area: d;
}

Experiment with it by using the following code snippet:

[role="tablist"] {
  display: grid;
  grid-template-columns: 1fr 3fr;
  grid-auto-rows: 1fr;
  grid-template-areas:
    'a d'
    'b d'
    'c d';
  margin: auto;
  height: 450px;
  width: 400px;
  background: #eee;
}

label {
  grid-column: 1;
  box-sizing: border-box;
  border: 1px solid #ddd;
  padding: 1em;
  cursor: pointer;
}

[role="tabpanel"] {
  display: none;
  grid-area: d;
  padding: 1em;
}

label:has(:checked) + [role="tabpanel"] {
  display: block;
}
<div role="tablist">
  <label role="tab">
    Tab 1
    <input name="tablist" type="radio" checked>
  </label>
  <div role="tabpanel">
    Tab 1 content. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,
    no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo
    dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
  </div>
  <label role="tab">
    Tab 2
    <input name="tablist" type="radio">
  </label>
  <div role="tabpanel">
    Tab 2 content. Invidunt ut labore et dolore magna aliquyam erat
  </div>
  <label role="tab">
    Tab 3
    <input name="tablist" type="radio">
  </label>
  <div role="tabpanel">
    Tab 3 content. Lorem ipsum dolor sit amet, consetetur sadipscing elitr
  </div>
</div>

Answer №2

Appreciate the input, @InSync! It does appear that utilizing css-grid is the optimal approach in this scenario. However, I'm seeking a solution that doesn't hinge on knowing the exact number of tabs beforehand.

After some exploration, I did discover a workaround. This workaround involves assigning a high value like 9999 to the grid-row property. Unfortunately, using the gap property with such a large number results in excessive spacing within the grid row.

[role=tablist] {
  display: grid;
  background: #eee;
  width: 600px;
  margin: auto;
  grid-template-columns: 1fr 3fr;
}

label {
  border: 1px solid #ddd;
  padding: 1em;
  cursor: pointer;
  display: inline-flex;
}

[role=tabpanel] {
  grid-column: 2;
  grid-row: 1 / 9999;
  display: none;
  padding: 1em;
}

label:has(:checked) + [role=tabpanel] {
  display: block;
}
<div role="tablist">
    <label>
        Tab 1
        <input name="tablist" type="radio" checked="">
    </label>
    <div role="tabpanel">
        Tab 1 content. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
    </div>
    <label role="tab">
        Tab 2
        <input name="tablist" type="radio">
    </label>
    <div role="tabpanel">
        Tab 2 content. Invidunt ut labore et dolore magna aliquyam erat
    </div>
    <label role="tab">
        Tab 3
        <input name="tablist" type="radio">
    </label>
    <div role="tabpanel">
        Tab 3 content. Lorem ipsum dolor sit amet, consetetur sadipscing elitr
    </div>
</div>

If you wish to shift the tabs to the right side, you can simply modify the following:

[role=tablist] {
  grid-template-columns: 3fr 1fr;
}

label {
  grid-column: 2;
}

[role=tabpanel] {
  grid-column: 1;
}

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

The scaling of the slick carousel image is not working as expected

Having an issue with the Slick carousel where images are not resizing based on browser size (original size is 300x228px). Just to clarify: When I shrink the browser window, the number of slides decreases but the images remain the same size. I've bee ...

Tips for preventing a dynamic textbox from shifting other elements as it expands

Trying to explain the question clearly, I have a table with a textbox at the bottom where users can expand it by grabbing the corner. However, when they do so, other fields also move along with it. The setup of this form in a two-column table was inherited ...

The child div can be scrolled horizontally, while the parent window remains fixed

I am facing a challenge with my HTML and CSS setup. I want to create a child div that scrolls horizontally, but I do not want the parent window to scroll along with it. Below is my current code: <div id="parent"> <div id="div1"> . ...

The functionality of display flex is not functioning as expected outside of the CodePen

I attempted to create a responsive two-column layout on Codepen with success. The layout is quite simple, featuring a YouTube video and some text. However, when I tried to transfer this to my website, it failed to work... Here is the code – hoping someo ...

What could be causing the inaccuracies in my precise web design layout?

Struggling with modifying HTML using Javascript? Take a look at this example: https://jsfiddle.net/02mwyvyo/ The objective is to shift a specific element downwards on the page. This involves inserting a spacer div before the target element, with style att ...

When the page is scrolled, the div is fixed in place and a class is dynamically added. Some issues may

Greetings everyone, I have a webpage with two floating divs - one is about 360px wide and the other has an auto width. As the page scrolls, the left div is assigned a class that fixes it to the screen, allowing the other div to scroll. This functionality w ...

The webpage must be designed to be compatible with screen resolutions starting from 800 x 600 pixels and higher, utilizing Angular

I am working on developing a webpage that is specifically designed to work for resolutions of 800 x 600 pixels and higher. Any other resolutions will display the message "This website can only be accessed from desktops." Here is my approach using jQuery: ...

Tips on creating a slow and gradual border animation that unfolds smoothly

I am looking to create an animation effect on a border, gradually revealing it like in this Codepen example. However, my specific requirements are: The previous line should not be removed, but rather shown along with the new border. The border color ...

Drag near the bottom of a droppable DIV to scroll inside

Within a scrollable div, I have multiple draggable divs. However, when I drag them into another scrollable div (the droppable zone), only the page scrolls and not the droppable div itself. How can I make it so that only the droppable div scrolls while drag ...

Guide to setting up a node.js server that serves HTML files with CSS styling

I am currently working on setting up a simple node.js server for my HTML using http and express. Everything is functioning properly, but the CSS is not displaying as expected. Here is the code snippet for my server setup: const express = require("express ...

Selenium can locate an element by its CSS selector that comes after a specific element

How can I locate the text "Interesting" which is the first occurrence of the class b after h1.important when using Selenium? <div class="a"> <div class="b">Not interesting</div> </div> <div class="title"> <h1 c ...

Issues with font face rendering on Android Chrome and Firefox devices

I'm currently encountering an issue with the font face in CSS3. The code I have been using is as follows: @font-face { font-family: James Fajardo; src: url('https://www.twoseven.nl/kurkorganicwines/wp- content/themes/kurk/fonts/James_Fajardo.t ...

I.E Compatibility Problem with Button CSS Styling

I've created a button with some styling that looks great on Firefox and Chrome, but unfortunately doesn't work quite right on Internet Explorer (all versions). Check out the JsFiddle DEMO : http://jsfiddle.net/Mhded/1/ Below is the code I' ...

"Transitioning from jQuery to Vanilla Javascript: Mastering Scroll Animations

I'm seeking guidance on how to convert this jQuery code into pure Javascript. $('.revealedBox').each(function() { if ($(window).scrollTop() + $(window).height() > $(this).offset().top + $(this).outerHeight()) { $(this).addCla ...

Guide on combining vendor CSS files in a React application using Webpack

Incorporating third-party libraries is an essential part of my project. For example, I have Mapbox GL installed via npm, which comes with CSS files needed for its functionality. The Mapbox GL CSS file can be found at mapbox-gl/dist/mapbox-gl.css in the no ...

Adjusting the size of text according to the image and screen dimensions with Bootstrap

If you want to take a look at my SSCCE, here is the jsFiddle link. However, I'll provide an overview of my code below. My page is created using Twitter Bootstrap 4.0: <!DOCTYPE HTML> <html> <head> <title>FooBar</title&g ...

Creating dynamic tables with jquery mobile

When the screen width decreases, I need to find a way to position 3 tables below each other without using float or breaking the jquery mobile layout. Using float: left; on the surrounding containers of each table is not an option as it disrupts the jquery ...

Embed a video within an image while ensuring it remains responsive on all devices

I have a picture that resembles something like this one My goal is to embed a video into it while maintaining its aspect ratio when the screen size is reduced. The responsive design should only affect the width since the image will be displayed in portrai ...

What is the best way to obtain the final HTML output once all scripts have been executed

Is there a way to obtain the final HTML after all scripts have been executed? The scripts on the page are adding and changing controls and CSS, and I want to see the HTML of the display as a static page. Is there a method to achieve this? Edit: For exa ...

Exploring the effective utilization of bootstrap's push and pull functionalities

I've been struggling to rearrange my bootstrap columns for mobile view, but my code just isn't cooperating. It's likely that I'm making a mistake somewhere. Here is the snippet of my code: <div class="container"> <div cla ...