mixin cuboid()
.cuboid(class!=attributes.class)
if block
block
- let s = 0
while s < 6
.cuboid__side
- s++
.rotater(data-multiplier="-2" style=`--index: 0;`)
.rotater(data-multiplier="-1" style=`--index: 1;`)
.rotater(data-multiplier="0" style=`--index: 2;`)
.rotater(data-multiplier="1" style=`--index: 3;`)
.rotater(data-multiplier="2" style=`--index: 4;`)
.scene
form.stopwatch
input#start(type='checkbox')
input#pause(type='checkbox')
.stopwatch__chords
.stopwatch__chord
+cuboid()
.stopwatch__chord
+cuboid()
.stopwatch__back
.stopwatch__content
img.stopwatch__logo(src="https://assets.codepen.io/605876/Bear+%E2%80%93+2021+.png" alt="new bear logo")
.stopwatch__face
.digit.m.m--tens 0
.digit.m.m--singles 0
span :
.digit.second.s.s--tens 0
.digit.second.s.s--singles 0
span .
.digit.digit--small.ms.ms--tens 0
.digit.digit--small.ms.ms--singles 0
.stopwatch__glass
.cuboid.stopwatch__body
.cuboid__side
.stopwatch__body-angle
+cuboid.stopwatch__frame
button.stopwatch__control.stopwatch__reset(type='reset')
.button__placeholder
+cuboid.button__container
+cuboid.button
.stopwatch__body-angle
+cuboid.stopwatch__frame
.stopwatch__body-angle
+cuboid.stopwatch__frame
label.stopwatch__control.stopwatch__pause(for="pause")
.button__placeholder
+cuboid.button__container
+cuboid.button
label.stopwatch__control.stopwatch__start(for="start")
.button__placeholder
+cuboid.button__container
+cuboid.button
.cuboid__side
.stopwatch__body-angle
+cuboid.stopwatch__frame
.stopwatch__body-angle
+cuboid.stopwatch__frame
.stopwatch__body-angle
+cuboid.stopwatch__frame
.cuboid__side
.stopwatch__body-angle
+cuboid.stopwatch__frame
.stopwatch__body-angle
+cuboid.stopwatch__frame
.stopwatch__body-angle
+cuboid.stopwatch__frame
.cuboid__side
.stopwatch__body-angle
+cuboid.stopwatch__frame
.stopwatch__body-angle
+cuboid.stopwatch__frame
.stopwatch__body-angle
+cuboid.stopwatch__frame
.cuboid__side
.cuboid__side
View Compiled
@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@500&display=swap')
.cuboid
width 100%
height 100%
position relative
// 1 is the top and go t, r, b, l, f, b
&__side
filter brightness(var(--b, 1))
position absolute
&__side:nth-of-type(1)
--b 1.1
height calc(var(--depth, 20) * 1vmin)
width 100%
top 0
transform translate(0, -50%) rotateX(90deg)
&__side:nth-of-type(2)
--b 0.9
height 100%
width calc(var(--depth, 20) * 1vmin)
top 50%
right 0
transform translate(50%, -50%) rotateY(90deg)
&__side:nth-of-type(3)
--b 0.5
width 100%
height calc(var(--depth, 20) * 1vmin)
bottom 0
transform translate(0%, 50%) rotateX(90deg)
&__side:nth-of-type(4)
--b 1
height 100%
width calc(var(--depth, 20) * 1vmin)
left 0
top 50%
transform translate(-50%, -50%) rotateY(90deg)
&__side:nth-of-type(5)
--b 0.8
height 100%
width 100%
transform translate3d(0, 0, calc(var(--depth, 20) * 0.5vmin))
top 0
left 0
&__side:nth-of-type(6)
--b 1.2
height 100%
width 100%
transform translate3d(0, 0, calc(var(--depth, 20) * -0.5vmin)) rotateY(180deg)
top 0
left 0
:root
--stopwatch-size 40
--stopwatch-depth 10
--stopwatch-frame-depth 4
--body-clip polygon(25% 0, 75% 0, 100% 25%, 100% 75%, 75% 100%, 25% 100%, 0 75%, 0 25%)
--state paused
--bg hsl(280, 50%, 90%)
--digit hsl(90, 50%, 90%)
--face hsl(90, 50%, 5%)
--content hsl(0, 0%, 40%)
--glare hsla(0, 0%, 100%, 0.2)
--stopwatch-frame hsl(210, 20%, 50%)
--glass hsla(210, 100%, 90%, 0.15)
--chord-one hsl(0, 10%, 50%)
--chord-two hsl(0, 10%, 30%)
--start hsl(90, 90%, 50%)
--reset hsl(10, 90%, 50%)
*
*:after
*:before
box-sizing border-box
transform-style preserve-3d
// Trick to stop/start the stopwatch
// If neither are checked the animation-name is "none"
// And that resets the counters to their initial value
#start:checked ~ .stopwatch__content
#pause:checked ~ .stopwatch__content
.ms--tens
--name ms-tens
.ms--singles
--name ms-singles
.s--tens
--name s-tens
.s--singles
--name s-singles
.m--tens
--name m-tens
.m--singles
--name m-singles
// What handles the playback. When "Start" is checked,
// the play state is running. Then we can use "Pause" to
// toggle the play start of the animations.
#start:checked ~ .stopwatch__content
--state running
#pause:checked ~ .stopwatch__content
--state paused
// Trick to hide the start button
#start:checked
& ~ .stopwatch__body .stopwatch__start
z-index -1
display none
& ~ .stopwatch__body .stopwatch__pause
display block
.stopwatch__start:active ~ .stopwatch__stop-start
.stopwatch__pause:active ~ .stopwatch__stop-start
--y 25
.stopwatch__reset:active ~ .stopwatch__restart
--y 15
// The properties for animating each digit
// We should be able to declare these all as a chain
// But the syntax listed at: https://web.dev/at-property/#multiple-declarations
// doesn't work for me.
@property --ms-tens
initial-value 0
inherits false
syntax '<integer>'
@property --ms-singles
initial-value 0
inherits false
syntax '<integer>'
@property --s-tens
initial-value 0
inherits false
syntax '<integer>'
@property --s-singles
initial-value 0
inherits false
syntax '<integer>'
@property --m-tens
initial-value 0
inherits false
syntax '<integer>'
@property --m-singles
initial-value 0
inherits false
syntax '<integer>'
body
min-height 100vh
display grid
place-items center
background var(--bg)
overflow hidden
font-family 'Orbitron', sans-serif
[type='checkbox']
position fixed
width 1px
height 1px
padding 0
margin -1px
overflow hidden
clip rect(0, 0, 0, 0)
white-space nowrap
border-width 0
.scene
--rotate-y 0
--rotate-x 0
transform translate(-50%, -50%)
position fixed
top 50%
left 50%
transition transform 0.1s
transform translate3d(-50%, -50%, 100vmin) rotateX(-24deg) rotateY(-24deg) rotateX(calc(var(--rotate-x, 0) * 1deg)) rotateY(calc(var(--rotate-y, 0) * 1deg))
.stopwatch
--depth var(--stopwatch-depth)
height calc(var(--stopwatch-size, 50) * 1vmin)
margin 0
width calc(var(--stopwatch-size, 50) * 1vmin)
&__chords
height 100vmax
width 26%
position absolute
top 100%
left 50%
transform translate(-50%, 0)
&__chord
height 100%
width 10%
position absolute
top 0
.cuboid
--depth 1
.cuboid__side
background repeating-linear-gradient(calc(var(--deg, 45) * 1deg), var(--chord-one) 0 1%, var(--chord-two) 1% 2%)
&:nth-of-type(even)
--deg -45
--b 0.5
&:nth-of-type(1)
left 0
&:nth-of-type(2)
right 0
&__logo
height 20%
position absolute
top 80%
left 50%
transform translate(-50%, -50%)
filter saturate(0)
opacity 0.5
&__glass
background var(--glass)
height 100%
width 100%
clip-path var(--body-clip)
-webkit-clip-path var(--body-clip)
position absolute
transform translate3d(0, 0, calc(var(--stopwatch-depth) * 0.3vmin)) scale(0.85)
&:after
content ''
position absolute
height 300%
width 300%
transition transform 0.1s
background linear-gradient(transparent 0 35%, var(--glare) 36% 42%, transparent 43% 45%, var(--glare) 46% 48%, transparent 49%)
transform translate(-50%, -50%) translateX(calc(var(--shift, 0) * 1%)) rotate(-60deg)
top 50%
left 50%
&__content
background var(--content)
height 100%
width 100%
clip-path var(--body-clip)
-webkit-clip-path var(--body-clip)
position absolute
transform scale(0.85)
&__face
color var(--digit, white)
display flex
font-size 6vmin
position absolute
top 50%
left 50%
transform translate(-50%, -50%)
padding 1.75vmin
border-radius 1vmin
background var(--face, black)
.stopwatch__body > .cuboid__side
&:nth-of-type(5)
&:nth-of-type(6)
display none
&__back
height 100%
width 100%
background var(--stopwatch-frame)
position absolute
transform translate3d(0, 0, calc(var(--stopwatch-depth) * -0.5vmin)) scale(1)
-webkit-clip-path var(--body-clip)
clip-path var(--body-clip)
.rotater
z-index -1
position fixed
height 100vh
width 20vw
left calc(var(--index) * 20%)
[data-multiplier="-2"]:hover ~ .scene
--shift 20
--rotate-y calc(-2 * var(--scene-rotation, 10))
[data-multiplier="-1"]:hover ~ .scene
--shift 10
--rotate-y calc(-1 * var(--scene-rotation, 10))
[data-multiplier="0"]:hover ~ .scene
--shift 0
--rotate-y calc(0 * var(--scene-rotation, 10))
[data-multiplier="1"]:hover ~ .scene
--shift -10
--rotate-y calc(1 * var(--scene-rotation, 10))
[data-multiplier="2"]:hover ~ .scene
--shift -20
--rotate-y calc(2 * var(--scene-rotation, 10))
// Theming
.stopwatch__body .cuboid__side
// Need to override "filter" in some places as it applies overflow hidden
filter none
display flex
flex-direction var(--flow, column)
&:nth-of-type(odd)
--flow row
// Front faces
&:nth-of-type(even) .stopwatch__frame .cuboid__side:nth-of-type(4)
&:nth-of-type(odd) .stopwatch__frame .cuboid__side:nth-of-type(3)
--b 0.55
// Rear faces for back panel
&:nth-of-type(even) .stopwatch__frame .cuboid__side:nth-of-type(2)
&:nth-of-type(odd) .stopwatch__frame .cuboid__side:nth-of-type(1)
--b 1
// Internal pieces that aren't seen
&:nth-of-type(even) .stopwatch__frame .cuboid__side:nth-of-type(1)
&:nth-of-type(even) .stopwatch__frame .cuboid__side:nth-of-type(3)
&:nth-of-type(odd) .stopwatch__frame .cuboid__side:nth-of-type(2)
&:nth-of-type(odd) .stopwatch__frame .cuboid__side:nth-of-type(4)
--b 0.5
// Drill down into the individual outer and inner faces
// Outer Faces
// Top face
.stopwatch__body .cuboid__side:nth-of-type(1) .stopwatch__body-angle:nth-of-type(2) .stopwatch__frame .cuboid__side:nth-of-type(5)
--b 1.2
// Top left
.stopwatch__body .cuboid__side:nth-of-type(1) .stopwatch__body-angle:nth-of-type(1) .stopwatch__frame .cuboid__side:nth-of-type(5)
.stopwatch__body .cuboid__side:nth-of-type(4) .stopwatch__body-angle:nth-of-type(1) .stopwatch__frame .cuboid__side:nth-of-type(6)
--b 1.1
// Left
.stopwatch__body .cuboid__side:nth-of-type(4) .stopwatch__body-angle:nth-of-type(2) .stopwatch__frame .cuboid__side:nth-of-type(6)
--b 1
//Bottom left
.stopwatch__body .cuboid__side:nth-of-type(3) .stopwatch__body-angle:nth-of-type(1) .stopwatch__frame .cuboid__side:nth-of-type(6)
.stopwatch__body .cuboid__side:nth-of-type(4) .stopwatch__body-angle:nth-of-type(3) .stopwatch__frame .cuboid__side:nth-of-type(6)
--b 0.9
//Bottom
.stopwatch__body .cuboid__side:nth-of-type(3) .stopwatch__body-angle:nth-of-type(2) .stopwatch__frame .cuboid__side:nth-of-type(6)
--b 0.8
//Bottom right
.stopwatch__body .cuboid__side:nth-of-type(3) .stopwatch__body-angle:nth-of-type(3) .stopwatch__frame .cuboid__side:nth-of-type(6)
.stopwatch__body .cuboid__side:nth-of-type(2) .stopwatch__body-angle:nth-of-type(3) .stopwatch__frame .cuboid__side:nth-of-type(5)
--b 0.7
//Right
.stopwatch__body .cuboid__side:nth-of-type(2) .stopwatch__body-angle:nth-of-type(2) .stopwatch__frame .cuboid__side:nth-of-type(5)
--b 0.7
//Top right
.stopwatch__body .cuboid__side:nth-of-type(1) .stopwatch__body-angle:nth-of-type(3) .stopwatch__frame .cuboid__side:nth-of-type(5)
.stopwatch__body .cuboid__side:nth-of-type(2) .stopwatch__body-angle:nth-of-type(1) .stopwatch__frame .cuboid__side:nth-of-type(5)
--b 1
// Internal Faces
// Top face
.stopwatch__body .cuboid__side:nth-of-type(1) .stopwatch__body-angle:nth-of-type(2) .stopwatch__frame .cuboid__side:nth-of-type(6)
--b 0.6
// Top left
.stopwatch__body .cuboid__side:nth-of-type(1) .stopwatch__body-angle:nth-of-type(1) .stopwatch__frame .cuboid__side:nth-of-type(6)
.stopwatch__body .cuboid__side:nth-of-type(4) .stopwatch__body-angle:nth-of-type(1) .stopwatch__frame .cuboid__side:nth-of-type(5)
--b 0.5
// Left
.stopwatch__body .cuboid__side:nth-of-type(4) .stopwatch__body-angle:nth-of-type(2) .stopwatch__frame .cuboid__side:nth-of-type(5)
--b 0.4
//Bottom left
.stopwatch__body .cuboid__side:nth-of-type(3) .stopwatch__body-angle:nth-of-type(1) .stopwatch__frame .cuboid__side:nth-of-type(5)
.stopwatch__body .cuboid__side:nth-of-type(4) .stopwatch__body-angle:nth-of-type(3) .stopwatch__frame .cuboid__side:nth-of-type(5)
--b 0.5
//Bottom
.stopwatch__body .cuboid__side:nth-of-type(3) .stopwatch__body-angle:nth-of-type(2) .stopwatch__frame .cuboid__side:nth-of-type(5)
--b 0.8
//Bottom right
.stopwatch__body .cuboid__side:nth-of-type(3) .stopwatch__body-angle:nth-of-type(3) .stopwatch__frame .cuboid__side:nth-of-type(5)
.stopwatch__body .cuboid__side:nth-of-type(2) .stopwatch__body-angle:nth-of-type(3) .stopwatch__frame .cuboid__side:nth-of-type(6)
--b 0.9
//Right
.stopwatch__body .cuboid__side:nth-of-type(2) .stopwatch__body-angle:nth-of-type(2) .stopwatch__frame .cuboid__side:nth-of-type(6)
--b 1
//Top right
.stopwatch__body .cuboid__side:nth-of-type(1) .stopwatch__body-angle:nth-of-type(3) .stopwatch__frame .cuboid__side:nth-of-type(6)
.stopwatch__body .cuboid__side:nth-of-type(2) .stopwatch__body-angle:nth-of-type(1) .stopwatch__frame .cuboid__side:nth-of-type(6)
--b 0.8
.stopwatch__body > .cuboid__side
pointer-events none
button
appearance none
border 0
background none
label
label > *
button
button > *
cursor pointer
pointer-events all
.stopwatch__body-angle
flex 1
position relative
&:nth-of-type(1)
&:nth-of-type(3)
flex 0.5
.stopwatch__body-angle
transform-origin var(--transform-origin, 50% 50%)
transform var(--rotate, rotate(0deg)) translate3d(0, 0, calc((var(--stopwatch-frame-depth) * var(--coefficient, -0.5)) * 1vmin))
.stopwatch__body .cuboid__side
&:nth-of-type(1) .stopwatch__body-angle
&:nth-of-type(1)
--transform-origin 100% 50%
--rotate rotateY(-45deg)
&:nth-of-type(3)
--transform-origin 0% 50%
--rotate rotateY(45deg)
&:nth-of-type(2) .stopwatch__body-angle
&:nth-of-type(1)
--transform-origin 50% 100%
--rotate rotateX(45deg)
&:nth-of-type(3)
--transform-origin 50% 0%
--rotate rotateX(-45deg)
&:nth-of-type(3) .stopwatch__body-angle
&:nth-of-type(1)
--transform-origin 100% 50%
--rotate rotateY(45deg)
--coefficient 0.5
&:nth-of-type(2)
--coefficient 0.5
&:nth-of-type(3)
--transform-origin 0% 50%
--coefficient 0.5
--rotate rotateY(-45deg)
&:nth-of-type(4) .stopwatch__body-angle
&:nth-of-type(1)
--transform-origin 50% 100%
--rotate rotateX(-45deg)
--coefficient 0.5
&:nth-of-type(2)
--coefficient 0.5
&:nth-of-type(3)
--transform-origin 50% 0%
--rotate rotateX(45deg)
--coefficient 0.5
.stopwatch__frame
--depth var(--stopwatch-frame-depth)
.cuboid__side
background var(--stopwatch-frame)
filter brightness(var(--b))
.stopwatch__control
position absolute
height 100%
width calc(var(--width, 140) * 1%)
top 50%
left 50%
transform translate3d(calc(var(--offset-x, -32) * 1%), -50%, calc(var(--stopwatch-frame-depth) * 0.5vmin))
.stopwatch__reset
--offset-x -64
.stopwatch__pause
display none
.cuboid__side > [type='reset']
height 100%
width 100%
position absolute
.stopwatch__pause
.stopwatch__start
--control-bg var(--start)
.stopwatch__reset
--control-bg var(--reset)
.button
--depth calc(var(--stopwatch-frame-depth) * 1)
transform translate3d(-50%, -50%, var(--elevation))
height 75%
width 65%
top 50%
left 50%
transition transform 0.1s
.cuboid__side
background var(--control-bg, red)
filter brightness(var(--b))
&__placeholder
width 100%
height 100%
&__container
--depth calc(var(--stopwatch-frame-depth) * 1.4)
--elevation calc(var(--stopwatch-frame-depth) * -0.2vmin)
transform translate3d(0, 0, calc(var(--depth) * 0.5vmin))
&:hover
--elevation calc(var(--stopwatch-frame-depth) * -0.35vmin)
&:active
--elevation calc(var(--stopwatch-frame-depth) * -0.85vmin)
.cuboid__side
filter brightness(var(--b))
// Stopwatch functionality
.digit
position relative
color transparent
counter-reset var(--counter-name) var(--counter-variable)
animation var(--name, none) var(--duration, 1s) infinite steps(var(--steps)) var(--state)
&:after
content counter(var(--counter-name))
font-variant tabular-nums
color var(--digit, white)
position absolute
bottom 0
right 0
.ms
font-size 4vmin
transform translate(0, -6%)
&--tens
--duration 1s
--steps 10
--counter-name ms-tens
--counter-variable var(--ms-tens)
&--singles
--duration 0.1s
--steps 10
--counter-name ms-singles
--counter-variable var(--ms-singles)
.s
&--tens
--duration 60s
--steps 6
--counter-name s-tens
--counter-variable var(--s-tens)
&--singles
--duration 10s
--steps 10
--counter-name s-singles
--counter-variable var(--s-singles)
.m
&--tens
--duration 3600s
--steps 6
--counter-name m-tens
--counter-variable var(--m-tens)
&--singles
--duration 600s
--steps 10
--counter-name m-singles
--counter-variable var(--m-singles)
// The different animations requires for each digit
@keyframes ms-tens
to
--ms-tens 10
@keyframes ms-singles
to
--ms-singles 10
@keyframes s-tens
to
--s-tens 6
@keyframes s-singles
to
--s-singles 10
@keyframes m-tens
to
--m-tens 6
@keyframes m-singles
to
--m-singles 10
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.