Phoenix News Desk

Home » News Desk » Rounded Manila Folder ... CSS Triangles

When building aberfoylehubccc.org.au we wanted the main navigation menu items to look like manila folder tabs. This meant it was necessary to add an outwardly flaring curve to the bottom of each nav menu item.

The inward curves at the top of each menu item are easily achieved with border-radius. But there is no way to implement an outward curve with border-radius. That outward curve is one of those things that should be easy but turns out to be a real pain to achieve with CSS.

We’re not the only ones who’ve tried to implement an outward curve.

  • CSS Tricks have a great tutorial and a sequel on creating a menu with rounded tabs. Unfortunately, their solution won’t work if your header background is anything more complex than a flat colour. Their method also won’t allow for menu items made up of different colours. The root of these two issues is that CSS Tricks uses two CSS circles which end up overlaid over the two adjacent menu items. These circles must be a flat colour and overlay an area of the same colour otherwise the effect falls apart.
  • orderedlist.com have their own implementation.

The Trick

Our solution was to layer several triangles on top of one another to approximate a curve. With enough triangles, the simulated curve becomes indistinguishable from an actual curve.  For a curve 25px in radius, we were able to achieve a seamless looking curve with 9 triangles.

For each menu item we have one curve on the left side and one on the the right so we need 18 CSS triangles. We can achieve 18 triangles with 6 <div> elements for each menu item. By using the :before and :after pseudo elements along with the div itself we get 6 x 3 =18 elements.

Therein lies the main downside of this solution. You have a bunch of extra <div> elements with no semantic purpose, only existing to make things look pretty. They add up to a lot of extra HTML in your menu. It helps if your menu is generated programmatically so you don’t have to add all this HTML manually. A day may come where we can have more than two pseudo elements per element – if that ever happens, this solution will become a lot more elegant. You can also cut down on the number of extra HTML elements by setting up pseudo elements from any semantic elements already there. Menu items tend to consist of at least <li> element and <a> element so that provides you with 4 triangles.

The only real bit of cross browser pain is when a 1px width gap sometimes appears between the triangle and the rectangle main menu element. These are fixed by shifting the triangles closer to the element by 0.5px.

The Result

You can see the results in the CodePen below. I’ve also pasted in the isolated HTML and SCSS to put the outwardly curved tabs in action.

CodePen Demo

See the Pen
Curved Tabs
by James Jones (@jamesjones)
on CodePen.

HTML

<nav class="menu_main_nav_area">
  <ul>
    <li>
      <a href="https://phoenixweb.com.au/">Home</a>
      <div class="curved-tabs curved-tabs-l curved-tabs-1"></div>
      <div class="curved-tabs curved-tabs-l curved-tabs-2"></div>
      <div class="curved-tabs curved-tabs-l curved-tabs-3"></div>
      <div class="curved-tabs curved-tabs-r curved-tabs-4"></div>
      <div class="curved-tabs curved-tabs-r curved-tabs-5"></div>
      <div class="curved-tabs curved-tabs-r curved-tabs-6"></div>
    </li>   
    <li>
      <a href="https://phoenixweb.com.au/">About Us</a>
      <div class="curved-tabs curved-tabs-l curved-tabs-1"></div>
      <div class="curved-tabs curved-tabs-l curved-tabs-2"></div>
      <div class="curved-tabs curved-tabs-l curved-tabs-3"></div>
      <div class="curved-tabs curved-tabs-r curved-tabs-4"></div>
      <div class="curved-tabs curved-tabs-r curved-tabs-5"></div>
      <div class="curved-tabs curved-tabs-r curved-tabs-6"></div>
     </li>
     <li>
       <a href="https://phoenixweb.com.au/">Children’s Rooms</a>
       <div class="curved-tabs curved-tabs-l curved-tabs-1"></div>
       <div class="curved-tabs curved-tabs-l curved-tabs-2"></div>
       <div class="curved-tabs curved-tabs-l curved-tabs-3"></div>
       <div class="curved-tabs curved-tabs-r curved-tabs-4"></div>
       <div class="curved-tabs curved-tabs-r curved-tabs-5"></div>
       <div class="curved-tabs curved-tabs-r curved-tabs-6"></div>
     </li>
     <li>
       <a href="https://phoenixweb.com.au/">Events</a>
       <div class="curved-tabs curved-tabs-l curved-tabs-1"></div>
       <div class="curved-tabs curved-tabs-l curved-tabs-2"></div>
       <div class="curved-tabs curved-tabs-l curved-tabs-3"></div>
       <div class="curved-tabs curved-tabs-r curved-tabs-4"></div>
       <div class="curved-tabs curved-tabs-r curved-tabs-5"></div>
       <div class="curved-tabs curved-tabs-r curved-tabs-6"></div>
     </li>
     <li>
       <a href="https://phoenixweb.com.au/">Contact Us</a>
       <div class="curved-tabs curved-tabs-l curved-tabs-1"></div>
       <div class="curved-tabs curved-tabs-l curved-tabs-2"></div>
       <div class="curved-tabs curved-tabs-l curved-tabs-3"></div>
       <div class="curved-tabs curved-tabs-r curved-tabs-4"></div>
       <div class="curved-tabs curved-tabs-r curved-tabs-5"></div>
       <div class="curved-tabs curved-tabs-r curved-tabs-6"></div>
     </li>
  </ul>
</nav>

SCSS

$corner-tab-size: 30px;
$triangle-color1: #f1f1f1;
$triangle-color2: #e1e1e1;

$accent-colour-1: #f0d001;
$accent-colour-2: #95c93d;
$accent-colour-3: #c768ff;
$accent-colour-4: #f48a4e;

@mixin border-radius-top($border-radius-size) {
  -webkit-border-top-left-radius: $border-radius-size;
  -webkit-border-top-right-radius: $border-radius-size;
  -moz-border-radius-topleft: $border-radius-size;
  -moz-border-radius-topright: $border-radius-size;
  border-top-left-radius: $border-radius-size;
  border-top-right-radius: $border-radius-size;
}

nav {
  display: block;
  margin-left: $corner-tab-size;

  ul {
    margin: 0;
    padding: 0;
    list-style-type: none;
    
    > li {
      z-index: 2;
      @include border-radius-top($corner-tab-size);
      background-color: $triangle-color1;
      border-top-width: 0.5em;
      border-top-style: solid;
      box-sizing: content-box;
      min-height: 4em;
      position: relative;
      display: block;
      float: left;
      
      a {
        padding: 2em;
        color: #a6a6a6;
        text-decoration: none;
        color: #232a34;
        display: block;
      }

      .curved-tabs,
      .curved-tabs:before,
      .curved-tabs:after {
        position: absolute;
        content: '';
        width: 0;
        height: 0;
        bottom: 0;
        border-style: solid;
      }

      .curved-tabs-l,
      .curved-tabs-l:before,
      .curved-tabs-l:after {
        border-color: transparent transparent $triangle-color1 transparent;
      }

      .curved-tabs-r,
      .curved-tabs-r:before,
      .curved-tabs-r:after {
        border-color: transparent transparent transparent $triangle-color1;
      }
    
      .curved-tabs-1 {
        border-width: 0 0 round($corner-tab-size*0.9) round($corner-tab-size*0.18);
        left: -1* round($corner-tab-size*0.18) + 0.5px;
      }

      .curved-tabs-1:before {
        border-width: 0 0 round($corner-tab-size*0.18) round($corner-tab-size*0.9);
        right: 0;
        bottom: -1 * round($corner-tab-size*0.9);
      }

      .curved-tabs-1:after {
        border-width: 0 0 round($corner-tab-size*0.4) round($corner-tab-size*0.74);
        right: 0;
        bottom: -1 * round($corner-tab-size*0.9);
      }

      .curved-tabs-2 {
        border-width: 0 0 round($corner-tab-size*0.74) round($corner-tab-size * 0.4);
        left: -1 * round($corner-tab-size*0.4) + 0.5px;
      }

      .curved-tabs-2:before {
        border-width: 0 0 round($corner-tab-size*0.8) round($corner-tab-size * 0.32);
        right: 0;
        bottom: -1 * round($corner-tab-size*0.74);
      }

      .curved-tabs-2:after {
        border-width: 0 0 round($corner-tab-size*0.32) round($corner-tab-size * 0.8);
        right: 0;
        bottom: -1 * round($corner-tab-size*0.74);
      }

      .curved-tabs-3 {
        border-width: 0 0 round($corner-tab-size*0.67) round($corner-tab-size * 0.50);
        left: -1 * round($corner-tab-size*0.5) + 0.5px;
      }

      .curved-tabs-3:before {
        border-width: 0 0 round($corner-tab-size*0.50) round($corner-tab-size * 0.67);
        right: 0;
        bottom: -1 * round($corner-tab-size*0.67);
      }

      .curved-tabs-3:after {
        border-width: 0 0 round($corner-tab-size*0.58) round($corner-tab-size * 0.58);
        right: 0;
        bottom: -1 * round($corner-tab-size*0.67);
      }

      .curved-tabs-4 {
        border-width: round($corner-tab-size*0.9) 0 0 round($corner-tab-size*0.18);
        right: -1 * round($corner-tab-size*0.18) + 0.5px;
      }

      .curved-tabs-4:before {
        border-width: round($corner-tab-size*0.18) 0 0 round($corner-tab-size*0.9);
        left: -1 * round($corner-tab-size*0.18);
      }

      .curved-tabs-4:after {
        border-width: round($corner-tab-size*0.4) 0 0 round($corner-tab-size*0.74);
        left: -1 * round($corner-tab-size*0.18);
      }

      .curved-tabs-5 {
        border-width: round($corner-tab-size*0.74) 0 0 round($corner-tab-size * 0.4);
        right: -1* round($corner-tab-size*0.4) + 0.5px;
      }

      .curved-tabs-5:before {
        border-width: round($corner-tab-size*0.8) 0 0 round($corner-tab-size * 0.32);
        left: -1 * round($corner-tab-size*0.4);
      }

      .curved-tabs-5:after {
        border-width: round($corner-tab-size*0.32) 0 0 round($corner-tab-size * 0.8);
        left: -1 * round($corner-tab-size*0.4);
      }

      .curved-tabs-6 {
        border-width: round($corner-tab-size*0.67) 0 0 round($corner-tab-size * 0.50);
        right: -1 * round($corner-tab-size*0.5) + 0.5px;
      }

      .curved-tabs-6:before {
        border-width: round($corner-tab-size*0.50) 0 0 round($corner-tab-size * 0.67);
        left: -1 * round($corner-tab-size*0.5);
      }

      .curved-tabs-6:after {
        border-width: round($corner-tab-size*0.58) 0 0 round($corner-tab-size * 0.58);
        left: -1 * round($corner-tab-size*0.5);
      }
    }

    //alternating light grey
    > li:nth-child(2n) {
      background-color: $triangle-color2;
      z-index: 1;

      .curved-tabs-l,
      .curved-tabs-l:before,
      .curved-tabs-l:after {
        border-color: transparent transparent $triangle-color2 transparent;
      }

      .curved-tabs-r,
      .curved-tabs-r:before,
      .curved-tabs-r:after {
        border-color: transparent transparent transparent $triangle-color2;
      }
    }

    > li:hover,
    > li:focus {
      z-index: 3;
    }

    > li:nth-child(4n) {
      border-top-color: $accent-colour-1;

      &:hover, &:focus {
        background: $accent-colour-1;

        .curved-tabs-l,
        .curved-tabs-l:before,
        .curved-tabs-l:after {
          border-color: transparent transparent $accent-colour-1 transparent;
        }

        .curved-tabs-r,
        .curved-tabs-r:before,
        .curved-tabs-r:after {
          border-color: transparent transparent transparent $accent-colour-1;
        }
      }
    }

    > li:nth-child(4n+1) {
      border-top-color: $accent-colour-2;

      &:hover, &:focus {
        background: $accent-colour-2;

        .curved-tabs-l,
        .curved-tabs-l:before,
        .curved-tabs-l:after {
          border-color: transparent transparent $accent-colour-2 transparent;
        }

        .curved-tabs-r,
        .curved-tabs-r:before,
        .curved-tabs-r:after {
          border-color: transparent transparent transparent $accent-colour-2;
        }
      }
    }

    > li:nth-child(4n+2) {
      border-top-color: $accent-colour-3;
      &:hover, &:focus {
        background: $accent-colour-3;

        .curved-tabs-l,
        .curved-tabs-l:before,
        .curved-tabs-l:after {
          border-color: transparent transparent $accent-colour-3 transparent;
        }

        .curved-tabs-r,
        .curved-tabs-r:before,
        .curved-tabs-r:after {
          border-color: transparent transparent transparent $accent-colour-3;
        }
      }
    }

    > li:nth-child(4n+3) {
      border-top-color: $accent-colour-4;

      &:hover, &:focus {
        background: $accent-colour-4;

        .curved-tabs-l,
        .curved-tabs-l:before,
        .curved-tabs-l:after {
          border-color: transparent transparent $accent-colour-4 transparent;
        }

        .curved-tabs-r,
        .curved-tabs-r:before,
        .curved-tabs-r:after {
          border-color: transparent transparent transparent $accent-colour-4;
        }
      }
    }
  }
}
Leave a reply

Search Site
Folding@Home contribution stats for team Phoenix Web Development
Team ID 230741
Grand score (points) 70,781,163
Work units completed 6,673
Team Ranking 6,315 of 229,570 teams
Report generated on October 4, 2024, 1:53 am
Phoenix Web Development donors (top 5 donors of 6)
James_Jones 52,567,622
Vicki_Jones 16,995,971
Inspiron7570Laptop 870,876
Anonymous 339,452
Barnes 6,000

Folding@home allows anyone to assist with disease research by donating their unused computer processing power. To join in, simply download the F@H software.

Latest From The Phoenix News Desk
Back to top