Search code examples
csscss-selectorstabsborder-radius

Tabbed navbar with border radius


Is this possible in css? I have found example of tabs which has background color. But none with plain borders that has border radius!

https://www.loom.com/i/23516b83849a4c1e87129b8d8bf1fd4f


Solution

  • You can achieve this by using additional elements (such as the before and after pseudo elements) to create borders on the top or bottom half of each tab.

    Here is an example that uses the before element of each tab to create a border on the top half of the active tab, and a border on the bottom half of the inactive tabs. Then it uses the after element of the first and last tabs to complete the ends.

    nav {
      padding: 10px;
    
      --border-width: 2px;
      --border: var(--border-width) solid;
      --border-radius: 10px;
    }
    
    nav a {
      /* capture before/after elements within tab */
      position: relative;
      padding: 5px 10px;
      /* add a negative margin so the tabs join borders */
      /* alternatively, you could make the before/after elements a little larger than the tab */
      margin: 0 calc(var(--border-width) / -2);
      cursor: pointer;
    }
    
    /* use before element as a floating border for either the top half or the bottom half */
    nav a:before {
      content: '';
      position: absolute;
      left: 0;
      right: 0;
      height: 50%;
      border: var(--border);
    }
    
    nav a.active:before {
      top: 0;
      border-bottom: none;
      border-top-left-radius: var(--border-radius);
      border-top-right-radius: var(--border-radius);
    }
    
    nav a:not(.active):before {
      top: 50%;
      border-top: none;
      border-left: none;
      border-right: none;
    }
    
    /* use after element as floating border for the ends of the tab group */
    nav a:first-child:after,
    nav a:last-child:after {
      content: '';
      position: absolute;
      bottom: 0;
      height: 50%;
      width: var(--border-radius);
      border-bottom: var(--border);
      margin: calc(var(--border-width) / -1);
    }
    
    nav a:first-child:after {
      right: 100%;
    }
    
    nav a:last-child:after {
      left: 100%;
    }
    
    nav a.left-of-active:before,
    nav a.active:first-child:after {
      border-right: var(--border);
      border-bottom-right-radius: var(--border-radius);
    }
    
    nav a.right-of-active:before,
    nav a.active:last-child:after {
      border-left: var(--border);
      border-bottom-left-radius: var(--border-radius);
    }
    <nav>
      <a class="active">
        Page 1
      </a>
      <a class="right-of-active">
        Page 2
      </a>
      <a>
        Page 3
      </a>
    </nav>
    
    <nav>
      <a class="left-of-active">
        Page 1
      </a>
      <a class="active">
        Page 2
      </a>
      <a class="right-of-active">
        Page 3
      </a>
    </nav>
    
    <nav>
      <a>
        Page 1
      </a>
      <a class="left-of-active">
        Page 2
      </a>
      <a class="active">
        Page 3
      </a>
    </nav>