- const ARR = ['one', 'two', 'three', 'four', 'five', 'six']

mixin cube(className, id)
  label.cube(class=className for=id)
    div
    div
      block
    div
    div
    div
    div

for $input in ARR
  input(type='checkbox' id=$input)
for $label in ARR
  label.label-mask(for=$label)

.spinner.spinner--left
.spinner.spinner--right

.scene
  .plane
    +cube('plate')
    .cake
      for $slice in ARR
        if ($slice !== 'six')
          +cube('cake-slice', $slice)
            if $slice === 'four'
              span.css-label CSS is awesome
        else
          label.cube(class='cake-slice' for='six')
            div
            div
            div
              img.cake-bear(src='https://assets.codepen.io/605876/avatar.png')
            div
            div
            div
      for $shadow in ARR
        span.cake-slice__shadow

.backdrop
View Compiled
*
  box-sizing border-box

$starting-hue = 190

:root
  --plate-depth 1
  --marzipan hsl(50, 85%, 69%)
  --marzipan-dark hsl(50, 85%, 50%)
  --marzipan-light hsl(50, 85%, 78%)
  --jammies hsl(7, 87%, 75%)
  --jammies-dark hsl(7, 70%, 55%)
  --cake hsl(43, 91%, 80%)
  --cake-hover-y 2vmin
  --cake-hover-z 3vmin
  --cake-hover-rotate -10deg
  --cake-active-y 3vmin
  --cake-active-z 4vmin
  --cake-active-rotate -10deg
  --shadow-hover-translate -5%
  --shadow-hover-opacity 0.15
  --shadow-active-translate -8%
  --shadow-active-opacity 0.05
  --bg-hue $starting-hue

body
  min-height 100vh
  padding 0
  margin 0

.scene
  display flex
  align-items center
  justify-content center
  perspective 800px
  transform-style preserve-3d
  margin 0
  padding 0
  height 100vh
  width 100vw


// Used as a 3D set for the cake plate
.plane
  height 30vmin
  width 40vmin
  transform rotateX(-24deg) rotateY(-24deg) rotateX(90deg) rotate(0deg)
  transform-style preserve-3d


[type='checkbox']
  opacity 0
  position fixed
  left 100%

// Cube variables are scoped in here
.cube
  position absolute
  height calc(var(--height) * 1vmin)
  width calc(var(--width) * 1vmin)
  transform-style preserve-3d

  // Dupe base
  & > div:nth-of-type(1)
    height 100%
    width 100%
    transform translate3d(0, 0, var(--offset, 0))

  // Right face
  & > div:nth-of-type(2)
    position absolute
    top 0
    left calc(var(--width) * 1vmin)
    height 100%
    width calc(var(--depth) * 1vmin)
    transform rotateY(-90deg) translate(var(--offset, 0), 0)
    transform-origin 0 50%

  // Left face
  & > div:nth-of-type(3)
    position absolute
    top 0
    left 0
    height 100%
    width calc(var(--depth) * 1vmin)
    transform rotateY(-90deg) translate(var(--offset, 0), 0)
    transform-origin 0 50%

  // Back face
  & > div:nth-of-type(4)
    position absolute
    top 0
    left 0
    height calc(var(--depth) * 1vmin)
    width 100%
    transform-origin 50% 0
    transform rotateX(90deg) translate3d(0, var(--offset, 0), 0)

  // Front face
  & > div:nth-of-type(5)
    position absolute
    top 100%
    left 0
    width 100%
    height calc(var(--depth) * 1vmin)
    transform-origin 50% 0
    transform rotateX(90deg) translate3d(0, var(--offset, 0), 0)

  // The lid
  & > div:nth-of-type(6)
    height 100%
    width 100%
    position absolute
    top 0
    left 0
    transform translateZ(calc(var(--depth) * 1vmin)) translate3d(0, 0, var(--offset, 0))

.plate
  --height 25
  --width 35
  --depth 1
  top 50%
  left 50%
  transform translate(-50%, -50%)

  & > div:nth-of-type(2)
  & > div:nth-of-type(3)
  & > div:nth-of-type(4)
    background hsl(0, 0%, 80%)
  & > div:nth-of-type(5)
    background hsl(0, 0%, 90%)
  & > div:nth-of-type(6)
    background hsl(0, 0%, 95%)

  &:before
    content ''
    position absolute
    left 100%
    height 5vmin
    width 1vmin
    top 72%
    transition transform 0.25s, opacity 0.25s
    background hsl(0, 0%, 10%)
    opacity 0
    transform rotateY(-90deg) skewY(-20deg)
    transform-origin 0 100%

  &:after
    content ''
    position absolute
    left 100%
    height 20vmin
    width 11.5vmin
    transition transform 0.25s, opacity 0.25s
    background hsl(0, 0%, 10%)
    opacity 0
    top 52%
    transform-origin 0 50%
    transform translate3d(0%, -50%, -0.2vmin) scaleX(0)

.cake
  height 20vmin
  width 30vmin
  position absolute
  top 50%
  left 50%
  transform-style preserve-3d
  transform translate(-50%, -50%) translateZ(calc(var(--plate-depth) * 1vmin))

.cake-slice
  --depth 15
  --height 20
  --width 5
  --offset calc((var(--depth) / 2) * -1vmin)
  position absolute
  top 0
  transition transform 0.25s
  transform-origin 50% 100%
  z-index 2
  transform translate3d(0, 0, calc((var(--depth) / 2) * 1vmin))

  &:hover
    transform translate3d(0, 0, calc((var(--depth) / 2) * 1vmin)) translate3d(0, var(--cake-hover-y), var(--cake-hover-z)) rotateX(var(--cake-hover-rotate))

  & > div:nth-of-type(1)
    background var(--marzipan-light)
  & > div:nth-of-type(2)
    background var(--marzipan-dark)
  & > div:nth-of-type(3)
    background var(--marzipan)
  & > div:nth-of-type(4)
    background var(--marzipan-light)
  & > div:nth-of-type(5)
    background var(--marzipan-light)
  & > div:nth-of-type(6)
    background var(--marzipan)

  for $slice in 1..6
    &:nth-of-type({$slice})
      left 'calc((var(--width) * %s) * 1vmin)' % ($slice - 1)

      &:hover ~ span:nth-of-type({$slice})
        transform translateZ(0.00001vmin) translate(0, var(--shadow-hover-translate))
        opacity var(--shadow-hover-opacity)

.cake-slice:nth-of-type(1)
.cake-slice:nth-of-type(2)
.cake-slice:nth-of-type(3)
.cake-slice:nth-of-type(4)
.cake-slice:nth-of-type(5)
  & > div:nth-of-type(2)
    background linear-gradient(var(--jammies), var(--jammies)) 10% 10% / 43% 43% no-repeat,
      linear-gradient(var(--cake), var(--cake)) 90% 10% / 43% 43% no-repeat,
      linear-gradient(var(--jammies), var(--jammies)) 90% 90% / 43% 43% no-repeat,
      linear-gradient(var(--cake), var(--cake)) 10% 90% / 43% 43% no-repeat,
      linear-gradient(var(--jammies-dark), var(--jammies-dark)) center center / 92% 92% no-repeat, var(--marzipan-light)

.cake-slice:nth-of-type(6)
  & > div:nth-of-type(3)
    background linear-gradient(var(--jammies), var(--jammies)) 10% 10% / 43% 43% no-repeat,
      linear-gradient(var(--cake), var(--cake)) 90% 10% / 43% 43% no-repeat,
      linear-gradient(var(--jammies), var(--jammies)) 90% 90% / 43% 43% no-repeat,
      linear-gradient(var(--cake), var(--cake)) 10% 90% / 43% 43% no-repeat,
      linear-gradient(var(--jammies-dark), var(--jammies-dark)) center center / 92% 92% no-repeat, var(--marzipan-light)

.css-label
  display block
  transform rotate(90deg) rotateY(180deg) translate(-25%, 15%)
  position absolute
  top 0
  left 0
  mix-blend-mode overlay
  font-family sans-serif
  font-weight bold
  font-size 4vmin

.backdrop
  height 200vh
  width 200vw
  position fixed
  top 0
  left 0
  right 0
  bottom 0
  background 'hsl(%s, 20%, 40%)' % var(--bg-hue)
  transform translateZ(-30vmin)
  z-index -1

.cake-slice__shadow
  --width 5
  --alpha 1
  display block
  position absolute
  height 100%
  width calc(var(--width) * 1vmin)
  background hsl(0, 0%, 10%)
  transition transform 0.25s, opacity 0.25s
  top 0
  transform translateZ(0.00001vmin)

  for $shadow in 1..6
    &:nth-of-type({$shadow})
      left 'calc((var(--width) * %s) * 1vmin)' % ($shadow - 1)

[type='checkbox']
  for $checked in 1..6
    &:nth-of-type({$checked}):checked
      ~ label:nth-of-type({$checked})
        height 100vh
        width 100vw
        position fixed
        z-index 11
        opacity 0.3
        transform translateZ(30vmin)

      ~ .scene .plane .cake .cake-slice:nth-of-type({$checked})
        transform translate3d(0, 0, calc((var(--depth) / 2) * 1vmin)) translate3d(0, var(--cake-active-y), var(--cake-active-z)) rotateX(var(--cake-active-rotate))

      ~ .scene .plane .cake .cake-slice__shadow:nth-of-type({$checked})
        transform translateZ(0.00001vmin) translate(0, var(--shadow-active-translate))
        opacity var(--shadow-active-opacity)

    &:nth-of-type(1):checked ~ .backdrop
      animation party-drop 1s infinite linear

    &:nth-of-type(2):checked ~ .scene .plane .cake .cake-slice:nth-of-type(2)
      animation cake-flip 1s infinite linear
    &:nth-of-type(2):checked ~ .scene .plane .cake .cake-slice__shadow:nth-of-type(2)
      animation shadow-flip 1s infinite linear

    &:nth-of-type(3):checked ~ .scene .plane .cake .cake-slice:nth-of-type(1)
      animation cake-wave 1s 0.1s infinite both
    &:nth-of-type(3):checked ~ .scene .plane .cake .cake-slice:nth-of-type(2)
      animation cake-wave 1s 0.2s infinite both
    &:nth-of-type(3):checked ~ .scene .plane .cake .cake-slice:nth-of-type(3)
      transform translate3d(0, 0, calc((var(--depth) / 2) * 1vmin)) translate3d(0, 0, 0) rotateX(0)
      animation cake-wave 1s 0.3s infinite both
    &:nth-of-type(3):checked ~ .scene .plane .cake .cake-slice:nth-of-type(4)
      animation cake-wave 1s 0.4s infinite both
    &:nth-of-type(3):checked ~ .scene .plane .cake .cake-slice:nth-of-type(5)
      animation cake-wave 1s 0.5s infinite both
    &:nth-of-type(3):checked ~ .scene .plane .cake .cake-slice:nth-of-type(6)
      animation cake-wave 1s 0.6s infinite both
    &:nth-of-type(3):checked ~ .scene .plane .cake .cake-slice__shadow:nth-of-type(1)
      animation shadow-wave 1s 0.1s infinite both
    &:nth-of-type(3):checked ~ .scene .plane .cake .cake-slice__shadow:nth-of-type(2)
      animation shadow-wave 1s 0.2s infinite both
    &:nth-of-type(3):checked ~ .scene .plane .cake .cake-slice__shadow:nth-of-type(3)
      opacity 1
      animation shadow-wave 1s 0.3s infinite both
    &:nth-of-type(3):checked ~ .scene .plane .cake .cake-slice__shadow:nth-of-type(4)
      animation shadow-wave 1s 0.4s infinite both
    &:nth-of-type(3):checked ~ .scene .plane .cake .cake-slice__shadow:nth-of-type(5)
      animation shadow-wave 1s 0.5s infinite both
    &:nth-of-type(3):checked ~ .scene .plane .cake .cake-slice__shadow:nth-of-type(6)
      animation shadow-wave 1s 0.6s infinite both

    &:nth-of-type(4):checked ~ .scene .plane .cake .cake-slice:nth-of-type(4)
      transform-origin 50% 50%
      transform translate3d(0, 0, calc((var(--depth) / 2) * 1vmin)) translate3d(0, var(--cake-active-y), var(--cake-active-z)) rotateX(var(--cake-active-rotate)) translate3d(0, 0, 20vmin) rotate(90deg)
      // animation show-off 0.5s both
    &:nth-of-type(4):checked ~ .scene .plane .cake .cake-slice__shadow:nth-of-type(4)
      opacity 0

    &:nth-of-type(5):checked ~ .scene .plane .cake .cake-slice:nth-of-type(5)
      transform-origin 50% 50%
      animation blast-off 2s
    &:nth-of-type(5):checked ~ .scene .plane .cake .cake-slice__shadow:nth-of-type(5)
      animation blast-shadow 2s

    &:nth-of-type(6):checked ~ .scene .plane .cake .cake-slice:nth-of-type(6)
      transform translate3d(0, 0, calc((var(--depth) / 2) * 1vmin)) translate3d(0, 0, 0) rotateX(0) translate3d(0, 0, 0) scale(1) rotate(0deg) translate3d(calc((var(--width)) * 2vmin), 0, calc(var(--width) * -1vmin)) rotateY(100deg)
    &:nth-of-type(6):checked ~ .scene .plane .cake .cake-slice__shadow:nth-of-type(6)
      opacity 0.8
      transform translateZ(0.00001vmin) translate(100%, 0)
    &:nth-of-type(6):checked ~ .scene .plane .plate:before
      opacity 0.8
    &:nth-of-type(6):checked ~ .scene .plane .plate:after
      opacity 0.8
      transform translate3d(0%, -50%, -0.2vmin) scaleX(1)

.spinner
  height 100vh
  width 15vw
  position fixed
  top 0
  z-index 10

  &:hover
    ~ .scene .plane
      animation-name cake-spin
      animation-duration 1s
      animation-iteration-count infinite
      animation-timing-function linear

  &--left
    left 0


  &--right
    right 0

    &:hover ~ .scene .plane
      animation-direction reverse



@keyframes party-drop
  for $frame in (0..100)
    {$frame * 1%}
      background 'hsl(%s, 20%, 40%)' % (($frame * 3.6) + $starting-hue)

@keyframes cake-flip
  0%
    transform-origin 50% 50%
    transform translate3d(0, 0, calc((var(--depth) / 2) * 1vmin)) translate3d(0, var(--cake-active-y), var(--cake-active-z)) rotateX(var(--cake-active-rotate)) translate3d(0, 0, 0) scale(1) rotate(0deg)
  25%
    transform-origin 50% 50%
    transform translate3d(0, 0, calc((var(--depth) / 2) * 1vmin)) translate3d(0, var(--cake-active-y), var(--cake-active-z)) rotateX(var(--cake-active-rotate)) translate3d(0, 0, -1vmin) scale(0.95) rotate(0deg)
  50%
    transform-origin 50% 50%
    transform translate3d(0, 0, calc((var(--depth) / 2) * 1vmin)) translate3d(0, var(--cake-active-y), var(--cake-active-z)) rotateX(var(--cake-active-rotate)) translate3d(0, 0, 20vmin) scale(1.2)
  75%
    transform-origin 50% 50%
    transform translate3d(0, 0, calc((var(--depth) / 2) * 1vmin)) translate3d(0, var(--cake-active-y), var(--cake-active-z)) rotateX(var(--cake-active-rotate)) translate3d(0, 0, 20vmin) scale(1.1) rotateX(-360deg)
  100%
    transform-origin 50% 50%
    transform translate3d(0, 0, calc((var(--depth) / 2) * 1vmin)) translate3d(0, var(--cake-active-y), var(--cake-active-z)) rotateX(var(--cake-active-rotate)) translate3d(0, 0, 0) scale(1) rotate(-360deg)

@keyframes shadow-flip
  25%
    opacity 1
  75%
    opacity 0

@keyframes cake-spin
  to
    transform rotateX(-24deg) rotateY(-24deg) rotateX(90deg) rotate(360deg)

@keyframes show-off
  50%
    transform translate3d(0, 0, calc((var(--depth) / 2) * 1vmin)) translate3d(0, var(--cake-active-y), var(--cake-active-z)) rotateX(var(--cake-active-rotate)) translate3d(0, 0, 15vmin) rotate(0deg)
  100%
    transform translate3d(0, 0, calc((var(--depth) / 2) * 1vmin)) translate3d(0, var(--cake-active-y), var(--cake-active-z)) rotateX(var(--cake-active-rotate)) translate3d(0, 0, 15vmin) rotate(90deg)

@keyframes blast-off
  0%, 5%, 10%, 15%, 20%, 25%
    transform translate3d(0, 0, calc((var(--depth) / 2) * 1vmin)) translate3d(0, var(--cake-active-y), var(--cake-active-z)) rotateX(var(--cake-active-rotate)) rotateX(2deg) translate3d(0, 0, 0) scale(1)
  2.5%, 7.5%, 12.5%, 17.5%, 22.5%
    transform translate3d(0, 0, calc((var(--depth) / 2) * 1vmin)) translate3d(0, var(--cake-active-y), var(--cake-active-z)) rotateX(var(--cake-active-rotate)) rotateX(-2deg) translate3d(0, 0, 0) scale(1)
  80%
    transform translate3d(0, 0, calc((var(--depth) / 2) * 1vmin)) translate3d(0, var(--cake-active-y), var(--cake-active-z)) rotateX(var(--cake-active-rotate)) rotateX(0deg) translate3d(0, 0, 100vmin) scale(1)
  80.1%
    transform translate3d(0, 0, calc((var(--depth) / 2) * 1vmin)) translate3d(0, var(--cake-active-y), var(--cake-active-z)) rotateX(var(--cake-active-rotate)) rotateX(0deg) translate3d(0, 0, 100vmin) scale(0)
  80.2%
    transform translate3d(0, 0, calc((var(--depth) / 2) * 1vmin)) translate3d(0, var(--cake-active-y), var(--cake-active-z)) rotateX(var(--cake-active-rotate)) rotateX(0deg) translate3d(0, 0, 0) scale(0)
  100%
    transform translate3d(0, 0, calc((var(--depth) / 2) * 1vmin)) translate3d(0, var(--cake-active-y), var(--cake-active-z)) rotateX(var(--cake-active-rotate)) rotateX(0deg) translate3d(0, 0, 0) scale(1)

@keyframes blast-shadow
  80%
    opacity 0

@keyframes cake-wave
  0, 100%
    transform translate3d(0, 0, calc((var(--depth) / 2) * 1vmin)) translate3d(0, 0, 0) rotateX(0) translate3d(0, 0, 0)
  50%
    transform translate3d(0, 0, calc((var(--depth) / 2) * 1vmin)) translate3d(0, 0, 0) rotateX(0) translate3d(0, 0, 3vmin)
@keyframes shadow-wave
  50%
    transform translateZ(0.00001vmin) translate(0, var(--shadow-active-translate))
    opacity var(--shadow-active-opacity)


.cake-bear
  mix-blend-mode overlay
  position absolute
  width 100%
  transform rotate(90deg) translate(15%, 0)
View Compiled
// 404
// Do something different with CSS
View Compiled
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.