11 CSS Page Transitions09 / 11
Vertical Split Curtain
Two full-height panels slide closed like theatre curtains, swap the page, then split apart with a different easing — a gold-seamed theatrical reveal. A Parisian haute couture house.
Published
This is a full-page demo — interact inside the frame above, or open it in the playground for the full-screen experience.
The code
<!-- Curtain panels -->
<div class="curtain-left" id="cLeft"></div>
<div class="curtain-right" id="cRight"></div>
<div class="pages">
<div class="page active" id="p0">
<div class="p0-layout">
<div class="p0-left">
<div class="p0-mark">Maison Lécluse · Paris</div>
<div class="p0-main">
<div class="p0-season">Automne–Hiver 2025</div>
<h1 class="p0-title">Entre<br>Ombre<br>& Lumière</h1>
<div class="p0-title-fr">Between shadow and light</div>
<p class="p0-body">A collection born from the silences between words. Forty-two looks. Each one a conversation the body has alone.</p>
<button class="p0-cta" data-next="1">Discover the collection <span class="p0-cta-arrow"></span></button>
</div>
</div>
<div class="p0-right">
<div class="silhouette-area">
<div class="figure">
<div class="fig-head"></div>
<div class="fig-arm fig-arm-l"></div>
<div class="fig-arm fig-arm-r"></div>
<div class="fig-body"></div>
</div>
</div>
<div class="p0-right-bottom">
<div class="p0-detail-row"><div class="det-key">Maison</div><div class="det-val">Since 1967</div></div>
<div class="p0-detail-row"><div class="det-key">Ateliers</div><div class="det-val">Paris · Florence</div></div>
<div class="p0-detail-row"><div class="det-key">Collection</div><div class="det-val">AH 2025 · 42 looks</div></div>
<div class="p0-detail-row"><div class="det-key">Runway</div><div class="det-val">Palais Royal, 4 Oct</div></div>
</div>
</div>
</div>
</div>
<div class="page" id="p1">
<div class="p1-top">
<h2 class="p1-title">The<br>Collection</h2>
<div class="p1-count">42 Looks · AH 2025</div>
</div>
<div class="look-grid">
<div class="look"><div class="look-img"><div class="garment g1"></div></div><div class="look-num">Look 01</div><div class="look-name">L'aube noire</div></div>
<div class="look"><div class="look-img"><div class="garment g2"></div></div><div class="look-num">Look 07</div><div class="look-name">Le voile froid</div></div>
<div class="look"><div class="look-img"><div class="garment g3"></div></div><div class="look-num">Look 14</div><div class="look-name">La colonne</div></div>
<div class="look"><div class="look-img"><div class="garment g4"></div></div><div class="look-num">Look 21</div><div class="look-name">Le bruissement</div></div>
<div class="look"><div class="look-img"><div class="garment g5"></div></div><div class="look-num">Look 38</div><div class="look-name">La chute</div></div>
</div>
</div>
<div class="page" id="p2">
<div class="p2-left">
<div class="p2-eyebrow">L'Atelier Lécluse</div>
<h2 class="p2-title">Made by<br>hand, in<br>silence</h2>
<p class="p2-body">Each garment passes through twenty-four pairs of hands before it leaves the atelier. We consider this not a process, but a conversation with the material.</p>
<div class="craft-list">
<div class="craft-row"><div class="craft-n">I</div><div class="craft-t">Pattern cutting by master tailleur</div></div>
<div class="craft-row"><div class="craft-n">II</div><div class="craft-t">Hand-draping on the mannequin</div></div>
<div class="craft-row"><div class="craft-n">III</div><div class="craft-t">Three fittings per garment minimum</div></div>
<div class="craft-row"><div class="craft-n">IV</div><div class="craft-t">Handstitched finishing throughout</div></div>
<div class="craft-row"><div class="craft-n">V</div><div class="craft-t">Final inspection by the directrice</div></div>
</div>
</div>
<div class="p2-right">
<div class="maison-since">Maison Lécluse · Since 1967</div>
<div class="p2-numbers">
<div class="num-item"><div class="num-big">58</div><div class="num-label">Years of haute<br>couture</div></div>
<div class="num-item"><div class="num-big">24</div><div class="num-label">Artisan hands per<br>garment</div></div>
<div class="num-item"><div class="num-big">200+</div><div class="num-label">Hours in a single<br>couture piece</div></div>
</div>
</div>
</div>
<div class="page" id="p3">
<div class="p3-bg-text">ML</div>
<div class="p3-content">
<span class="p3-mark">Maison Lécluse · Paris</span>
<h2 class="p3-title">Private<br>Fitting</h2>
<p class="p3-sub">By appointment only. Ateliers are open to clients for consultation from Tuesday through Saturday.</p>
<div class="p3-contact-grid">
<div class="p3-contact-row"><div class="p3-contact-key">Address</div><div class="p3-contact-val">24 Rue du Faubourg Saint-Honoré</div></div>
<div class="p3-contact-row"><div class="p3-contact-key">Telephone</div><div class="p3-contact-val">+33 1 42 68 00 00</div></div>
<div class="p3-contact-row"><div class="p3-contact-key">Fitting hours</div><div class="p3-contact-val">Mar–Sam · 10h–18h</div></div>
<div class="p3-contact-row"><div class="p3-contact-key">Correspondence</div><div class="p3-contact-val">atelier@lecluse.paris</div></div>
</div>
</div>
</div>
</div>
<!-- Nav -->
<div class="c-nav">
<button class="c-btn" id="cPrev">‹</button>
<div class="c-dots">
<button class="c-dot active" data-i="0"></button>
<button class="c-dot" data-i="1"></button>
<button class="c-dot" data-i="2"></button>
<button class="c-dot" data-i="3"></button>
</div>
<div class="c-label" id="cLabel">Maison</div>
<button class="c-btn" id="cNext">›</button>
</div><!-- Curtain panels -->
<div class="curtain-left" id="cLeft"></div>
<div class="curtain-right" id="cRight"></div>
<div class="pages">
<div class="page active" id="p0">
<div class="p0-layout">
<div class="p0-left">
<div class="p0-mark">Maison Lécluse · Paris</div>
<div class="p0-main">
<div class="p0-season">Automne–Hiver 2025</div>
<h1 class="p0-title">Entre<br>Ombre<br>& Lumière</h1>
<div class="p0-title-fr">Between shadow and light</div>
<p class="p0-body">A collection born from the silences between words. Forty-two looks. Each one a conversation the body has alone.</p>
<button class="p0-cta" data-next="1">Discover the collection <span class="p0-cta-arrow"></span></button>
</div>
</div>
<div class="p0-right">
<div class="silhouette-area">
<div class="figure">
<div class="fig-head"></div>
<div class="fig-arm fig-arm-l"></div>
<div class="fig-arm fig-arm-r"></div>
<div class="fig-body"></div>
</div>
</div>
<div class="p0-right-bottom">
<div class="p0-detail-row"><div class="det-key">Maison</div><div class="det-val">Since 1967</div></div>
<div class="p0-detail-row"><div class="det-key">Ateliers</div><div class="det-val">Paris · Florence</div></div>
<div class="p0-detail-row"><div class="det-key">Collection</div><div class="det-val">AH 2025 · 42 looks</div></div>
<div class="p0-detail-row"><div class="det-key">Runway</div><div class="det-val">Palais Royal, 4 Oct</div></div>
</div>
</div>
</div>
</div>
<div class="page" id="p1">
<div class="p1-top">
<h2 class="p1-title">The<br>Collection</h2>
<div class="p1-count">42 Looks · AH 2025</div>
</div>
<div class="look-grid">
<div class="look"><div class="look-img"><div class="garment g1"></div></div><div class="look-num">Look 01</div><div class="look-name">L'aube noire</div></div>
<div class="look"><div class="look-img"><div class="garment g2"></div></div><div class="look-num">Look 07</div><div class="look-name">Le voile froid</div></div>
<div class="look"><div class="look-img"><div class="garment g3"></div></div><div class="look-num">Look 14</div><div class="look-name">La colonne</div></div>
<div class="look"><div class="look-img"><div class="garment g4"></div></div><div class="look-num">Look 21</div><div class="look-name">Le bruissement</div></div>
<div class="look"><div class="look-img"><div class="garment g5"></div></div><div class="look-num">Look 38</div><div class="look-name">La chute</div></div>
</div>
</div>
<div class="page" id="p2">
<div class="p2-left">
<div class="p2-eyebrow">L'Atelier Lécluse</div>
<h2 class="p2-title">Made by<br>hand, in<br>silence</h2>
<p class="p2-body">Each garment passes through twenty-four pairs of hands before it leaves the atelier. We consider this not a process, but a conversation with the material.</p>
<div class="craft-list">
<div class="craft-row"><div class="craft-n">I</div><div class="craft-t">Pattern cutting by master tailleur</div></div>
<div class="craft-row"><div class="craft-n">II</div><div class="craft-t">Hand-draping on the mannequin</div></div>
<div class="craft-row"><div class="craft-n">III</div><div class="craft-t">Three fittings per garment minimum</div></div>
<div class="craft-row"><div class="craft-n">IV</div><div class="craft-t">Handstitched finishing throughout</div></div>
<div class="craft-row"><div class="craft-n">V</div><div class="craft-t">Final inspection by the directrice</div></div>
</div>
</div>
<div class="p2-right">
<div class="maison-since">Maison Lécluse · Since 1967</div>
<div class="p2-numbers">
<div class="num-item"><div class="num-big">58</div><div class="num-label">Years of haute<br>couture</div></div>
<div class="num-item"><div class="num-big">24</div><div class="num-label">Artisan hands per<br>garment</div></div>
<div class="num-item"><div class="num-big">200+</div><div class="num-label">Hours in a single<br>couture piece</div></div>
</div>
</div>
</div>
<div class="page" id="p3">
<div class="p3-bg-text">ML</div>
<div class="p3-content">
<span class="p3-mark">Maison Lécluse · Paris</span>
<h2 class="p3-title">Private<br>Fitting</h2>
<p class="p3-sub">By appointment only. Ateliers are open to clients for consultation from Tuesday through Saturday.</p>
<div class="p3-contact-grid">
<div class="p3-contact-row"><div class="p3-contact-key">Address</div><div class="p3-contact-val">24 Rue du Faubourg Saint-Honoré</div></div>
<div class="p3-contact-row"><div class="p3-contact-key">Telephone</div><div class="p3-contact-val">+33 1 42 68 00 00</div></div>
<div class="p3-contact-row"><div class="p3-contact-key">Fitting hours</div><div class="p3-contact-val">Mar–Sam · 10h–18h</div></div>
<div class="p3-contact-row"><div class="p3-contact-key">Correspondence</div><div class="p3-contact-val">atelier@lecluse.paris</div></div>
</div>
</div>
</div>
</div>
<!-- Nav -->
<div class="c-nav">
<button class="c-btn" id="cPrev">‹</button>
<div class="c-dots">
<button class="c-dot active" data-i="0"></button>
<button class="c-dot" data-i="1"></button>
<button class="c-dot" data-i="2"></button>
<button class="c-dot" data-i="3"></button>
</div>
<div class="c-label" id="cLabel">Maison</div>
<button class="c-btn" id="cNext">›</button>
</div>*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--noir: #080808;
--white: #f8f4f0;
--warm: #e8e0d4;
--dim: rgba(248,244,240,0.4);
--accent: #c8a060;
--mid: rgba(248,244,240,0.1);
--dur: 900ms;
--ease: cubic-bezier(0.76,0,0.24,1);
}
html,
body {
height: 100%;
overflow: hidden;
background: var(--noir);
font-family: 'Cormorant Garamond',serif;
}
/* Pages */
.pages {
position: fixed;
inset: 0;
}
.page {
position: absolute;
inset: 0;
pointer-events: none;
visibility: hidden;
}
.page.active {
visibility: visible;
pointer-events: auto;
}
/* Curtain panels */
.curtain-left,
.curtain-right {
position: fixed;
top: 0;
bottom: 0;
z-index: 700;
background: var(--noir);
will-change: transform;
}
.curtain-left {
left: 0;
width: 50%;
transform: translateX(-100%);
transform-origin: left;
}
.curtain-right {
right: 0;
width: 50%;
transform: translateX(100%);
transform-origin: right;
}
/* Centre seam line */
.curtain-left::after {
content: '';
position: absolute;
right: 0;
top: 0;
bottom: 0;
width: 1px;
background: linear-gradient(180deg,transparent,var(--accent),transparent);
opacity: 0;
}
/* States */
.curtain-left.close {
transform: translateX(0);
}
.curtain-right.close {
transform: translateX(0);
}
.curtain-left.close::after {
opacity: 0.4;
}
/* PAGE 0 — MAISON */
#p0 {
background: var(--noir);
color: var(--white);
}
.p0-layout {
height: 100%;
display: grid;
grid-template-columns: 1fr 1fr;
}
.p0-left {
padding: 60px 80px;
display: flex;
flex-direction: column;
justify-content: space-between;
border-right: 1px solid var(--mid);
}
.p0-mark {
font-family: 'Italiana',serif;
font-size: 11px;
letter-spacing: 0.4em;
text-transform: uppercase;
color: var(--dim);
}
.p0-main {
flex: 1;
display: flex;
flex-direction: column;
justify-content: flex-end;
padding-bottom: 20px;
}
.p0-season {
font-size: 8px;
letter-spacing: 0.4em;
text-transform: uppercase;
color: var(--accent);
margin-bottom: 24px;
display: flex;
align-items: center;
gap: 12px;
}
.p0-season::before {
content: '';
width: 20px;
height: 1px;
background: var(--accent);
}
.p0-title {
font-family: 'Italiana',serif;
font-size: clamp(52px,8vw,112px);
font-weight: 400;
line-height: 0.9;
letter-spacing: -0.02em;
color: var(--white);
margin-bottom: 24px;
}
.p0-title-fr {
font-size: clamp(24px,3.5vw,48px);
font-style: italic;
font-weight: 300;
color: rgba(248,244,240,0.35);
margin-bottom: 40px;
}
.p0-body {
font-size: 13px;
line-height: 1.9;
font-weight: 300;
color: var(--dim);
max-width: 380px;
font-style: italic;
}
.p0-cta {
margin-top: 40px;
display: inline-flex;
align-items: center;
gap: 16px;
font-size: 9px;
letter-spacing: 0.3em;
text-transform: uppercase;
color: var(--white);
cursor: pointer;
background: none;
border: none;
font-family: 'Didact Gothic',sans-serif;
transition: color .2s;
}
.p0-cta:hover {
color: var(--accent);
}
.p0-cta-arrow {
width: 40px;
height: 1px;
background: currentColor;
transition: width .3s;
position: relative;
}
.p0-cta-arrow::after {
content: '';
position: absolute;
right: -1px;
top: -3px;
width: 7px;
height: 7px;
border-right: 1px solid currentColor;
border-top: 1px solid currentColor;
transform: rotate(45deg);
}
.p0-cta:hover .p0-cta-arrow {
width: 64px;
}
.p0-right {
display: grid;
grid-template-rows: 1fr 1fr;
padding: 60px;
gap: 0;
}
/* Abstract fashion illustration using CSS shapes */
.silhouette-area {
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.figure {
position: relative;
width: 80px;
height: 200px;
}
.fig-body {
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 48px;
height: 140px;
background: linear-gradient(180deg,rgba(200,160,96,0.2),rgba(200,160,96,0.06));
border: 1px solid rgba(200,160,96,0.2);
border-radius: 2px 2px 0 0;
}
.fig-head {
position: absolute;
bottom: 136px;
left: 50%;
transform: translateX(-50%);
width: 20px;
height: 24px;
border-radius: 50%;
background: rgba(200,160,96,0.15);
border: 1px solid rgba(200,160,96,0.2);
}
.fig-arm {
position: absolute;
height: 1px;
background: rgba(200,160,96,0.25);
top: 72px;
}
.fig-arm-l {
width: 32px;
right: 48px;
}
.fig-arm-r {
width: 32px;
left: 48px;
}
.p0-right-bottom {
display: flex;
flex-direction: column;
justify-content: flex-end;
gap: 16px;
}
.p0-detail-row {
display: flex;
justify-content: space-between;
align-items: baseline;
border-bottom: 1px solid var(--mid);
padding: 12px 0;
}
.det-key {
font-size: 8px;
letter-spacing: 0.25em;
text-transform: uppercase;
color: rgba(248,244,240,0.25);
font-family: 'Didact Gothic',sans-serif;
}
.det-val {
font-size: 12px;
font-style: italic;
color: rgba(248,244,240,0.6);
}
/* PAGE 1 — COLLECTION */
#p1 {
background: #0c0c0c;
color: var(--white);
padding: 60px 80px;
display: flex;
flex-direction: column;
}
.p1-top {
display: flex;
align-items: flex-end;
justify-content: space-between;
margin-bottom: 52px;
padding-bottom: 24px;
border-bottom: 1px solid var(--mid);
}
.p1-title {
font-family: 'Italiana',serif;
font-size: clamp(44px,7vw,100px);
font-weight: 400;
line-height: 0.9;
letter-spacing: -0.02em;
}
.p1-count {
font-size: 9px;
letter-spacing: 0.25em;
color: var(--dim);
font-family: 'Didact Gothic',sans-serif;
text-transform: uppercase;
}
.look-grid {
display: grid;
grid-template-columns: repeat(5,1fr);
gap: 12px;
flex: 1;
}
.look {
display: flex;
flex-direction: column;
gap: 12px;
cursor: pointer;
}
.look-img {
flex: 1;
border: 1px solid rgba(248,244,240,0.06);
position: relative;
overflow: hidden;
min-height: 200px;
background: linear-gradient(180deg,#111,#0a0a0a);
transition: border-color .3s;
}
.look:hover .look-img {
border-color: rgba(200,160,96,0.3);
}
/* Abstract garment shape */
.garment {
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 60%;
background: rgba(200,160,96,0.08);
border-top: 1px solid rgba(200,160,96,0.15);
}
.g1 {
height: 70%;
border-radius: 2px 2px 0 0;
}
.g2 {
height: 85%;
clip-path: polygon(20% 0,80% 0,100% 100%,0 100%);
}
.g3 {
height: 60%;
border-radius: 40% 40% 0 0;
}
.g4 {
height: 75%;
clip-path: polygon(0 0,100% 0,90% 100%,10% 100%);
}
.g5 {
height: 90%;
clip-path: polygon(30% 0,70% 0,100% 100%,0 100%);
}
.look-num {
font-size: 8px;
letter-spacing: 0.2em;
color: var(--accent);
font-family: 'Didact Gothic',sans-serif;
}
.look-name {
font-family: 'Cormorant Garamond',serif;
font-size: 13px;
font-style: italic;
color: rgba(248,244,240,0.7);
}
/* PAGE 2 — ATELIER */
#p2 {
background: var(--white);
color: var(--noir);
display: grid;
grid-template-columns: 1fr 1fr;
}
.p2-left {
padding: 80px;
display: flex;
flex-direction: column;
justify-content: center;
background: #f0ece6;
}
.p2-eyebrow {
font-size: 8px;
letter-spacing: 0.35em;
text-transform: uppercase;
color: var(--accent);
margin-bottom: 28px;
font-family: 'Didact Gothic',sans-serif;
}
.p2-title {
font-family: 'Italiana',serif;
font-size: clamp(44px,6vw,80px);
font-weight: 400;
line-height: 1.0;
color: var(--noir);
letter-spacing: -0.02em;
margin-bottom: 28px;
}
.p2-body {
font-size: 15px;
line-height: 1.85;
font-weight: 300;
font-style: italic;
color: rgba(8,8,8,0.5);
max-width: 400px;
margin-bottom: 48px;
}
.craft-list {
display: flex;
flex-direction: column;
gap: 0;
}
.craft-row {
display: flex;
gap: 20px;
padding: 18px 0;
border-bottom: 1px solid rgba(8,8,8,0.08);
align-items: baseline;
}
.craft-n {
font-size: 9px;
letter-spacing: 0.15em;
color: var(--accent);
font-family: 'Didact Gothic',sans-serif;
width: 24px;
flex-shrink: 0;
}
.craft-t {
font-size: 14px;
font-style: italic;
color: rgba(8,8,8,0.6);
}
.p2-right {
padding: 80px;
background: var(--white);
display: flex;
flex-direction: column;
justify-content: center;
border-left: 1px solid rgba(8,8,8,0.06);
}
.maison-since {
font-size: 9px;
letter-spacing: 0.35em;
text-transform: uppercase;
color: rgba(8,8,8,0.25);
margin-bottom: 40px;
font-family: 'Didact Gothic',sans-serif;
}
.p2-numbers {
display: flex;
flex-direction: column;
gap: 28px;
}
.num-item {
display: flex;
align-items: baseline;
gap: 20px;
padding-bottom: 28px;
border-bottom: 1px solid rgba(8,8,8,0.06);
}
.num-big {
font-family: 'Italiana',serif;
font-size: 56px;
color: var(--noir);
line-height: 1;
}
.num-label {
font-size: 12px;
font-style: italic;
color: rgba(8,8,8,0.45);
line-height: 1.4;
}
/* PAGE 3 — CONTACT */
#p3 {
background: var(--noir);
color: var(--white);
display: flex;
align-items: center;
justify-content: center;
text-align: center;
padding: 80px;
position: relative;
overflow: hidden;
}
.p3-bg-text {
position: absolute;
font-family: 'Italiana',serif;
font-size: 30vw;
color: rgba(248,244,240,0.025);
line-height: 1;
letter-spacing: -0.06em;
pointer-events: none;
user-select: none;
}
.p3-content {
position: relative;
max-width: 560px;
}
.p3-mark {
font-family: 'Italiana',serif;
font-size: 9px;
letter-spacing: 0.5em;
text-transform: uppercase;
color: var(--dim);
margin-bottom: 48px;
display: block;
}
.p3-title {
font-family: 'Italiana',serif;
font-size: clamp(44px,8vw,100px);
font-weight: 400;
line-height: 0.9;
letter-spacing: -0.02em;
color: var(--white);
margin-bottom: 16px;
}
.p3-sub {
font-size: 14px;
font-style: italic;
color: var(--dim);
margin-bottom: 48px;
line-height: 1.7;
}
.p3-contact-grid {
display: flex;
flex-direction: column;
gap: 16px;
border-top: 1px solid var(--mid);
padding-top: 36px;
}
.p3-contact-row {
display: flex;
justify-content: space-between;
align-items: baseline;
padding: 8px 0;
border-bottom: 1px solid var(--mid);
}
.p3-contact-key {
font-size: 8px;
letter-spacing: 0.25em;
text-transform: uppercase;
color: rgba(248,244,240,0.25);
font-family: 'Didact Gothic',sans-serif;
}
.p3-contact-val {
font-size: 13px;
font-style: italic;
color: rgba(248,244,240,0.65);
}
/* Curtain nav */
.c-nav {
position: fixed;
bottom: 40px;
left: 50%;
transform: translateX(-50%);
z-index: 800;
display: flex;
align-items: center;
gap: 24px;
background: rgba(8,8,8,0.7);
border: 1px solid var(--mid);
padding: 16px 32px;
backdrop-filter: blur(20px);
}
.c-label {
font-size: 8px;
letter-spacing: 0.3em;
text-transform: uppercase;
color: var(--dim);
font-family: 'Didact Gothic',sans-serif;
min-width: 80px;
text-align: center;
}
.c-btn {
width: 36px;
height: 36px;
border: 1px solid var(--mid);
background: none;
color: var(--dim);
font-size: 16px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: border-color .2s,color .2s;
font-family: serif;
}
.c-btn:hover {
border-color: var(--accent);
color: var(--accent);
}
.c-dots {
display: flex;
gap: 8px;
}
.c-dot {
width: 3px;
height: 3px;
border-radius: 50%;
background: rgba(248,244,240,0.2);
border: none;
cursor: pointer;
transition: background .25s,transform .3s;
}
.c-dot.active {
background: var(--accent);
transform: scale(1.8);
}
@media (max-width: 768px) {
#p0 .p0-layout {
grid-template-columns: 1fr;
}
.p0-right {
display: none;
}
.p0-left {
padding: 40px 28px;
}
#p1 {
padding: 40px 24px;
}
.look-grid {
grid-template-columns: repeat(2,1fr);
}
#p2 {
grid-template-columns: 1fr;
}
.p2-right {
display: none;
}
.p2-left {
padding: 40px 28px;
}
#p3 {
padding: 40px 28px;
}
}*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--noir: #080808;
--white: #f8f4f0;
--warm: #e8e0d4;
--dim: rgba(248,244,240,0.4);
--accent: #c8a060;
--mid: rgba(248,244,240,0.1);
--dur: 900ms;
--ease: cubic-bezier(0.76,0,0.24,1);
}
html,
body {
height: 100%;
overflow: hidden;
background: var(--noir);
font-family: 'Cormorant Garamond',serif;
}
/* Pages */
.pages {
position: fixed;
inset: 0;
}
.page {
position: absolute;
inset: 0;
pointer-events: none;
visibility: hidden;
}
.page.active {
visibility: visible;
pointer-events: auto;
}
/* Curtain panels */
.curtain-left,
.curtain-right {
position: fixed;
top: 0;
bottom: 0;
z-index: 700;
background: var(--noir);
will-change: transform;
}
.curtain-left {
left: 0;
width: 50%;
transform: translateX(-100%);
transform-origin: left;
}
.curtain-right {
right: 0;
width: 50%;
transform: translateX(100%);
transform-origin: right;
}
/* Centre seam line */
.curtain-left::after {
content: '';
position: absolute;
right: 0;
top: 0;
bottom: 0;
width: 1px;
background: linear-gradient(180deg,transparent,var(--accent),transparent);
opacity: 0;
}
/* States */
.curtain-left.close {
transform: translateX(0);
}
.curtain-right.close {
transform: translateX(0);
}
.curtain-left.close::after {
opacity: 0.4;
}
/* PAGE 0 — MAISON */
#p0 {
background: var(--noir);
color: var(--white);
}
.p0-layout {
height: 100%;
display: grid;
grid-template-columns: 1fr 1fr;
}
.p0-left {
padding: 60px 80px;
display: flex;
flex-direction: column;
justify-content: space-between;
border-right: 1px solid var(--mid);
}
.p0-mark {
font-family: 'Italiana',serif;
font-size: 11px;
letter-spacing: 0.4em;
text-transform: uppercase;
color: var(--dim);
}
.p0-main {
flex: 1;
display: flex;
flex-direction: column;
justify-content: flex-end;
padding-bottom: 20px;
}
.p0-season {
font-size: 8px;
letter-spacing: 0.4em;
text-transform: uppercase;
color: var(--accent);
margin-bottom: 24px;
display: flex;
align-items: center;
gap: 12px;
}
.p0-season::before {
content: '';
width: 20px;
height: 1px;
background: var(--accent);
}
.p0-title {
font-family: 'Italiana',serif;
font-size: clamp(52px,8vw,112px);
font-weight: 400;
line-height: 0.9;
letter-spacing: -0.02em;
color: var(--white);
margin-bottom: 24px;
}
.p0-title-fr {
font-size: clamp(24px,3.5vw,48px);
font-style: italic;
font-weight: 300;
color: rgba(248,244,240,0.35);
margin-bottom: 40px;
}
.p0-body {
font-size: 13px;
line-height: 1.9;
font-weight: 300;
color: var(--dim);
max-width: 380px;
font-style: italic;
}
.p0-cta {
margin-top: 40px;
display: inline-flex;
align-items: center;
gap: 16px;
font-size: 9px;
letter-spacing: 0.3em;
text-transform: uppercase;
color: var(--white);
cursor: pointer;
background: none;
border: none;
font-family: 'Didact Gothic',sans-serif;
transition: color .2s;
}
.p0-cta:hover {
color: var(--accent);
}
.p0-cta-arrow {
width: 40px;
height: 1px;
background: currentColor;
transition: width .3s;
position: relative;
}
.p0-cta-arrow::after {
content: '';
position: absolute;
right: -1px;
top: -3px;
width: 7px;
height: 7px;
border-right: 1px solid currentColor;
border-top: 1px solid currentColor;
transform: rotate(45deg);
}
.p0-cta:hover .p0-cta-arrow {
width: 64px;
}
.p0-right {
display: grid;
grid-template-rows: 1fr 1fr;
padding: 60px;
gap: 0;
}
/* Abstract fashion illustration using CSS shapes */
.silhouette-area {
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.figure {
position: relative;
width: 80px;
height: 200px;
}
.fig-body {
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 48px;
height: 140px;
background: linear-gradient(180deg,rgba(200,160,96,0.2),rgba(200,160,96,0.06));
border: 1px solid rgba(200,160,96,0.2);
border-radius: 2px 2px 0 0;
}
.fig-head {
position: absolute;
bottom: 136px;
left: 50%;
transform: translateX(-50%);
width: 20px;
height: 24px;
border-radius: 50%;
background: rgba(200,160,96,0.15);
border: 1px solid rgba(200,160,96,0.2);
}
.fig-arm {
position: absolute;
height: 1px;
background: rgba(200,160,96,0.25);
top: 72px;
}
.fig-arm-l {
width: 32px;
right: 48px;
}
.fig-arm-r {
width: 32px;
left: 48px;
}
.p0-right-bottom {
display: flex;
flex-direction: column;
justify-content: flex-end;
gap: 16px;
}
.p0-detail-row {
display: flex;
justify-content: space-between;
align-items: baseline;
border-bottom: 1px solid var(--mid);
padding: 12px 0;
}
.det-key {
font-size: 8px;
letter-spacing: 0.25em;
text-transform: uppercase;
color: rgba(248,244,240,0.25);
font-family: 'Didact Gothic',sans-serif;
}
.det-val {
font-size: 12px;
font-style: italic;
color: rgba(248,244,240,0.6);
}
/* PAGE 1 — COLLECTION */
#p1 {
background: #0c0c0c;
color: var(--white);
padding: 60px 80px;
display: flex;
flex-direction: column;
}
.p1-top {
display: flex;
align-items: flex-end;
justify-content: space-between;
margin-bottom: 52px;
padding-bottom: 24px;
border-bottom: 1px solid var(--mid);
}
.p1-title {
font-family: 'Italiana',serif;
font-size: clamp(44px,7vw,100px);
font-weight: 400;
line-height: 0.9;
letter-spacing: -0.02em;
}
.p1-count {
font-size: 9px;
letter-spacing: 0.25em;
color: var(--dim);
font-family: 'Didact Gothic',sans-serif;
text-transform: uppercase;
}
.look-grid {
display: grid;
grid-template-columns: repeat(5,1fr);
gap: 12px;
flex: 1;
}
.look {
display: flex;
flex-direction: column;
gap: 12px;
cursor: pointer;
}
.look-img {
flex: 1;
border: 1px solid rgba(248,244,240,0.06);
position: relative;
overflow: hidden;
min-height: 200px;
background: linear-gradient(180deg,#111,#0a0a0a);
transition: border-color .3s;
}
.look:hover .look-img {
border-color: rgba(200,160,96,0.3);
}
/* Abstract garment shape */
.garment {
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 60%;
background: rgba(200,160,96,0.08);
border-top: 1px solid rgba(200,160,96,0.15);
}
.g1 {
height: 70%;
border-radius: 2px 2px 0 0;
}
.g2 {
height: 85%;
clip-path: polygon(20% 0,80% 0,100% 100%,0 100%);
}
.g3 {
height: 60%;
border-radius: 40% 40% 0 0;
}
.g4 {
height: 75%;
clip-path: polygon(0 0,100% 0,90% 100%,10% 100%);
}
.g5 {
height: 90%;
clip-path: polygon(30% 0,70% 0,100% 100%,0 100%);
}
.look-num {
font-size: 8px;
letter-spacing: 0.2em;
color: var(--accent);
font-family: 'Didact Gothic',sans-serif;
}
.look-name {
font-family: 'Cormorant Garamond',serif;
font-size: 13px;
font-style: italic;
color: rgba(248,244,240,0.7);
}
/* PAGE 2 — ATELIER */
#p2 {
background: var(--white);
color: var(--noir);
display: grid;
grid-template-columns: 1fr 1fr;
}
.p2-left {
padding: 80px;
display: flex;
flex-direction: column;
justify-content: center;
background: #f0ece6;
}
.p2-eyebrow {
font-size: 8px;
letter-spacing: 0.35em;
text-transform: uppercase;
color: var(--accent);
margin-bottom: 28px;
font-family: 'Didact Gothic',sans-serif;
}
.p2-title {
font-family: 'Italiana',serif;
font-size: clamp(44px,6vw,80px);
font-weight: 400;
line-height: 1.0;
color: var(--noir);
letter-spacing: -0.02em;
margin-bottom: 28px;
}
.p2-body {
font-size: 15px;
line-height: 1.85;
font-weight: 300;
font-style: italic;
color: rgba(8,8,8,0.5);
max-width: 400px;
margin-bottom: 48px;
}
.craft-list {
display: flex;
flex-direction: column;
gap: 0;
}
.craft-row {
display: flex;
gap: 20px;
padding: 18px 0;
border-bottom: 1px solid rgba(8,8,8,0.08);
align-items: baseline;
}
.craft-n {
font-size: 9px;
letter-spacing: 0.15em;
color: var(--accent);
font-family: 'Didact Gothic',sans-serif;
width: 24px;
flex-shrink: 0;
}
.craft-t {
font-size: 14px;
font-style: italic;
color: rgba(8,8,8,0.6);
}
.p2-right {
padding: 80px;
background: var(--white);
display: flex;
flex-direction: column;
justify-content: center;
border-left: 1px solid rgba(8,8,8,0.06);
}
.maison-since {
font-size: 9px;
letter-spacing: 0.35em;
text-transform: uppercase;
color: rgba(8,8,8,0.25);
margin-bottom: 40px;
font-family: 'Didact Gothic',sans-serif;
}
.p2-numbers {
display: flex;
flex-direction: column;
gap: 28px;
}
.num-item {
display: flex;
align-items: baseline;
gap: 20px;
padding-bottom: 28px;
border-bottom: 1px solid rgba(8,8,8,0.06);
}
.num-big {
font-family: 'Italiana',serif;
font-size: 56px;
color: var(--noir);
line-height: 1;
}
.num-label {
font-size: 12px;
font-style: italic;
color: rgba(8,8,8,0.45);
line-height: 1.4;
}
/* PAGE 3 — CONTACT */
#p3 {
background: var(--noir);
color: var(--white);
display: flex;
align-items: center;
justify-content: center;
text-align: center;
padding: 80px;
position: relative;
overflow: hidden;
}
.p3-bg-text {
position: absolute;
font-family: 'Italiana',serif;
font-size: 30vw;
color: rgba(248,244,240,0.025);
line-height: 1;
letter-spacing: -0.06em;
pointer-events: none;
user-select: none;
}
.p3-content {
position: relative;
max-width: 560px;
}
.p3-mark {
font-family: 'Italiana',serif;
font-size: 9px;
letter-spacing: 0.5em;
text-transform: uppercase;
color: var(--dim);
margin-bottom: 48px;
display: block;
}
.p3-title {
font-family: 'Italiana',serif;
font-size: clamp(44px,8vw,100px);
font-weight: 400;
line-height: 0.9;
letter-spacing: -0.02em;
color: var(--white);
margin-bottom: 16px;
}
.p3-sub {
font-size: 14px;
font-style: italic;
color: var(--dim);
margin-bottom: 48px;
line-height: 1.7;
}
.p3-contact-grid {
display: flex;
flex-direction: column;
gap: 16px;
border-top: 1px solid var(--mid);
padding-top: 36px;
}
.p3-contact-row {
display: flex;
justify-content: space-between;
align-items: baseline;
padding: 8px 0;
border-bottom: 1px solid var(--mid);
}
.p3-contact-key {
font-size: 8px;
letter-spacing: 0.25em;
text-transform: uppercase;
color: rgba(248,244,240,0.25);
font-family: 'Didact Gothic',sans-serif;
}
.p3-contact-val {
font-size: 13px;
font-style: italic;
color: rgba(248,244,240,0.65);
}
/* Curtain nav */
.c-nav {
position: fixed;
bottom: 40px;
left: 50%;
transform: translateX(-50%);
z-index: 800;
display: flex;
align-items: center;
gap: 24px;
background: rgba(8,8,8,0.7);
border: 1px solid var(--mid);
padding: 16px 32px;
backdrop-filter: blur(20px);
}
.c-label {
font-size: 8px;
letter-spacing: 0.3em;
text-transform: uppercase;
color: var(--dim);
font-family: 'Didact Gothic',sans-serif;
min-width: 80px;
text-align: center;
}
.c-btn {
width: 36px;
height: 36px;
border: 1px solid var(--mid);
background: none;
color: var(--dim);
font-size: 16px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: border-color .2s,color .2s;
font-family: serif;
}
.c-btn:hover {
border-color: var(--accent);
color: var(--accent);
}
.c-dots {
display: flex;
gap: 8px;
}
.c-dot {
width: 3px;
height: 3px;
border-radius: 50%;
background: rgba(248,244,240,0.2);
border: none;
cursor: pointer;
transition: background .25s,transform .3s;
}
.c-dot.active {
background: var(--accent);
transform: scale(1.8);
}
@media (max-width: 768px) {
#p0 .p0-layout {
grid-template-columns: 1fr;
}
.p0-right {
display: none;
}
.p0-left {
padding: 40px 28px;
}
#p1 {
padding: 40px 24px;
}
.look-grid {
grid-template-columns: repeat(2,1fr);
}
#p2 {
grid-template-columns: 1fr;
}
.p2-right {
display: none;
}
.p2-left {
padding: 40px 28px;
}
#p3 {
padding: 40px 28px;
}
}const cLeft=document.getElementById('cLeft');
const cRight=document.getElementById('cRight');
const pages=document.querySelectorAll('.page');
const cdots=document.querySelectorAll('.c-dot');
const cLabel=document.getElementById('cLabel');
const labels=['Maison','Collection','Atelier','Contact'];
let cur=0,busy=false;
const dur=900;
function curtainTransition(prev,next,done){
cLeft.style.transition=`transform ${dur*0.4}ms cubic-bezier(0.76,0,0.24,1)`;
cRight.style.transition=`transform ${dur*0.4}ms cubic-bezier(0.76,0,0.24,1)`;
cLeft.classList.add('close');
cRight.classList.add('close');
setTimeout(()=>{
pages[prev].classList.remove('active');
pages[next].classList.add('active');
cLeft.style.transition=`transform ${dur*0.55}ms cubic-bezier(0.25,1,0.5,1)`;
cRight.style.transition=`transform ${dur*0.55}ms cubic-bezier(0.25,1,0.5,1)`;
cLeft.classList.remove('close');
cRight.classList.remove('close');
setTimeout(()=>{ done&&done(); },dur*0.6);
},dur*0.42);
}
function goTo(n){
if(busy||n===cur)return;
busy=true;
const prev=cur;cur=n;
cdots.forEach((d,i)=>d.classList.toggle('active',i===cur));
cLabel.textContent=labels[cur];
curtainTransition(prev,cur,()=>{busy=false;});
}
document.getElementById('cNext').onclick=()=>goTo(Math.min(3,cur+1));
document.getElementById('cPrev').onclick=()=>goTo(Math.max(0,cur-1));
cdots.forEach(d=>d.addEventListener('click',()=>goTo(+d.dataset.i)));
document.querySelectorAll('[data-next]').forEach(b=>b.addEventListener('click',()=>goTo(+b.dataset.next)));
let wt=0;
window.addEventListener('wheel',e=>{
const now=Date.now();if(now-wt<1100)return;wt=now;
goTo(Math.max(0,Math.min(3,cur+(e.deltaY>0?1:-1))));
},{passive:true});
document.addEventListener('keydown',e=>{
if(e.key==='ArrowRight')goTo(Math.min(3,cur+1));
if(e.key==='ArrowLeft')goTo(Math.max(0,cur-1));
});const cLeft=document.getElementById('cLeft');
const cRight=document.getElementById('cRight');
const pages=document.querySelectorAll('.page');
const cdots=document.querySelectorAll('.c-dot');
const cLabel=document.getElementById('cLabel');
const labels=['Maison','Collection','Atelier','Contact'];
let cur=0,busy=false;
const dur=900;
function curtainTransition(prev,next,done){
cLeft.style.transition=`transform ${dur*0.4}ms cubic-bezier(0.76,0,0.24,1)`;
cRight.style.transition=`transform ${dur*0.4}ms cubic-bezier(0.76,0,0.24,1)`;
cLeft.classList.add('close');
cRight.classList.add('close');
setTimeout(()=>{
pages[prev].classList.remove('active');
pages[next].classList.add('active');
cLeft.style.transition=`transform ${dur*0.55}ms cubic-bezier(0.25,1,0.5,1)`;
cRight.style.transition=`transform ${dur*0.55}ms cubic-bezier(0.25,1,0.5,1)`;
cLeft.classList.remove('close');
cRight.classList.remove('close');
setTimeout(()=>{ done&&done(); },dur*0.6);
},dur*0.42);
}
function goTo(n){
if(busy||n===cur)return;
busy=true;
const prev=cur;cur=n;
cdots.forEach((d,i)=>d.classList.toggle('active',i===cur));
cLabel.textContent=labels[cur];
curtainTransition(prev,cur,()=>{busy=false;});
}
document.getElementById('cNext').onclick=()=>goTo(Math.min(3,cur+1));
document.getElementById('cPrev').onclick=()=>goTo(Math.max(0,cur-1));
cdots.forEach(d=>d.addEventListener('click',()=>goTo(+d.dataset.i)));
document.querySelectorAll('[data-next]').forEach(b=>b.addEventListener('click',()=>goTo(+b.dataset.next)));
let wt=0;
window.addEventListener('wheel',e=>{
const now=Date.now();if(now-wt<1100)return;wt=now;
goTo(Math.max(0,Math.min(3,cur+(e.deltaY>0?1:-1))));
},{passive:true});
document.addEventListener('keydown',e=>{
if(e.key==='ArrowRight')goTo(Math.min(3,cur+1));
if(e.key==='ArrowLeft')goTo(Math.max(0,cur-1));
});Here's a working CSS Page Transition from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Vertical Split Curtain
Source: https://codefronts.com/motion/css-page-transitions/vertical-split-curtain/
Two full-height panels slide closed like theatre curtains, swap the page, then split apart with a different easing — a gold-seamed theatrical reveal. A Parisian haute couture house.
## HTML
```html
<!-- Curtain panels -->
<div class="curtain-left" id="cLeft"></div>
<div class="curtain-right" id="cRight"></div>
<div class="pages">
<div class="page active" id="p0">
<div class="p0-layout">
<div class="p0-left">
<div class="p0-mark">Maison Lécluse · Paris</div>
<div class="p0-main">
<div class="p0-season">Automne–Hiver 2025</div>
<h1 class="p0-title">Entre<br>Ombre<br>& Lumière</h1>
<div class="p0-title-fr">Between shadow and light</div>
<p class="p0-body">A collection born from the silences between words. Forty-two looks. Each one a conversation the body has alone.</p>
<button class="p0-cta" data-next="1">Discover the collection <span class="p0-cta-arrow"></span></button>
</div>
</div>
<div class="p0-right">
<div class="silhouette-area">
<div class="figure">
<div class="fig-head"></div>
<div class="fig-arm fig-arm-l"></div>
<div class="fig-arm fig-arm-r"></div>
<div class="fig-body"></div>
</div>
</div>
<div class="p0-right-bottom">
<div class="p0-detail-row"><div class="det-key">Maison</div><div class="det-val">Since 1967</div></div>
<div class="p0-detail-row"><div class="det-key">Ateliers</div><div class="det-val">Paris · Florence</div></div>
<div class="p0-detail-row"><div class="det-key">Collection</div><div class="det-val">AH 2025 · 42 looks</div></div>
<div class="p0-detail-row"><div class="det-key">Runway</div><div class="det-val">Palais Royal, 4 Oct</div></div>
</div>
</div>
</div>
</div>
<div class="page" id="p1">
<div class="p1-top">
<h2 class="p1-title">The<br>Collection</h2>
<div class="p1-count">42 Looks · AH 2025</div>
</div>
<div class="look-grid">
<div class="look"><div class="look-img"><div class="garment g1"></div></div><div class="look-num">Look 01</div><div class="look-name">L'aube noire</div></div>
<div class="look"><div class="look-img"><div class="garment g2"></div></div><div class="look-num">Look 07</div><div class="look-name">Le voile froid</div></div>
<div class="look"><div class="look-img"><div class="garment g3"></div></div><div class="look-num">Look 14</div><div class="look-name">La colonne</div></div>
<div class="look"><div class="look-img"><div class="garment g4"></div></div><div class="look-num">Look 21</div><div class="look-name">Le bruissement</div></div>
<div class="look"><div class="look-img"><div class="garment g5"></div></div><div class="look-num">Look 38</div><div class="look-name">La chute</div></div>
</div>
</div>
<div class="page" id="p2">
<div class="p2-left">
<div class="p2-eyebrow">L'Atelier Lécluse</div>
<h2 class="p2-title">Made by<br>hand, in<br>silence</h2>
<p class="p2-body">Each garment passes through twenty-four pairs of hands before it leaves the atelier. We consider this not a process, but a conversation with the material.</p>
<div class="craft-list">
<div class="craft-row"><div class="craft-n">I</div><div class="craft-t">Pattern cutting by master tailleur</div></div>
<div class="craft-row"><div class="craft-n">II</div><div class="craft-t">Hand-draping on the mannequin</div></div>
<div class="craft-row"><div class="craft-n">III</div><div class="craft-t">Three fittings per garment minimum</div></div>
<div class="craft-row"><div class="craft-n">IV</div><div class="craft-t">Handstitched finishing throughout</div></div>
<div class="craft-row"><div class="craft-n">V</div><div class="craft-t">Final inspection by the directrice</div></div>
</div>
</div>
<div class="p2-right">
<div class="maison-since">Maison Lécluse · Since 1967</div>
<div class="p2-numbers">
<div class="num-item"><div class="num-big">58</div><div class="num-label">Years of haute<br>couture</div></div>
<div class="num-item"><div class="num-big">24</div><div class="num-label">Artisan hands per<br>garment</div></div>
<div class="num-item"><div class="num-big">200+</div><div class="num-label">Hours in a single<br>couture piece</div></div>
</div>
</div>
</div>
<div class="page" id="p3">
<div class="p3-bg-text">ML</div>
<div class="p3-content">
<span class="p3-mark">Maison Lécluse · Paris</span>
<h2 class="p3-title">Private<br>Fitting</h2>
<p class="p3-sub">By appointment only. Ateliers are open to clients for consultation from Tuesday through Saturday.</p>
<div class="p3-contact-grid">
<div class="p3-contact-row"><div class="p3-contact-key">Address</div><div class="p3-contact-val">24 Rue du Faubourg Saint-Honoré</div></div>
<div class="p3-contact-row"><div class="p3-contact-key">Telephone</div><div class="p3-contact-val">+33 1 42 68 00 00</div></div>
<div class="p3-contact-row"><div class="p3-contact-key">Fitting hours</div><div class="p3-contact-val">Mar–Sam · 10h–18h</div></div>
<div class="p3-contact-row"><div class="p3-contact-key">Correspondence</div><div class="p3-contact-val">atelier@lecluse.paris</div></div>
</div>
</div>
</div>
</div>
<!-- Nav -->
<div class="c-nav">
<button class="c-btn" id="cPrev">‹</button>
<div class="c-dots">
<button class="c-dot active" data-i="0"></button>
<button class="c-dot" data-i="1"></button>
<button class="c-dot" data-i="2"></button>
<button class="c-dot" data-i="3"></button>
</div>
<div class="c-label" id="cLabel">Maison</div>
<button class="c-btn" id="cNext">›</button>
</div>
```
## CSS
```css
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--noir: #080808;
--white: #f8f4f0;
--warm: #e8e0d4;
--dim: rgba(248,244,240,0.4);
--accent: #c8a060;
--mid: rgba(248,244,240,0.1);
--dur: 900ms;
--ease: cubic-bezier(0.76,0,0.24,1);
}
html,
body {
height: 100%;
overflow: hidden;
background: var(--noir);
font-family: 'Cormorant Garamond',serif;
}
/* Pages */
.pages {
position: fixed;
inset: 0;
}
.page {
position: absolute;
inset: 0;
pointer-events: none;
visibility: hidden;
}
.page.active {
visibility: visible;
pointer-events: auto;
}
/* Curtain panels */
.curtain-left,
.curtain-right {
position: fixed;
top: 0;
bottom: 0;
z-index: 700;
background: var(--noir);
will-change: transform;
}
.curtain-left {
left: 0;
width: 50%;
transform: translateX(-100%);
transform-origin: left;
}
.curtain-right {
right: 0;
width: 50%;
transform: translateX(100%);
transform-origin: right;
}
/* Centre seam line */
.curtain-left::after {
content: '';
position: absolute;
right: 0;
top: 0;
bottom: 0;
width: 1px;
background: linear-gradient(180deg,transparent,var(--accent),transparent);
opacity: 0;
}
/* States */
.curtain-left.close {
transform: translateX(0);
}
.curtain-right.close {
transform: translateX(0);
}
.curtain-left.close::after {
opacity: 0.4;
}
/* PAGE 0 — MAISON */
#p0 {
background: var(--noir);
color: var(--white);
}
.p0-layout {
height: 100%;
display: grid;
grid-template-columns: 1fr 1fr;
}
.p0-left {
padding: 60px 80px;
display: flex;
flex-direction: column;
justify-content: space-between;
border-right: 1px solid var(--mid);
}
.p0-mark {
font-family: 'Italiana',serif;
font-size: 11px;
letter-spacing: 0.4em;
text-transform: uppercase;
color: var(--dim);
}
.p0-main {
flex: 1;
display: flex;
flex-direction: column;
justify-content: flex-end;
padding-bottom: 20px;
}
.p0-season {
font-size: 8px;
letter-spacing: 0.4em;
text-transform: uppercase;
color: var(--accent);
margin-bottom: 24px;
display: flex;
align-items: center;
gap: 12px;
}
.p0-season::before {
content: '';
width: 20px;
height: 1px;
background: var(--accent);
}
.p0-title {
font-family: 'Italiana',serif;
font-size: clamp(52px,8vw,112px);
font-weight: 400;
line-height: 0.9;
letter-spacing: -0.02em;
color: var(--white);
margin-bottom: 24px;
}
.p0-title-fr {
font-size: clamp(24px,3.5vw,48px);
font-style: italic;
font-weight: 300;
color: rgba(248,244,240,0.35);
margin-bottom: 40px;
}
.p0-body {
font-size: 13px;
line-height: 1.9;
font-weight: 300;
color: var(--dim);
max-width: 380px;
font-style: italic;
}
.p0-cta {
margin-top: 40px;
display: inline-flex;
align-items: center;
gap: 16px;
font-size: 9px;
letter-spacing: 0.3em;
text-transform: uppercase;
color: var(--white);
cursor: pointer;
background: none;
border: none;
font-family: 'Didact Gothic',sans-serif;
transition: color .2s;
}
.p0-cta:hover {
color: var(--accent);
}
.p0-cta-arrow {
width: 40px;
height: 1px;
background: currentColor;
transition: width .3s;
position: relative;
}
.p0-cta-arrow::after {
content: '';
position: absolute;
right: -1px;
top: -3px;
width: 7px;
height: 7px;
border-right: 1px solid currentColor;
border-top: 1px solid currentColor;
transform: rotate(45deg);
}
.p0-cta:hover .p0-cta-arrow {
width: 64px;
}
.p0-right {
display: grid;
grid-template-rows: 1fr 1fr;
padding: 60px;
gap: 0;
}
/* Abstract fashion illustration using CSS shapes */
.silhouette-area {
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.figure {
position: relative;
width: 80px;
height: 200px;
}
.fig-body {
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 48px;
height: 140px;
background: linear-gradient(180deg,rgba(200,160,96,0.2),rgba(200,160,96,0.06));
border: 1px solid rgba(200,160,96,0.2);
border-radius: 2px 2px 0 0;
}
.fig-head {
position: absolute;
bottom: 136px;
left: 50%;
transform: translateX(-50%);
width: 20px;
height: 24px;
border-radius: 50%;
background: rgba(200,160,96,0.15);
border: 1px solid rgba(200,160,96,0.2);
}
.fig-arm {
position: absolute;
height: 1px;
background: rgba(200,160,96,0.25);
top: 72px;
}
.fig-arm-l {
width: 32px;
right: 48px;
}
.fig-arm-r {
width: 32px;
left: 48px;
}
.p0-right-bottom {
display: flex;
flex-direction: column;
justify-content: flex-end;
gap: 16px;
}
.p0-detail-row {
display: flex;
justify-content: space-between;
align-items: baseline;
border-bottom: 1px solid var(--mid);
padding: 12px 0;
}
.det-key {
font-size: 8px;
letter-spacing: 0.25em;
text-transform: uppercase;
color: rgba(248,244,240,0.25);
font-family: 'Didact Gothic',sans-serif;
}
.det-val {
font-size: 12px;
font-style: italic;
color: rgba(248,244,240,0.6);
}
/* PAGE 1 — COLLECTION */
#p1 {
background: #0c0c0c;
color: var(--white);
padding: 60px 80px;
display: flex;
flex-direction: column;
}
.p1-top {
display: flex;
align-items: flex-end;
justify-content: space-between;
margin-bottom: 52px;
padding-bottom: 24px;
border-bottom: 1px solid var(--mid);
}
.p1-title {
font-family: 'Italiana',serif;
font-size: clamp(44px,7vw,100px);
font-weight: 400;
line-height: 0.9;
letter-spacing: -0.02em;
}
.p1-count {
font-size: 9px;
letter-spacing: 0.25em;
color: var(--dim);
font-family: 'Didact Gothic',sans-serif;
text-transform: uppercase;
}
.look-grid {
display: grid;
grid-template-columns: repeat(5,1fr);
gap: 12px;
flex: 1;
}
.look {
display: flex;
flex-direction: column;
gap: 12px;
cursor: pointer;
}
.look-img {
flex: 1;
border: 1px solid rgba(248,244,240,0.06);
position: relative;
overflow: hidden;
min-height: 200px;
background: linear-gradient(180deg,#111,#0a0a0a);
transition: border-color .3s;
}
.look:hover .look-img {
border-color: rgba(200,160,96,0.3);
}
/* Abstract garment shape */
.garment {
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 60%;
background: rgba(200,160,96,0.08);
border-top: 1px solid rgba(200,160,96,0.15);
}
.g1 {
height: 70%;
border-radius: 2px 2px 0 0;
}
.g2 {
height: 85%;
clip-path: polygon(20% 0,80% 0,100% 100%,0 100%);
}
.g3 {
height: 60%;
border-radius: 40% 40% 0 0;
}
.g4 {
height: 75%;
clip-path: polygon(0 0,100% 0,90% 100%,10% 100%);
}
.g5 {
height: 90%;
clip-path: polygon(30% 0,70% 0,100% 100%,0 100%);
}
.look-num {
font-size: 8px;
letter-spacing: 0.2em;
color: var(--accent);
font-family: 'Didact Gothic',sans-serif;
}
.look-name {
font-family: 'Cormorant Garamond',serif;
font-size: 13px;
font-style: italic;
color: rgba(248,244,240,0.7);
}
/* PAGE 2 — ATELIER */
#p2 {
background: var(--white);
color: var(--noir);
display: grid;
grid-template-columns: 1fr 1fr;
}
.p2-left {
padding: 80px;
display: flex;
flex-direction: column;
justify-content: center;
background: #f0ece6;
}
.p2-eyebrow {
font-size: 8px;
letter-spacing: 0.35em;
text-transform: uppercase;
color: var(--accent);
margin-bottom: 28px;
font-family: 'Didact Gothic',sans-serif;
}
.p2-title {
font-family: 'Italiana',serif;
font-size: clamp(44px,6vw,80px);
font-weight: 400;
line-height: 1.0;
color: var(--noir);
letter-spacing: -0.02em;
margin-bottom: 28px;
}
.p2-body {
font-size: 15px;
line-height: 1.85;
font-weight: 300;
font-style: italic;
color: rgba(8,8,8,0.5);
max-width: 400px;
margin-bottom: 48px;
}
.craft-list {
display: flex;
flex-direction: column;
gap: 0;
}
.craft-row {
display: flex;
gap: 20px;
padding: 18px 0;
border-bottom: 1px solid rgba(8,8,8,0.08);
align-items: baseline;
}
.craft-n {
font-size: 9px;
letter-spacing: 0.15em;
color: var(--accent);
font-family: 'Didact Gothic',sans-serif;
width: 24px;
flex-shrink: 0;
}
.craft-t {
font-size: 14px;
font-style: italic;
color: rgba(8,8,8,0.6);
}
.p2-right {
padding: 80px;
background: var(--white);
display: flex;
flex-direction: column;
justify-content: center;
border-left: 1px solid rgba(8,8,8,0.06);
}
.maison-since {
font-size: 9px;
letter-spacing: 0.35em;
text-transform: uppercase;
color: rgba(8,8,8,0.25);
margin-bottom: 40px;
font-family: 'Didact Gothic',sans-serif;
}
.p2-numbers {
display: flex;
flex-direction: column;
gap: 28px;
}
.num-item {
display: flex;
align-items: baseline;
gap: 20px;
padding-bottom: 28px;
border-bottom: 1px solid rgba(8,8,8,0.06);
}
.num-big {
font-family: 'Italiana',serif;
font-size: 56px;
color: var(--noir);
line-height: 1;
}
.num-label {
font-size: 12px;
font-style: italic;
color: rgba(8,8,8,0.45);
line-height: 1.4;
}
/* PAGE 3 — CONTACT */
#p3 {
background: var(--noir);
color: var(--white);
display: flex;
align-items: center;
justify-content: center;
text-align: center;
padding: 80px;
position: relative;
overflow: hidden;
}
.p3-bg-text {
position: absolute;
font-family: 'Italiana',serif;
font-size: 30vw;
color: rgba(248,244,240,0.025);
line-height: 1;
letter-spacing: -0.06em;
pointer-events: none;
user-select: none;
}
.p3-content {
position: relative;
max-width: 560px;
}
.p3-mark {
font-family: 'Italiana',serif;
font-size: 9px;
letter-spacing: 0.5em;
text-transform: uppercase;
color: var(--dim);
margin-bottom: 48px;
display: block;
}
.p3-title {
font-family: 'Italiana',serif;
font-size: clamp(44px,8vw,100px);
font-weight: 400;
line-height: 0.9;
letter-spacing: -0.02em;
color: var(--white);
margin-bottom: 16px;
}
.p3-sub {
font-size: 14px;
font-style: italic;
color: var(--dim);
margin-bottom: 48px;
line-height: 1.7;
}
.p3-contact-grid {
display: flex;
flex-direction: column;
gap: 16px;
border-top: 1px solid var(--mid);
padding-top: 36px;
}
.p3-contact-row {
display: flex;
justify-content: space-between;
align-items: baseline;
padding: 8px 0;
border-bottom: 1px solid var(--mid);
}
.p3-contact-key {
font-size: 8px;
letter-spacing: 0.25em;
text-transform: uppercase;
color: rgba(248,244,240,0.25);
font-family: 'Didact Gothic',sans-serif;
}
.p3-contact-val {
font-size: 13px;
font-style: italic;
color: rgba(248,244,240,0.65);
}
/* Curtain nav */
.c-nav {
position: fixed;
bottom: 40px;
left: 50%;
transform: translateX(-50%);
z-index: 800;
display: flex;
align-items: center;
gap: 24px;
background: rgba(8,8,8,0.7);
border: 1px solid var(--mid);
padding: 16px 32px;
backdrop-filter: blur(20px);
}
.c-label {
font-size: 8px;
letter-spacing: 0.3em;
text-transform: uppercase;
color: var(--dim);
font-family: 'Didact Gothic',sans-serif;
min-width: 80px;
text-align: center;
}
.c-btn {
width: 36px;
height: 36px;
border: 1px solid var(--mid);
background: none;
color: var(--dim);
font-size: 16px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: border-color .2s,color .2s;
font-family: serif;
}
.c-btn:hover {
border-color: var(--accent);
color: var(--accent);
}
.c-dots {
display: flex;
gap: 8px;
}
.c-dot {
width: 3px;
height: 3px;
border-radius: 50%;
background: rgba(248,244,240,0.2);
border: none;
cursor: pointer;
transition: background .25s,transform .3s;
}
.c-dot.active {
background: var(--accent);
transform: scale(1.8);
}
@media (max-width: 768px) {
#p0 .p0-layout {
grid-template-columns: 1fr;
}
.p0-right {
display: none;
}
.p0-left {
padding: 40px 28px;
}
#p1 {
padding: 40px 24px;
}
.look-grid {
grid-template-columns: repeat(2,1fr);
}
#p2 {
grid-template-columns: 1fr;
}
.p2-right {
display: none;
}
.p2-left {
padding: 40px 28px;
}
#p3 {
padding: 40px 28px;
}
}
```
## JavaScript
```js
const cLeft=document.getElementById('cLeft');
const cRight=document.getElementById('cRight');
const pages=document.querySelectorAll('.page');
const cdots=document.querySelectorAll('.c-dot');
const cLabel=document.getElementById('cLabel');
const labels=['Maison','Collection','Atelier','Contact'];
let cur=0,busy=false;
const dur=900;
function curtainTransition(prev,next,done){
cLeft.style.transition=`transform ${dur*0.4}ms cubic-bezier(0.76,0,0.24,1)`;
cRight.style.transition=`transform ${dur*0.4}ms cubic-bezier(0.76,0,0.24,1)`;
cLeft.classList.add('close');
cRight.classList.add('close');
setTimeout(()=>{
pages[prev].classList.remove('active');
pages[next].classList.add('active');
cLeft.style.transition=`transform ${dur*0.55}ms cubic-bezier(0.25,1,0.5,1)`;
cRight.style.transition=`transform ${dur*0.55}ms cubic-bezier(0.25,1,0.5,1)`;
cLeft.classList.remove('close');
cRight.classList.remove('close');
setTimeout(()=>{ done&&done(); },dur*0.6);
},dur*0.42);
}
function goTo(n){
if(busy||n===cur)return;
busy=true;
const prev=cur;cur=n;
cdots.forEach((d,i)=>d.classList.toggle('active',i===cur));
cLabel.textContent=labels[cur];
curtainTransition(prev,cur,()=>{busy=false;});
}
document.getElementById('cNext').onclick=()=>goTo(Math.min(3,cur+1));
document.getElementById('cPrev').onclick=()=>goTo(Math.max(0,cur-1));
cdots.forEach(d=>d.addEventListener('click',()=>goTo(+d.dataset.i)));
document.querySelectorAll('[data-next]').forEach(b=>b.addEventListener('click',()=>goTo(+b.dataset.next)));
let wt=0;
window.addEventListener('wheel',e=>{
const now=Date.now();if(now-wt<1100)return;wt=now;
goTo(Math.max(0,Math.min(3,cur+(e.deltaY>0?1:-1))));
},{passive:true});
document.addEventListener('keydown',e=>{
if(e.key==='ArrowRight')goTo(Math.min(3,cur+1));
if(e.key==='ArrowLeft')goTo(Math.max(0,cur-1));
});
```Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
Here's a working CSS Page Transition from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Vertical Split Curtain
Source: https://codefronts.com/motion/css-page-transitions/vertical-split-curtain/
Two full-height panels slide closed like theatre curtains, swap the page, then split apart with a different easing — a gold-seamed theatrical reveal. A Parisian haute couture house.
## HTML
```html
<!-- Curtain panels -->
<div class="curtain-left" id="cLeft"></div>
<div class="curtain-right" id="cRight"></div>
<div class="pages">
<div class="page active" id="p0">
<div class="p0-layout">
<div class="p0-left">
<div class="p0-mark">Maison Lécluse · Paris</div>
<div class="p0-main">
<div class="p0-season">Automne–Hiver 2025</div>
<h1 class="p0-title">Entre<br>Ombre<br>& Lumière</h1>
<div class="p0-title-fr">Between shadow and light</div>
<p class="p0-body">A collection born from the silences between words. Forty-two looks. Each one a conversation the body has alone.</p>
<button class="p0-cta" data-next="1">Discover the collection <span class="p0-cta-arrow"></span></button>
</div>
</div>
<div class="p0-right">
<div class="silhouette-area">
<div class="figure">
<div class="fig-head"></div>
<div class="fig-arm fig-arm-l"></div>
<div class="fig-arm fig-arm-r"></div>
<div class="fig-body"></div>
</div>
</div>
<div class="p0-right-bottom">
<div class="p0-detail-row"><div class="det-key">Maison</div><div class="det-val">Since 1967</div></div>
<div class="p0-detail-row"><div class="det-key">Ateliers</div><div class="det-val">Paris · Florence</div></div>
<div class="p0-detail-row"><div class="det-key">Collection</div><div class="det-val">AH 2025 · 42 looks</div></div>
<div class="p0-detail-row"><div class="det-key">Runway</div><div class="det-val">Palais Royal, 4 Oct</div></div>
</div>
</div>
</div>
</div>
<div class="page" id="p1">
<div class="p1-top">
<h2 class="p1-title">The<br>Collection</h2>
<div class="p1-count">42 Looks · AH 2025</div>
</div>
<div class="look-grid">
<div class="look"><div class="look-img"><div class="garment g1"></div></div><div class="look-num">Look 01</div><div class="look-name">L'aube noire</div></div>
<div class="look"><div class="look-img"><div class="garment g2"></div></div><div class="look-num">Look 07</div><div class="look-name">Le voile froid</div></div>
<div class="look"><div class="look-img"><div class="garment g3"></div></div><div class="look-num">Look 14</div><div class="look-name">La colonne</div></div>
<div class="look"><div class="look-img"><div class="garment g4"></div></div><div class="look-num">Look 21</div><div class="look-name">Le bruissement</div></div>
<div class="look"><div class="look-img"><div class="garment g5"></div></div><div class="look-num">Look 38</div><div class="look-name">La chute</div></div>
</div>
</div>
<div class="page" id="p2">
<div class="p2-left">
<div class="p2-eyebrow">L'Atelier Lécluse</div>
<h2 class="p2-title">Made by<br>hand, in<br>silence</h2>
<p class="p2-body">Each garment passes through twenty-four pairs of hands before it leaves the atelier. We consider this not a process, but a conversation with the material.</p>
<div class="craft-list">
<div class="craft-row"><div class="craft-n">I</div><div class="craft-t">Pattern cutting by master tailleur</div></div>
<div class="craft-row"><div class="craft-n">II</div><div class="craft-t">Hand-draping on the mannequin</div></div>
<div class="craft-row"><div class="craft-n">III</div><div class="craft-t">Three fittings per garment minimum</div></div>
<div class="craft-row"><div class="craft-n">IV</div><div class="craft-t">Handstitched finishing throughout</div></div>
<div class="craft-row"><div class="craft-n">V</div><div class="craft-t">Final inspection by the directrice</div></div>
</div>
</div>
<div class="p2-right">
<div class="maison-since">Maison Lécluse · Since 1967</div>
<div class="p2-numbers">
<div class="num-item"><div class="num-big">58</div><div class="num-label">Years of haute<br>couture</div></div>
<div class="num-item"><div class="num-big">24</div><div class="num-label">Artisan hands per<br>garment</div></div>
<div class="num-item"><div class="num-big">200+</div><div class="num-label">Hours in a single<br>couture piece</div></div>
</div>
</div>
</div>
<div class="page" id="p3">
<div class="p3-bg-text">ML</div>
<div class="p3-content">
<span class="p3-mark">Maison Lécluse · Paris</span>
<h2 class="p3-title">Private<br>Fitting</h2>
<p class="p3-sub">By appointment only. Ateliers are open to clients for consultation from Tuesday through Saturday.</p>
<div class="p3-contact-grid">
<div class="p3-contact-row"><div class="p3-contact-key">Address</div><div class="p3-contact-val">24 Rue du Faubourg Saint-Honoré</div></div>
<div class="p3-contact-row"><div class="p3-contact-key">Telephone</div><div class="p3-contact-val">+33 1 42 68 00 00</div></div>
<div class="p3-contact-row"><div class="p3-contact-key">Fitting hours</div><div class="p3-contact-val">Mar–Sam · 10h–18h</div></div>
<div class="p3-contact-row"><div class="p3-contact-key">Correspondence</div><div class="p3-contact-val">atelier@lecluse.paris</div></div>
</div>
</div>
</div>
</div>
<!-- Nav -->
<div class="c-nav">
<button class="c-btn" id="cPrev">‹</button>
<div class="c-dots">
<button class="c-dot active" data-i="0"></button>
<button class="c-dot" data-i="1"></button>
<button class="c-dot" data-i="2"></button>
<button class="c-dot" data-i="3"></button>
</div>
<div class="c-label" id="cLabel">Maison</div>
<button class="c-btn" id="cNext">›</button>
</div>
```
## CSS
```css
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
:root {
--noir: #080808;
--white: #f8f4f0;
--warm: #e8e0d4;
--dim: rgba(248,244,240,0.4);
--accent: #c8a060;
--mid: rgba(248,244,240,0.1);
--dur: 900ms;
--ease: cubic-bezier(0.76,0,0.24,1);
}
html,
body {
height: 100%;
overflow: hidden;
background: var(--noir);
font-family: 'Cormorant Garamond',serif;
}
/* Pages */
.pages {
position: fixed;
inset: 0;
}
.page {
position: absolute;
inset: 0;
pointer-events: none;
visibility: hidden;
}
.page.active {
visibility: visible;
pointer-events: auto;
}
/* Curtain panels */
.curtain-left,
.curtain-right {
position: fixed;
top: 0;
bottom: 0;
z-index: 700;
background: var(--noir);
will-change: transform;
}
.curtain-left {
left: 0;
width: 50%;
transform: translateX(-100%);
transform-origin: left;
}
.curtain-right {
right: 0;
width: 50%;
transform: translateX(100%);
transform-origin: right;
}
/* Centre seam line */
.curtain-left::after {
content: '';
position: absolute;
right: 0;
top: 0;
bottom: 0;
width: 1px;
background: linear-gradient(180deg,transparent,var(--accent),transparent);
opacity: 0;
}
/* States */
.curtain-left.close {
transform: translateX(0);
}
.curtain-right.close {
transform: translateX(0);
}
.curtain-left.close::after {
opacity: 0.4;
}
/* PAGE 0 — MAISON */
#p0 {
background: var(--noir);
color: var(--white);
}
.p0-layout {
height: 100%;
display: grid;
grid-template-columns: 1fr 1fr;
}
.p0-left {
padding: 60px 80px;
display: flex;
flex-direction: column;
justify-content: space-between;
border-right: 1px solid var(--mid);
}
.p0-mark {
font-family: 'Italiana',serif;
font-size: 11px;
letter-spacing: 0.4em;
text-transform: uppercase;
color: var(--dim);
}
.p0-main {
flex: 1;
display: flex;
flex-direction: column;
justify-content: flex-end;
padding-bottom: 20px;
}
.p0-season {
font-size: 8px;
letter-spacing: 0.4em;
text-transform: uppercase;
color: var(--accent);
margin-bottom: 24px;
display: flex;
align-items: center;
gap: 12px;
}
.p0-season::before {
content: '';
width: 20px;
height: 1px;
background: var(--accent);
}
.p0-title {
font-family: 'Italiana',serif;
font-size: clamp(52px,8vw,112px);
font-weight: 400;
line-height: 0.9;
letter-spacing: -0.02em;
color: var(--white);
margin-bottom: 24px;
}
.p0-title-fr {
font-size: clamp(24px,3.5vw,48px);
font-style: italic;
font-weight: 300;
color: rgba(248,244,240,0.35);
margin-bottom: 40px;
}
.p0-body {
font-size: 13px;
line-height: 1.9;
font-weight: 300;
color: var(--dim);
max-width: 380px;
font-style: italic;
}
.p0-cta {
margin-top: 40px;
display: inline-flex;
align-items: center;
gap: 16px;
font-size: 9px;
letter-spacing: 0.3em;
text-transform: uppercase;
color: var(--white);
cursor: pointer;
background: none;
border: none;
font-family: 'Didact Gothic',sans-serif;
transition: color .2s;
}
.p0-cta:hover {
color: var(--accent);
}
.p0-cta-arrow {
width: 40px;
height: 1px;
background: currentColor;
transition: width .3s;
position: relative;
}
.p0-cta-arrow::after {
content: '';
position: absolute;
right: -1px;
top: -3px;
width: 7px;
height: 7px;
border-right: 1px solid currentColor;
border-top: 1px solid currentColor;
transform: rotate(45deg);
}
.p0-cta:hover .p0-cta-arrow {
width: 64px;
}
.p0-right {
display: grid;
grid-template-rows: 1fr 1fr;
padding: 60px;
gap: 0;
}
/* Abstract fashion illustration using CSS shapes */
.silhouette-area {
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.figure {
position: relative;
width: 80px;
height: 200px;
}
.fig-body {
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 48px;
height: 140px;
background: linear-gradient(180deg,rgba(200,160,96,0.2),rgba(200,160,96,0.06));
border: 1px solid rgba(200,160,96,0.2);
border-radius: 2px 2px 0 0;
}
.fig-head {
position: absolute;
bottom: 136px;
left: 50%;
transform: translateX(-50%);
width: 20px;
height: 24px;
border-radius: 50%;
background: rgba(200,160,96,0.15);
border: 1px solid rgba(200,160,96,0.2);
}
.fig-arm {
position: absolute;
height: 1px;
background: rgba(200,160,96,0.25);
top: 72px;
}
.fig-arm-l {
width: 32px;
right: 48px;
}
.fig-arm-r {
width: 32px;
left: 48px;
}
.p0-right-bottom {
display: flex;
flex-direction: column;
justify-content: flex-end;
gap: 16px;
}
.p0-detail-row {
display: flex;
justify-content: space-between;
align-items: baseline;
border-bottom: 1px solid var(--mid);
padding: 12px 0;
}
.det-key {
font-size: 8px;
letter-spacing: 0.25em;
text-transform: uppercase;
color: rgba(248,244,240,0.25);
font-family: 'Didact Gothic',sans-serif;
}
.det-val {
font-size: 12px;
font-style: italic;
color: rgba(248,244,240,0.6);
}
/* PAGE 1 — COLLECTION */
#p1 {
background: #0c0c0c;
color: var(--white);
padding: 60px 80px;
display: flex;
flex-direction: column;
}
.p1-top {
display: flex;
align-items: flex-end;
justify-content: space-between;
margin-bottom: 52px;
padding-bottom: 24px;
border-bottom: 1px solid var(--mid);
}
.p1-title {
font-family: 'Italiana',serif;
font-size: clamp(44px,7vw,100px);
font-weight: 400;
line-height: 0.9;
letter-spacing: -0.02em;
}
.p1-count {
font-size: 9px;
letter-spacing: 0.25em;
color: var(--dim);
font-family: 'Didact Gothic',sans-serif;
text-transform: uppercase;
}
.look-grid {
display: grid;
grid-template-columns: repeat(5,1fr);
gap: 12px;
flex: 1;
}
.look {
display: flex;
flex-direction: column;
gap: 12px;
cursor: pointer;
}
.look-img {
flex: 1;
border: 1px solid rgba(248,244,240,0.06);
position: relative;
overflow: hidden;
min-height: 200px;
background: linear-gradient(180deg,#111,#0a0a0a);
transition: border-color .3s;
}
.look:hover .look-img {
border-color: rgba(200,160,96,0.3);
}
/* Abstract garment shape */
.garment {
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 60%;
background: rgba(200,160,96,0.08);
border-top: 1px solid rgba(200,160,96,0.15);
}
.g1 {
height: 70%;
border-radius: 2px 2px 0 0;
}
.g2 {
height: 85%;
clip-path: polygon(20% 0,80% 0,100% 100%,0 100%);
}
.g3 {
height: 60%;
border-radius: 40% 40% 0 0;
}
.g4 {
height: 75%;
clip-path: polygon(0 0,100% 0,90% 100%,10% 100%);
}
.g5 {
height: 90%;
clip-path: polygon(30% 0,70% 0,100% 100%,0 100%);
}
.look-num {
font-size: 8px;
letter-spacing: 0.2em;
color: var(--accent);
font-family: 'Didact Gothic',sans-serif;
}
.look-name {
font-family: 'Cormorant Garamond',serif;
font-size: 13px;
font-style: italic;
color: rgba(248,244,240,0.7);
}
/* PAGE 2 — ATELIER */
#p2 {
background: var(--white);
color: var(--noir);
display: grid;
grid-template-columns: 1fr 1fr;
}
.p2-left {
padding: 80px;
display: flex;
flex-direction: column;
justify-content: center;
background: #f0ece6;
}
.p2-eyebrow {
font-size: 8px;
letter-spacing: 0.35em;
text-transform: uppercase;
color: var(--accent);
margin-bottom: 28px;
font-family: 'Didact Gothic',sans-serif;
}
.p2-title {
font-family: 'Italiana',serif;
font-size: clamp(44px,6vw,80px);
font-weight: 400;
line-height: 1.0;
color: var(--noir);
letter-spacing: -0.02em;
margin-bottom: 28px;
}
.p2-body {
font-size: 15px;
line-height: 1.85;
font-weight: 300;
font-style: italic;
color: rgba(8,8,8,0.5);
max-width: 400px;
margin-bottom: 48px;
}
.craft-list {
display: flex;
flex-direction: column;
gap: 0;
}
.craft-row {
display: flex;
gap: 20px;
padding: 18px 0;
border-bottom: 1px solid rgba(8,8,8,0.08);
align-items: baseline;
}
.craft-n {
font-size: 9px;
letter-spacing: 0.15em;
color: var(--accent);
font-family: 'Didact Gothic',sans-serif;
width: 24px;
flex-shrink: 0;
}
.craft-t {
font-size: 14px;
font-style: italic;
color: rgba(8,8,8,0.6);
}
.p2-right {
padding: 80px;
background: var(--white);
display: flex;
flex-direction: column;
justify-content: center;
border-left: 1px solid rgba(8,8,8,0.06);
}
.maison-since {
font-size: 9px;
letter-spacing: 0.35em;
text-transform: uppercase;
color: rgba(8,8,8,0.25);
margin-bottom: 40px;
font-family: 'Didact Gothic',sans-serif;
}
.p2-numbers {
display: flex;
flex-direction: column;
gap: 28px;
}
.num-item {
display: flex;
align-items: baseline;
gap: 20px;
padding-bottom: 28px;
border-bottom: 1px solid rgba(8,8,8,0.06);
}
.num-big {
font-family: 'Italiana',serif;
font-size: 56px;
color: var(--noir);
line-height: 1;
}
.num-label {
font-size: 12px;
font-style: italic;
color: rgba(8,8,8,0.45);
line-height: 1.4;
}
/* PAGE 3 — CONTACT */
#p3 {
background: var(--noir);
color: var(--white);
display: flex;
align-items: center;
justify-content: center;
text-align: center;
padding: 80px;
position: relative;
overflow: hidden;
}
.p3-bg-text {
position: absolute;
font-family: 'Italiana',serif;
font-size: 30vw;
color: rgba(248,244,240,0.025);
line-height: 1;
letter-spacing: -0.06em;
pointer-events: none;
user-select: none;
}
.p3-content {
position: relative;
max-width: 560px;
}
.p3-mark {
font-family: 'Italiana',serif;
font-size: 9px;
letter-spacing: 0.5em;
text-transform: uppercase;
color: var(--dim);
margin-bottom: 48px;
display: block;
}
.p3-title {
font-family: 'Italiana',serif;
font-size: clamp(44px,8vw,100px);
font-weight: 400;
line-height: 0.9;
letter-spacing: -0.02em;
color: var(--white);
margin-bottom: 16px;
}
.p3-sub {
font-size: 14px;
font-style: italic;
color: var(--dim);
margin-bottom: 48px;
line-height: 1.7;
}
.p3-contact-grid {
display: flex;
flex-direction: column;
gap: 16px;
border-top: 1px solid var(--mid);
padding-top: 36px;
}
.p3-contact-row {
display: flex;
justify-content: space-between;
align-items: baseline;
padding: 8px 0;
border-bottom: 1px solid var(--mid);
}
.p3-contact-key {
font-size: 8px;
letter-spacing: 0.25em;
text-transform: uppercase;
color: rgba(248,244,240,0.25);
font-family: 'Didact Gothic',sans-serif;
}
.p3-contact-val {
font-size: 13px;
font-style: italic;
color: rgba(248,244,240,0.65);
}
/* Curtain nav */
.c-nav {
position: fixed;
bottom: 40px;
left: 50%;
transform: translateX(-50%);
z-index: 800;
display: flex;
align-items: center;
gap: 24px;
background: rgba(8,8,8,0.7);
border: 1px solid var(--mid);
padding: 16px 32px;
backdrop-filter: blur(20px);
}
.c-label {
font-size: 8px;
letter-spacing: 0.3em;
text-transform: uppercase;
color: var(--dim);
font-family: 'Didact Gothic',sans-serif;
min-width: 80px;
text-align: center;
}
.c-btn {
width: 36px;
height: 36px;
border: 1px solid var(--mid);
background: none;
color: var(--dim);
font-size: 16px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: border-color .2s,color .2s;
font-family: serif;
}
.c-btn:hover {
border-color: var(--accent);
color: var(--accent);
}
.c-dots {
display: flex;
gap: 8px;
}
.c-dot {
width: 3px;
height: 3px;
border-radius: 50%;
background: rgba(248,244,240,0.2);
border: none;
cursor: pointer;
transition: background .25s,transform .3s;
}
.c-dot.active {
background: var(--accent);
transform: scale(1.8);
}
@media (max-width: 768px) {
#p0 .p0-layout {
grid-template-columns: 1fr;
}
.p0-right {
display: none;
}
.p0-left {
padding: 40px 28px;
}
#p1 {
padding: 40px 24px;
}
.look-grid {
grid-template-columns: repeat(2,1fr);
}
#p2 {
grid-template-columns: 1fr;
}
.p2-right {
display: none;
}
.p2-left {
padding: 40px 28px;
}
#p3 {
padding: 40px 28px;
}
}
```
## JavaScript
```js
const cLeft=document.getElementById('cLeft');
const cRight=document.getElementById('cRight');
const pages=document.querySelectorAll('.page');
const cdots=document.querySelectorAll('.c-dot');
const cLabel=document.getElementById('cLabel');
const labels=['Maison','Collection','Atelier','Contact'];
let cur=0,busy=false;
const dur=900;
function curtainTransition(prev,next,done){
cLeft.style.transition=`transform ${dur*0.4}ms cubic-bezier(0.76,0,0.24,1)`;
cRight.style.transition=`transform ${dur*0.4}ms cubic-bezier(0.76,0,0.24,1)`;
cLeft.classList.add('close');
cRight.classList.add('close');
setTimeout(()=>{
pages[prev].classList.remove('active');
pages[next].classList.add('active');
cLeft.style.transition=`transform ${dur*0.55}ms cubic-bezier(0.25,1,0.5,1)`;
cRight.style.transition=`transform ${dur*0.55}ms cubic-bezier(0.25,1,0.5,1)`;
cLeft.classList.remove('close');
cRight.classList.remove('close');
setTimeout(()=>{ done&&done(); },dur*0.6);
},dur*0.42);
}
function goTo(n){
if(busy||n===cur)return;
busy=true;
const prev=cur;cur=n;
cdots.forEach((d,i)=>d.classList.toggle('active',i===cur));
cLabel.textContent=labels[cur];
curtainTransition(prev,cur,()=>{busy=false;});
}
document.getElementById('cNext').onclick=()=>goTo(Math.min(3,cur+1));
document.getElementById('cPrev').onclick=()=>goTo(Math.max(0,cur-1));
cdots.forEach(d=>d.addEventListener('click',()=>goTo(+d.dataset.i)));
document.querySelectorAll('[data-next]').forEach(b=>b.addEventListener('click',()=>goTo(+b.dataset.next)));
let wt=0;
window.addEventListener('wheel',e=>{
const now=Date.now();if(now-wt<1100)return;wt=now;
goTo(Math.max(0,Math.min(3,cur+(e.deltaY>0?1:-1))));
},{passive:true});
document.addEventListener('keydown',e=>{
if(e.key==='ArrowRight')goTo(Math.min(3,cur+1));
if(e.key==='ArrowLeft')goTo(Math.max(0,cur-1));
});
```