ARTICLE AD BOX
I have a layout where tabs are visually part of the same gradient container.
The block consists of:
.purchase-tabs — 3 buttons at the top
.purchase-panel — the main panel below
The panel () has a gradient background and looks correct..purchase-panel
What I want
When a tab is active, I want it to look like it’s cut out from the same parent gradient, i.e. like a window into the gradient behind it.
Meaning:
the gradient must NOT restart inside the tab button
the active tab background should be the same exact gradient slice that exists at that position in the main container
visually it should look like one continuous gradient across the whole block
So the active tab should match the panel gradient seamlessly. BAD RESULT -> GOOD RESULT
"use client"; import { useState } from "react"; type TabType = "gamepass" | "giftcard" | "superpass"; export default function PurchaseMethods() { const [activeTab, setActiveTab] = useState<TabType>("gamepass"); return ( <section className={`purchase-methods-section purchase-methods--${activeTab}`}> <div className="purchase-methods-container"> {/* 3 tabs */} <div className="purchase-tabs"> <button className={`purchase-tab ${activeTab === "gamepass" ? "active" : ""}`} onClick={() => setActiveTab("gamepass")} type="button" > 1 </button> <button className={`purchase-tab ${activeTab === "giftcard" ? "active" : ""}`} onClick={() => setActiveTab("giftcard")} type="button" > 2 </button> <button className={`purchase-tab ${activeTab === "superpass" ? "active" : ""}`} onClick={() => setActiveTab("superpass")} type="button" > 3 </button> </div> {/* content 1/2/3 */} <div className="purchase-panel"> <div className="purchase-content">Content {activeTab}</div> </div> </div> </section> ); } /* Purchase Methods Section */ .purchase-methods-section { display: flex; flex-direction: column; gap: 16px; width: 100%; max-width: 1376px; margin: 0 auto; } .purchase-methods-header { margin: 0; font-size: 24px; font-weight: 500; color: var(--text); } .purchase-methods-container { width: 100%; position: relative; filter: drop-shadow(8px 4px 30px rgba(138, 126, 87, 0.12)); } /* Tabs */ .purchase-tabs { display: grid; grid-template-columns: 1fr 1fr 1fr; width: 100%; isolation: isolate; border-radius: 20px 20px 0 0; overflow: hidden; } .purchase-tab { display: flex; justify-content: center; align-items: center; padding: 16px 10px; height: 55px; background: transparent; border: none; font-size: 20px; font-weight: 500; color: var(--accent); cursor: pointer; position: relative; transition: all 0.3s ease; } .purchase-tab:first-child { border-radius: 20px 0 0 0; } .purchase-tab:last-child { border-radius: 0 20px 0 0; } .purchase-tab.active { background: linear-gradient(95deg, #E4D497 0%, #DECA83 29.91%, #C8B46F 74.42%, #AF9A5C 99.71%); color: #fff; border-radius: 20px 20px 0 0; } .purchase-tab.active:first-child { border-radius: 20px 20px 0 0; } .purchase-tab.active:last-child { border-radius: 20px 20px 0 0; } /* Content Panel */ .purchase-panel { width: 100%; background: linear-gradient(95deg, #E4D497 0%, #DECA83 29.91%, #C8B46F 74.42%, #AF9A5C 99.71%); border-radius: 0 0 20px 20px; padding: 40px 32px 32px; } .purchase-content { max-width: 913px; margin: 0 auto; display: flex; flex-direction: column; gap: 30px; } .purchase-title { margin: 0; text-align: center; font-size: 28px; font-weight: 500; color: #fff; }