For decades there has only been two ways to create curved/flared tabs at the base:
- SVG images
- CSS with background trickery
Unfortunately both have downsides: Using an SVG image, the curve radius is set in stone (unless you embed it in the HTML and use some JavaScript/JS script to modify the path after loading). The CSS way has, to date, been the modern way to create a flared base… but there’s also a huge downside. You have to set the background color of the area above the flare. So if you wanted a more complex background – like a gradient or image – it becomes very tricky if not impossible to simulate.
The benefits of the new flared tabs method
Now there is a new CSS method that modern browsers support. It allows for using any background and style that you would like and even better, you can use CSS variables to set the curve radius and other factors!
You also don’t need to embed a vector image like SVG or link to it, requiring a separate image each time you need a different curve radius.
Additionally, no JS script is required. You don’t need to have a flash of uninitialized content if using above the fold such as a hero or banner section.
Since it doesn’t rely on having backgrounds set on the left & right sides of the tab, you are not bound by specific colors for the background behind the tabs. Use images, colors, gradients, even a video if you wish!
Lastly, you can use CSS variables to dynamically adjust the border radius (among other things).
Is the new flared tabs method supported by web browsers?
Using a combination of clip-path, which has been supported by browsers since 2020, and the new shape() function, which has been supported for the past year (as of 2026):
- Google Chrome 135 (and most variants like Microsoft Edge, Opera, Brave, Vivaldi, etc)
- Released April 1, 2025 (no, not an April Fools joke)
- Apple Safari 18.4 (Mac OSX, iOS)
- Released March 30, 2025
- Mozilla Firefox 148
- Released February 23, 2026
This new method may not work for those using older devices or browsers, but as of 2026 that is only 15% of users and falling (mostly due to some Google Chrome users going quite a while without an update).
How does this new flared tabs method work?
To create curved/flared tabs without using static vector images such as SVG, JS scripting, or resorting to CSS trickery, all you need to do is start with the CSS method but replace the :after and :before selectors with a clip path. It’s as easy as that.
Take a look at this example:
<section class="tabs">
<details open name="tab">
<summary><div class="tab-title"><div class="tab-inner-title">First Tab</div></div></summary>
<section class="tab-content">Just some tab content for the first tab.</section>
</details>
<details name="tab">
<summary><div class="tab-title"><div class="tab-inner-title">Second Tab</div></div></summary>
<section class="tab-content">Just some tab content for the second tab.</section>
</details>
<details name="tab">
<summary><div class="tab-title"><div class="tab-inner-title">Third Tab</div></div></summary>
<section class="tab-content">Just some tab content for the third tab.</section>
</details>
</section>And add the styling:
@property --tab-index {
syntax: '<integer>';
initial-value: 1;
inherits: true;
}
.tabs {
--tab-total: 3;
--tab--upper-radius: 20px;
--tab-lower-radius: 20px;
padding: 0.5rem;
counter-reset: tab-counter;
display: grid;
grid-template-columns: repeat(var(--tab-total), minmax(200px, 1fr));
grid-template-rows: auto;
column-gap: 0rem;
background-image: url(https://static.desygner.com/wp-content/uploads/sites/13/2022/05/04141642/Free-Stock-Photos-01.jpg);
background-size: cover;
backdrop-filter: blur(2);
&> details {
--tab-title-background: rgba(255, 255, 255, 0.4);
counter-increment: tab-counter;
--tab-count: counter(tab-counter);
--tab-index: sibling-index();
display: grid;
grid-column: 1 / -1;
grid-row: 1 / span 2;
grid-template-columns: subgrid;
grid-template-rows: subgrid;
&> summary {
grid-column: var(--tab-index) / span 1;
grid-row: auto;
display: grid;
padding: 0;
cursor: pointer;
z-index: 1;
padding: 0rem;
&> .tab-title {
display: flex;
width: 100%;
&> .tab-inner-title {
display: flex;
width: 100%;
padding: 1rem;
background: var(--tab-title-background);
border-radius: var(--tab--upper-radius) var(--tab--upper-radius) 0 0;
&, &:before, &:after {
backdrop-filter: blur(2px);
}
}
&:before, &:after {
content: "";
display: block;
background: var(--tab-title-background);
width: var(--tab-lower-radius);
height: 100%;
}
&:before {
clip-path: shape(
from 100% calc(100% - var(--tab-lower-radius)),
arc to 0% 100% of calc(var(--tab-lower-radius)) cw,
line to 100% 100%,
close
);
}
&:after {
clip-path: shape(
from 100% 100%,
arc to 0% calc(100% - var(--tab-lower-radius)) of calc(var(--tab-lower-radius)) cw,
line to 0% 100%,
close
);
}
}
}
&:not(:last-child) {
&> summary {
margin-right: -10px;
}
}
&:last-child {
&> summary {
margin-right: 0.5rem;
}
}
&:first-child {
&> summary {
margin-left: 0.5rem;
}
}
&[open] {
&> summary {
&> .tab-title {
--tab-title-background: rgba(255, 255, 255, 0.6);
}
}
}
&:not([open]) {
&::details-content {
display: none;
}
}
&::details-content {
grid-row: 2;
grid-column: 1 / -1;
padding: 0.4rem;
background: top left linear-gradient(to bottom, var(--tab-title-background), var(--tab-title-background));
color: white;
border-radius: 0.5rem;
}
& .tab-content {
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0.7));
padding: 0.5rem;
}
}
}Now let’s put it all together:
First Tab
Second Tab
Third Tab
Note: This won’t quite work in Firefox up to 150 yet as I am using sibling-count() to split the tabs into the grid layout. Unfortunately Firefox does not yet support that CSS function (but they are working on it).
If you are unable to see it due to a browser not supporting something, here is an image of it using the latest Chrome/Chromium 148:













