* {
box-sizing: border-box;
}
body {
font-family: "Signika Negative", sans-serif;
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
padding: 0;
margin: 0;
background-color: #1d1e22;
color: #23272a;
font-size: var(--step-0);
line-height: 1.34;
overflow: hidden;
--one: hsl(192deg 40% 43%);
--two: hsl(268deg 45% 46%);
--three:hsl(268deg 45% 42%);
--four: hsl(192deg 40% 43%);
--five: hsl(356deg 80% 25%);
}
h1,
h2 {
margin: 0;
}
p {
margin-top: 0.75em;
color: #4c4c52;
}
a {
color: #61AC27;
font-weight: bold;
}
h1 {
font-size: var(--step-2);
}
h2 {
font-size: var(--step-1);
}
.content--open {
display: none;
max-width: 750px;
margin: 0 auto;
}
.open .content--open {
display: block;
}
.open .content--closed {
display: none;
visibility: hidden;
}
.card {
position: relative;
background: #fff;
padding: var(--space-s-l);
padding-top: 80px;
width: 90vw;
max-width: 580px;
border-radius: 16px;
margin-top: 120px;
cursor: pointer;
}
.flipping.card {
max-width: unset;
}
.open .card {
position: fixed;
bottom: 0;
left: 0;
right: 0;
border-radius: 0;
width: 100%;
max-width: 100%;
height: 40vh;
padding: var(--space-s-xl);
padding-top: 90px;
}
@media only screen and (max-width: 600px) {
.open .card {
height: 65vh;
padding-top: 75px;
}
.card {
padding-top: 65px
}
}
.gift-container {
position: absolute;
bottom: calc(100% - 120px);
z-index: 3;
opacity: 0;
left: calc(50% - 125px);
}
.open .gift-container {
left: 8rem;
}
.bottom {
--width: 20;
--height: 15;
--depth: 20;
}
.top {
--width: 22;
--height: 5;
--depth: 22;
}
.plane {
height: 250px;
width: 250px;
transform-style: preserve-3d;
transform: rotateX(-15deg) rotateY(314deg) rotateX(90deg) translate3d(0, 0, 0);
--size: 8px;
}
@media only screen and (max-width: 600px) {
.plane {
--size: 5px;
}
.gift-container {
bottom: calc(100% - 150px);
left: calc(50% - 125px);
}
.open .gift-container {
left: -2rem;
}
}
.box > div {
background: linear-gradient(
to right,
var(--three),
var(--three) 42%,
var(--one) 42%,
var(--one) 58%,
var(--three) 58%
);
}
.top {
transform: translate3d(0, 0, calc(8 * var(--size)));
}
.top > div:nth-of-type(5) {
background: linear-gradient(
to bottom,
transparent,
transparent 42%,
var(--one) 42%,
var(--one) 58%,
transparent 58%
),
linear-gradient(
to right,
var(--two),
var(--two) 42%,
var(--one) 42%,
var(--one) 58%,
var(--two) 58%
);
}
.bottom > div:nth-of-type(5) {
background: transparent;
}
.bottom > div:nth-of-type(2),
.bottom > div:nth-of-type(4) {
background: #422e61;
border: solid 0.2px #341d1d;
z-index: -200,
}
.box {
height: calc(var(--depth) * var(--size));
width: calc(var(--width) * var(--size));
transform-style: preserve-3d;
position: absolute;
font-size: 1rem;
}
.box > div:nth-of-type(1) {
height: calc(var(--height) * var(--size));
width: 100%;
transform-origin: 50% 50%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotateX(-90deg) translate3d(0, 0, calc((var(--depth) / 2) * var(--size)));
background: linear-gradient(
to right,
var(--three),
var(--three) 42%,
var(--one) 42%,
var(--one) 58%,
var(--three) 58%
);
}
.box > div:nth-of-type(2) {
height: calc(var(--height) * var(--size));
width: 100%;
transform-origin: 50% 50%;
transform: translate(-50%, -50%) rotateX(-90deg) rotateY(180deg) translate3d(0, 0, calc((var(--depth) / 2) * var(--size)));
position: absolute;
top: 50%;
left: 50%;
}
.box > div:nth-of-type(3) {
height: calc(var(--height) * var(--size));
width: calc(var(--depth) * var(--size));
transform: translate(-50%, -50%) rotateX(-90deg) rotateY(90deg) translate3d(0, 0, calc((var(--width) / 2) * var(--size)));
position: absolute;
top: 50%;
left: 50%;
}
.box > div:nth-of-type(4) {
height: calc(var(--height) * var(--size));
width: calc(var(--depth) * var(--size));
transform: translate(-50%, -50%) rotateX(-90deg) rotateY(-90deg) translate3d(0, 0, calc((var(--width) / 2) * var(--size)));
position: absolute;
top: 50%;
left: 50%;
}
.box > div:nth-of-type(5) {
height: calc(var(--depth) * var(--size));
width: calc(var(--width) * var(--size));
transform: translate(-50%, -50%) translate3d(0, 0, calc((var(--height) / 2) * var(--size)));
position: absolute;
top: 50%;
left: 50%;
}
.box > div:nth-of-type(6) {
height: calc(var(--depth) * var(--size));
width: calc(var(--width) * var(--size));
transform: translate(-50%, -50%) translate3d(0, 0, calc((var(--height) / 2) * var(--size) * -1)) rotateX(180deg);
position: absolute;
top: 50%;
left: 50%;
}
.top > div:nth-of-type(6) {
background: transparent
}
.confetti {
position: absolute;
width: 20px;
height: 20px;
left: 48%;
top: 40%;
z-index: 1
}
.confetti-cont {
width: 100px;
height: 100px;
transform: rotate(312deg) rotateY(181deg) rotateX(72deg) translate3d(0, 0, 4px);
}
.letters {
display: flex;
flex-direction: row;
align-items: center;
left: 0;
bottom: 50%;
}
.letter {
text-align: center;
color: black;
font-size: 15vmin;
font-weight: 400;
display: flex;
align-items: center;
justify-content: center;
padding: 2px 6px;
}
.F {
background: #428899;
}
.l {
background: #386ab5;
}
.i {
background: #683b9c;
}
.p {
background: #424d9f;
}
.for, .gsap {
display: none;
color: white;
font-size: 5vmin;
}
.for {
padding: 2px 1.6vmin;
font-weight: 300;
}
.gsap {
padding: 2px 0;
font-weight: 600;
}
.open {
align-items: flex-start;
}
.open .for, .open .gsap {
display: block;
z-index: -4
}
.letters {
z-index: -3;
}
.gift-container > .letters {
position: absolute;
transform: scale(0.2);
.letter {
opacity: 0;
}
}
.open > .letters {
margin-top: 5vh;
height: 40vh;
margin-left: 3rem;
opacity: 1;
transform: scale(1)
}
.logo {
position: fixed;
width: 60px;
bottom: 20px;
right: 30px;
z-index: 9999;
}
View Compiled
let confettis = document.querySelector(".confetti-cont");
let container = document.querySelector(".gift-container");
gsap.set(container, { opacity: 1 });
let explosion = gsap.timeline({ paused: true });
for (let i = 0; i < 100; i++) {
let c = document.createElement("div");
c.innerHTML = gsap.utils.random(["💚", "✨", "⭐", "💙", "💜"]);
c.setAttribute("class", "confetti");
confettis.appendChild(c);
explosion.to(
c,
{
keyframes: [
{
opacity: 1,
duration: 0.01
},
{
duration: 3,
physics2D: {
velocity: "random(200, 650)",
angle: "random(250, 290)",
gravity: 300
}
},
{
opacity: 0,
duration: 0.3,
delay: -2
}
]
},
Math.random() * 2
);
}
let tl = gsap.timeline({
paused: true
});
tl.to(".top", {
z: 110,
duration: 0.2,
ease: "back.out"
})
.to(
".top",
{
rotate: 360,
transformOrigin: "center center",
duration: 1,
ease: "back.out"
},
"-=0.2"
)
.to(".top", {
z: 80,
scale: 0.9,
rotateY: -240,
x: -15,
duration: 1.2,
transformOrigin: "center left",
ease: "sine.inOut",
onStart: () => {
explosion.play(0);
}
})
.reverse();
let card = document.querySelector(".card");
let letters = document.querySelector(".letters");
let isOpen;
card.addEventListener("click", () => {
isOpen = !isOpen;
const cardState = Flip.getState(
".card, .gift-container, .content--open, .content--closed",
{ props: "borderRadius,padding" }
);
const letterState = Flip.getState(".letter, .for, .gsap", {
props: "opacity"
});
document.body.classList.toggle("open");
if (isOpen) {
document.body.appendChild(letters);
} else {
container.appendChild(letters);
explosion.progress(0).pause();
}
Flip.from(cardState, {
absolute: '.card',
nested: true,
duration: 0.75,
ease: "sine.inOut",
toggleClass: 'flipping',
onStart: () => {
isOpen ? tl.timeScale(1).play() : tl.timeScale(1.5).reverse()
;
},
onEnter: (elements) => {
gsap.fromTo(
elements,
{ autoAlpha: 0 },
{ autoAlpha: 1, duration: 0.5, delay: 0.75, overwrite: true }
);
},
onLeave: (elements) => {
gsap.fromTo(
elements,
{ autoAlpha: 1 },
{ autoAlpha: 0, duration: 0.01, overwrite: true }
);
}
});
Flip.from(letterState, {
duration: 1,
delay: isOpen ? 1 : 0,
ease: "power1.inOut",
scale: true,
stagger: 0.2,
nested: true,
spin: isOpen ? -1 : 1,
onEnter: (elements) => {
gsap.fromTo(
elements,
{ autoAlpha: 0, x: -40 },
{
autoAlpha: 1,
x: 0,
duration: 1,
delay: isOpen ? 2.75 : 0,
overwrite: true,
stagger: 0.2
}
);
}
});
});