skip to Main Content

I am trying to see if there is a way to create vertical tabs by changing the CSS only. The solution I am using works great for horizontal tabs and is CSS only. I am trying to see if I can modify the CSS to make it vertical tabs without changing the HTML.

[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>

I just need to know if there is a way to move the tab panels to the top right without using position absolute as I need to retain the height of them. Or if there is some way to do with flex-grow, shrink, basis, etc. for the tabs or using xxxx-self on the tabs or tab panels, etc.

Bonus if I can also align the tabs to the right with tab panels on the left.

2

Answers


  1. Chosen as BEST ANSWER

    Thanks @InSync, Yes it seems css-grid is the way to go, but I need a solution that doesn't require knowing the amount of tabs.

    I did find a solution, but does require adding a high number like 9999 to the grid-row and you can't use gap as it will add a lot up space with the high number on 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 want to change the tabs to the right side then you can just adjust the following:

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

  2. This kind of interface is most suitable for grid:

    [role="tablist"] {
      /* 2 columns & 3 rows, with the right part 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;
    }
    

    Try it:

    [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>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search