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.
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.
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.
See the Pen
Curved Tabs by James Jones (@jamesjones)
on CodePen.
<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>
$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