Skip to content

Instantly share code, notes, and snippets.

@darvil82
Last active May 4, 2022 21:56
Show Gist options
  • Save darvil82/3c5ce73c7ac7ad10e269ca5c17f3151b to your computer and use it in GitHub Desktop.
Save darvil82/3c5ce73c7ac7ad10e269ca5c17f3151b to your computer and use it in GitHub Desktop.
Envelope
<div class="envelope">
<div class="wrapper"></div>
<div class="content">
<h1 class="title">This is a letter for you</h1>
Lorem ipsum, dolor sit amet consectetur adipisicing elit. Corporis tenetur quasi fugiat sed temporibus possimus. Omnis voluptatem totam nemo facere, cumque officia. Tempore unde quis adipisci natus placeat corporis sed.
</div>
</div>
const envelopes = document.querySelectorAll(".envelope")
envelopes.forEach(e => {
let lastTime = 0
e.addEventListener("click", () => {
if (new Date() - lastTime <= 1000) return
if (e.classList.contains("open")) {
e.classList.add("close")
e.classList.remove("open")
e.addEventListener("animationend",
() => e.classList.remove("close"),
{ once: true }
)
} else {
e.classList.remove("close")
e.classList.add("open")
}
lastTime = new Date();
})
})
*, *::after, *::before {
box-sizing: border-box;
}
body, html {
height: 100%;
}
body {
display: flex;
justify-content: center;
align-items: center;
background-color: #333;
font-size: 1.3em;
}
.title {
margin-top: 0;
font-size: 1.5em;
}
.envelope {
$content-rotation: 15deg;
max-width: 600px;
min-height: 300px;
background-color: #eee;
box-shadow: inset 0 0 2em rgba(0 0 0 / 25%);
position: relative;
border: 2px solid #aaa;
filter: drop-shadow(0 0 1.25em rgba(0 0 0 / 50%));
border-radius: 10px;
transition: .25s;
perspective: 1000px;
cursor: pointer;
// the content of the letter
.content {
padding: 1em;
margin: .25em;
padding-bottom: 3em;
background-color: #ffc;
box-shadow:
inset 0 0 2em rgba(0 0 0 / 20%),
inset 0 0 .25em rgba(0 0 0 / 25%);
transition: .75s;
border-radius: 4px;
filter: drop-shadow(0 0 .5em rgba(0 0 0 / 20%));
}
// flap
&::before, &::after {
content: "";
position: absolute;
inset: 0;
height: 40%;
clip-path: polygon(100% 0, 100% 10%, 50% 100%, 0 10%, 0 0);
transform-origin: top;
transition: .5s .75s;
border-radius: 7px;
z-index: 2;
}
// inner part of the flap
&::after {
background-image: conic-gradient(from 180deg at 50% 100%, #bbb 80deg, white 150deg, white, #bbb 300deg);
}
// flap border
&::before {
inset: 0.1em;
background-color: #ccc;
height: calc(40% + .25em);
}
// for the wrapper of the letter
.wrapper, .wrapper::after {
content: "";
position: absolute;
inset: 0;
clip-path: polygon(50% 30%, 100% 0%, 100% 100%, 0 100%, 0 0);
z-index: 1;
}
// for the wrapper of the letter
.wrapper {
background-color: #ccc;
border-radius: 7px;
overflow: hidden;
// for the inner part
&::after {
background-color: white;
box-shadow: inset 0 0 3em 13px #aaa;
}
}
&.close {
// moves the wrapper to the top, hiding the content
.wrapper, .wrapper::after {
z-index: 10;
transition: z-index 0s .5s;
}
.content {
animation: move-in 1s forwards;
// plays the move-in animation
@keyframes move-in {
0% {
transform: translateY(2em) rotateX($content-rotation);
z-index: 10;
}
70% {
transform: translateY(calc(-100% - 2em));
}
}
}
}
&.open {
// moves the wrapper to the bottom, allowing the content
// to be displayed
.wrapper, .wrapper::after {
z-index: 0;
transition: z-index 0s 0.5s;
}
// plays the move-out animation
.content {
animation: move-out 1s .25s forwards;
@keyframes move-out {
40% {
transform: translateY(calc(-100% - 2em));
}
100% {
transform: translateY(2em) rotateX($content-rotation);
z-index: 10;
}
}
}
}
&.open, &:hover {
transform: scale(1.05);
.content {
transition: transform .75s .15s;
}
// rotates the flaps 180degrees and darkens it
&::before, &::after {
transform: rotateX(-180deg);
z-index: -1;
transition: .5s;
filter: brightness(0.8);
}
}
// moves the card up a bit
&:hover {
.content {
transform: translateY(-2em);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment