mixin flaps(taped)
.package__flap.package__flap--top
if taped
.package__tape.package__tape--top
.package__flap.package__flap--bottom
if taped
.package__tape.package__tape--bottom
input#package(type="checkbox")
input#one(type="radio" name='size')
label.size-label.one(for="one") S
input#two(type="radio" name='size' checked)
label.size-label.two(for="two") M
input#three(type="radio" name='size')
label.size-label.three(for="three") L
input#four(type="radio" name='size')
label.size-label.four(for="four") XL
label.close(for="package") Close Package
label.open(for="package") Open Package
.scene
.package__wrapper
.package__shadow
.package
.package__content
svg.package__icon.package__icon--css(role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg")
title CSS3
path(d="M1.5 0h21l-1.91 21.563L11.977 24l-8.565-2.438L1.5 0zm17.09 4.413L5.41 4.41l.213 2.622 10.125.002-.255 2.716h-6.64l.24 2.573h6.182l-.366 3.523-2.91.804-2.956-.81-.188-2.11h-2.61l.29 3.855L12 19.288l5.373-1.53L18.59 4.414z")
svg.package__icon.package__icon--html(role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg")
title HTML5
path(d="M1.5 0h21l-1.91 21.563L11.977 24l-8.564-2.438L1.5 0zm7.031 9.75l-.232-2.718 10.059.003.23-2.622L5.412 4.41l.698 8.01h9.126l-.326 3.426-2.91.804-2.955-.81-.188-2.11H6.248l.33 4.171L12 19.351l5.379-1.443.744-8.157H8.531z")
svg.package__icon.package__icon--js(role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg")
title JavaScript
path(d="M0 0h24v24H0V0zm22.034 18.276c-.175-1.095-.888-2.015-3.003-2.873-.736-.345-1.554-.585-1.797-1.14-.091-.33-.105-.51-.046-.705.15-.646.915-.84 1.515-.66.39.12.75.42.976.9 1.034-.676 1.034-.676 1.755-1.125-.27-.42-.404-.601-.586-.78-.63-.705-1.469-1.065-2.834-1.034l-.705.089c-.676.165-1.32.525-1.71 1.005-1.14 1.291-.811 3.541.569 4.471 1.365 1.02 3.361 1.244 3.616 2.205.24 1.17-.87 1.545-1.966 1.41-.811-.18-1.26-.586-1.755-1.336l-1.83 1.051c.21.48.45.689.81 1.109 1.74 1.756 6.09 1.666 6.871-1.004.029-.09.24-.705.074-1.65l.046.067zm-8.983-7.245h-2.248c0 1.938-.009 3.864-.009 5.805 0 1.232.063 2.363-.138 2.711-.33.689-1.18.601-1.566.48-.396-.196-.597-.466-.83-.855-.063-.105-.11-.196-.127-.196l-1.825 1.125c.305.63.75 1.172 1.324 1.517.855.51 2.004.675 3.207.405.783-.226 1.458-.691 1.811-1.411.51-.93.402-2.07.397-3.346.012-2.054 0-4.109 0-6.179l.004-.056z")
.package__side.package__side--main
+flaps(true)
.package__side.package__side--tabbed
img.package__branding.package__branding--shadow(src="https://assets.codepen.io/605876/avatar.png")
img.package__branding(src="https://assets.codepen.io/605876/avatar.png")
+flaps()
.package__side.package__side--extra
+flaps()
.package__side.package__side--flipped
span.package__direction
svg(viewBox="0 0 256 512" title="long-arrow-alt-up")
path(d="M88 166.059V468c0 6.627 5.373 12 12 12h56c6.627 0 12-5.373 12-12V166.059h46.059c21.382 0 32.09-25.851 16.971-40.971l-86.059-86.059c-9.373-9.373-24.569-9.373-33.941 0l-86.059 86.059c-15.119 15.119-4.411 40.971 16.971 40.971H88z")
span THIS WAY UP
svg(viewBox="0 0 256 512" title="long-arrow-alt-up")
path(d="M88 166.059V468c0 6.627 5.373 12 12 12h56c6.627 0 12-5.373 12-12V166.059h46.059c21.382 0 32.09-25.851 16.971-40.971l-86.059-86.059c-9.373-9.373-24.569-9.373-33.941 0l-86.059 86.059c-15.119 15.119-4.411 40.971 16.971 40.971H88z")
span.package__label.package__label--shadow
span.package__label
+flaps()
View Compiled
*
*:after
*:before
box-sizing border-box
transform-style preserve-3d
body
background hsl(180, 20%, 92%)
min-height 100vh
display grid
place-items center
perspective 100vmin
overflow hidden
:root
--packaged 0
--steps 23
--delay 0.2
--speed 0.2
// Colors
--face-1 hsl(28, 41%, 57%)
--face-2 hsl(29, 58%, 66%)
--face-3 hsl(30, 69%, 70%)
--face-4 hsl(31, 82%, 74%)
--face-5 hsl(30, 72%, 70%)
--face-6 hsl(21, 75%, 28%)
--tape hsl(26, 37%, 51%)
.close
.open
position fixed
height 100vh
width 100vw
z-index 2
transform scale(1) translate3d(0, 0, 50vmin)
transition transform 0s calc(((var(--steps) + 2) * var(--delay)) * 1s)
.open
transform scale(0) translate3d(0, 0, 50vmin)
transition transform 0s 0s
#package:checked ~ .close
transition transform 0s 0s
transform scale(0) translate3d(0, 0, 50vmin)
#package:checked ~ .open
transition transform 0s calc(((var(--steps) + 2) * var(--delay)) * 1s)
transform scale(1) translate3d(0, 0, 50vmin)
input
position fixed
top 0
left 0
width 1px
height 1px
padding 0
margin -1px
overflow hidden
clip rect(0, 0, 0, 0)
white-space nowrap
border-width 0
[for='one']
[for='two']
[for='three']
[for='four']
position fixed
top var(--top)
right 1rem
z-index 3
[for='one']
--top 1rem
[for='two']
--top calc(1rem + 49px)
[for='three']
--top calc(1rem + 98px)
[for='four']
--top calc(1rem + 147px)
#one:checked ~ .one
#two:checked ~ .two
#three:checked ~ .three
#four:checked ~ .four
border-color hsl(10, 80%, 50%)
.size-label
font-family sans-serif
font-weight bold
color hsl(0, 0%, 15%)
height 44px
width 44px
display grid
place-items center
background hsl(0, 0%, 99%)
border-radius 50%
cursor pointer
border 4px solid hsl(180, 20%, 62%)
transform translate(0, calc(var(--y, 0) * 1%)) scale(var(--scale, 1))
transition transform 0.1s
&:hover
--y -5
&:active
--y 2
--scale 0.9
#one:checked ~ .scene .package__wrapper
--height 10
--width 20
--depth 20
#two:checked ~ .scene .package__wrapper
--height 20
--width 20
--depth 20
#three:checked ~ .scene .package__wrapper
--height 20
--width 30
--depth 20
#four:checked ~ .scene .package__wrapper
--height 30
--width 20
--depth 30
#package:checked ~ .scene
.package__side--main > .package__flap--top:before
--bg-step 9
#package:checked ~ .scene
--packaged 1
// Annoyingly we can't do a trick where we use the number of steps and reverse the order.
/**
* Handles all the steps of packaging up the box. Quite long winded.
* 1. Start with package rotated so that all sides are flat
* 2. Extra Side
* 3. Then Tabbed Side
* 4. Then Flipped Side and Tab
* 5. Then go through the bottom flaps in order
* 6. Tilt the box up.
* 7. Close the top.
*/
.package__side--extra
--step 0
.package__side--tabbed
--step 1
.package__side--tabbed:after
--step 2
.package__side--flipped
--step 2
// Bottom Flaps before the flip
.package__side--extra > .package__flap--bottom
--step 3
.package__side--tabbed > .package__flap--bottom
--step 4
.package__side--main > .package__flap--bottom
--step 5
.package__side--flipped > .package__flap--bottom
--step 6
// Tape
.package__tape--bottom
--step 7
// Move the package upright
.package__wrapper
--step 8
.package
.package__shadow
--step 9
// Load the content
.package__icon--html
--step 10
.package__icon--css
--step 11
.package__icon--js
--step 12
// Top Flaps Last after a little gap for the content
.package__side--extra > .package__flap--top
--step 16
.package__side--tabbed > .package__flap--top
--step 17
.package__side--main > .package__flap--top
--step 18
.package__side--flipped > .package__flap--top
--step 19
// Then tape the top
.package__tape--top
--step 20
.package__branding
.package__label
.package__branding--shadow
.package__label--shadow
--step 21
.package__label:after
--step 22
.package__label:before
--step 23
.scene
transform rotateX(-24deg) rotateY(-32deg) rotateX(90deg)
.package
.package__wrapper
.package__flap
.package__flap--top
.package__flap--bottom
.package__side
.package__side:after
.package__icon
.package__tape--top
.package__tape--bottom
.package__branding
.package__label
.package__label:after
.package__label:before
.package__shadow
.package__label--shadow
.package__branding--shadow
--delay 0.2
--speed 0.2
transition transform calc(var(--speed, 0.2) * 1s) calc((var(--step, 1) * var(--delay, 1)) * 1s), opacity 0.1s calc(((var(--step, 1) * var(--delay, 1)) + ((var(--speed) - 0.1) * (1 - var(--packaged)))) * 1s), height calc(var(--speed, 0.2) * 1s), width calc(var(--speed, 0.2) * 1s)
transition-timing-function ease-in-out
// Uncomment for instant scaling changes
// #one:focus ~ .scene
// #two:focus ~ .scene
// #three:focus ~ .scene
// #four:focus ~ .scene
// .package
// .package__wrapper
// .package__flap
// .package__flap--top
// .package__flap--bottom
// .package__side
// .package__side:after
// .package__icon
// .package__tape--top
// .package__tape--bottom
// .package__branding
// .package__label
// .package__label:after
// .package__label:before
// .package__shadow
// .package__label--shadow
// .package__branding--shadow
// transition none
// transition-timing-function ease-in-out
// Transition steps for closing
.package__side--extra
--step 23
.package__side--tabbed
--step 22
.package__side--tabbed:after
--step 21
.package__side--flipped
--step 20
// Bottom Flaps before the flip
.package__side--extra > .package__flap--bottom
--step 19
.package__side--tabbed > .package__flap--bottom
--step 18
.package__side--main > .package__flap--bottom
--step 17
.package__side--flipped > .package__flap--bottom
--step 16
// Tape
.package__tape--bottom
--step 15
// Move the package upright
.package__wrapper
--step 14
.package
.package__shadow
--step 13
// Load the content
.package__icon--html
--step 8
.package__icon--css
--step 7
.package__icon--js
--step 6
// Top Flaps Last after a little gap for the content
.package__side--extra > .package__flap--top
--step 5
.package__side--tabbed > .package__flap--top
--step 4
.package__side--main > .package__flap--top
--step 3
.package__side--flipped > .package__flap--top
--step 2
// Then tape the top
.package__tape--top
--step 1
.package__branding
.package__label
.package__label--shadow
.package__branding--shadow
--step 0
// Don't need to erase these. Just move the label.
.package__label:after
--step 5
.package__label:before
--step 5
.package
height calc(var(--depth) * 1vmin)
width calc(var(--width) * 1vmin)
// background hsla(280, 80%, 50%, 0.3)
transform-origin 50% 0
transform rotateX(calc((1 - var(--packaged, 0)) * 90deg))
&__shadow
background hsl(0, 0%, 35%)
opacity 0.75
position absolute
height 99%
width 99%
top 0
left 50%
transform-origin 50% 0
transform translate(-50%, 0) scaleY(var(--packaged))
&__tape
background var(--tape)
height min(4vmin, 50%)
width 94%
left 50%
position absolute
transform-origin 0 50%
transform translate3d(-50%, var(--offset-y), 2px) scaleX(var(--packaged, 0))
&--bottom
--offset-y 50%
bottom 100%
&--top
--offset-y -50%
top 100%
&__direction
display inline-flex
align-items center
font-family sans-serif
font-weight bold
font-size 1.75vmin
transform rotate(180deg) translate3d(0, 0, 1px)
position absolute
top 0
right 0
padding 5%
justify-content flex-end
color hsl(0, 0%, 10%)
backface-visibility hidden
-webkit-backface-visibility hidden
svg
fill currentColor
width 8%
min-width 2vmin
&__wrapper
// --height 20
// --width 30
// --depth 20
// background hsla(210, 80%, 50%, 0.3)
transform translate3d(0, calc(((1 - var(--packaged, 0)) * var(--height)) * 1vmin), calc(var(--height) * -0.5vmin))
&__label
height 20%
width 30%
background hsl(0, 0%, 98%)
position absolute
right 10%
bottom 20%
border-radius 5%
opacity var(--packaged)
-webkit-backface-visibility hidden
backface-visibility hidden
transform rotate(180deg) translate3d(0, 0, calc((1 - (var(--packaged, 0))) * 5vmin))
&--shadow
transform rotate(180deg) translate3d(0, 0, 0) scale(var(--packaged))
background hsl(0, 0%, 10%)
&:after
&:before
content ''
position absolute
height 20%
width var(--line-length, 70%)
top var(--line, 20%)
left 10%
background hsl(0, 0%, 10%)
transform-origin 0 50%
transform scaleX(var(--packaged, 0))
&:before
--line 50%
--line-length 40%
&__branding
height 30%
position absolute
bottom 10%
left 10%
transform rotate(-160deg) translate3d(0, 0, calc((1 - (var(--packaged, 0))) * 5vmin))
opacity var(--packaged)
-webkit-backface-visibility hidden
backface-visibility hidden
&--shadow
transform rotate(-160deg) translate3d(0, 0, 0) scale(var(--packaged))
filter brightness(0)
opacity var(--packaged)
&__icon
--speed 1
position absolute
top 50%
left 50%
width 40%
transform translate(-50%, -50%) translate3d(calc(var(--x, 0) * 1%), calc((((1 - var(--packaged,0)) * (var(--y, 0) * (max(var(--height), var(--depth), var(--width)))))) * -1vmin), calc(var(--z, 0) * 1vmin))
opacity var(--packaged)
&--js
--x 60
--y 1.4
--z 0
fill #F7DF1E
&--html
--x 0
--y 1.6
--z -3
fill #E34F26
&--css
--x -50
--y 1.2
--z 3
fill #1572B6
&__content
width calc(min(var(--height), var(--width)) * 1vmin)
height calc(var(--height) * 1vmin)
// background hsla(280, 80%, 50%, 0.5)
position absolute
left 50%
bottom 50%
transform-origin 50% 100%
transform translate(-50%, 0) rotateX(-90deg) rotateY(45deg)
&__flap
width 99.5%
height 49.5%
background var(--face-4)
position absolute
left 50%
&--bottom
transform-origin 50% 100%
bottom 100%
transform translate(-50%, 0) rotateX(calc(var(--packaged, 0) * 90deg))
&--top
top 100%
transform-origin 50% 0%
transform translate(-50%, 0) rotateX(calc(var(--packaged, 0) * -90deg))
&__side
background 'hsla(%s, 30%, 30%, 0.3)' % var(--hue, 0)
height calc(var(--height) * 1vmin)
position absolute
top 50%
&--main > .package__flap--top:before
--bg-step 13
content ''
height 100%
width 100%
position absolute
transform rotateY(180deg)
backface-visibility hidden
-webkit-backface-visibility hidden
background var(--face-2)
opacity var(--packaged)
transition opacity calc(var(--speed, 0.2) * 1s) calc((var(--bg-step, 1) * var(--delay, 1)) * 1s)
transition-timing-function ease-in-out
&--extra
&--tabbed
& > .package__flap--top
top 99%
& > .package__flap--bottom
bottom 99%
&--extra > .package__flap.package__flap--top
background hsl(32, 76%, 70%)
&--extra > .package__flap.package__flap--bottom
background hsl(32, 76%, 74%)
&--tabbed > .package__flap.package__flap--bottom
background hsl(32, 72%, 72%)
&--flipped > .package__flap.package__flap--bottom
background hsl(32, 78%, 76%)
&--main > .package__flap.package__flap--top
background hsl(32, 78%, 72%)
&--main
--hue 2
background var(--face-5)
left 50%
transform translate(-50%, -50%) rotateX(90deg) rotateY(0deg) translate3d(0, 0, calc(var(--depth) * 0.5vmin)) translate(0, 50%)
width calc(var(--width) * 1vmin)
& > .package__flap
height calc(var(--depth) * 0.495vmin)
&--tabbed
--hue 90
top 0
left 100%
background var(--face-2)
width calc(var(--depth) * 1vmin)
transform-origin 0% 50%
transform rotateY(calc(var(--packaged, 0) * 90deg))
& > .package__flap
height calc(var(--width) * 0.495vmin)
background var(--face-3)
&:after
content ''
position absolute
left 99.5%
top 0
height 100%
width 10%
background var(--face-3)
$clip = polygon(0 0%, 100% 20%, 100% 80%, 0 100%)
clip-path $clip
-webkit-clip-path $clip
transform-origin 0% 50%
transform rotateY(calc(var(--packaged, 0) * 91deg))
&--extra
--hue 120
right 100%
top 0
background var(--face-2)
width calc(var(--depth) * 1vmin)
transform-origin 100% 50%
transform rotateY(calc(var(--packaged, 0) * -90deg))
& > .package__flap
height calc(var(--width) * 0.495vmin)
background var(--face-3)
&--flipped
--hue 320
background var(--face-3)
top 0
right 100%
width calc(var(--width) * 1vmin)
transform-origin 100% 50%
transform rotateY(calc(var(--packaged, 0) * -90deg))
& > .package__flap
height calc(var(--depth) * 0.495vmin)
background var(--face-4)
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.