.game
form
.board
- for(let g = 1; g < 5; g++)
svg.board__line(style=`--x: ${g < 3 ? g : 0}; --y: ${g < 3 ? 0 : g - 2}`)
path(d='M 5 5 L 295 5', fill='none', stroke-width='10', stroke-linecap='round', stroke-dasharray='300', stroke-dashoffset='300')
- for(let x = 0; x < 9; x++)
input(type='checkbox', id=`x--${x}`, style=`--col: ${x % 3}; --row: ${Math.floor(x / 3)}`)
span(style=`--col: ${x % 3}; --row: ${Math.floor(x / 3)}`)
svg.x
path.cross(d='M 20 20 L 80 80', fill='none', stroke-width='10', stroke-linecap='round', stroke-dasharray='100', stroke-dashoffset='100')
path.cross(d='M 80 20 L 20 80', fill='none', stroke-width='10', stroke-linecap='round', stroke-dasharray='100', stroke-dashoffset='100')
input(type='checkbox', id=`o--${x}`, style=`--col: ${x % 3}; --row: ${Math.floor(x / 3)}`)
span(style=`--col: ${x % 3}; --row: ${Math.floor(x / 3)}`)
svg.o
circle.naught(cx='50', cy='50', r='30', fill='none', stroke-width='10', stroke-dasharray='200', stroke-dashoffset='200', stroke-linecap='round')
- for(let y = 0; y < 9; y++)
label(for=`x--${y}`, style=`--col: ${y % 3}; --row: ${Math.floor(y / 3)}`)
label(for=`o--${y}`, style=`--col: ${y % 3}; --row: ${Math.floor(y / 3)}`)
.board__result.board__result--x.result
dl.result__content
dt.result__title Winner!
dd.result__details
svg.x.result__icon
path.cross(d='M 20 20 L 80 80', fill='none', stroke-width='10', stroke-linecap='round', stroke-dasharray='100', stroke-dashoffset='100')
path.cross(d='M 80 20 L 20 80', fill='none', stroke-width='10', stroke-linecap='round', stroke-dasharray='100', stroke-dashoffset='100')
button.result__reset(type='reset') Play again
//- .result__shield
- for (let c = 0; c < 30; c++)
.result__firework-icon(style=`--y: ${Math.floor(Math.random() * 300) + 200}; --r: ${Math.floor(Math.random() * 360)}`) 🎉
.board__result.board__result--o.result
dl.result__content
dt.result__title Winner!
dd.result__details
svg.o.result__icon
circle.naught(cx='50', cy='50', r='30', fill='none', stroke-width='10', stroke-dasharray='200', stroke-dashoffset='200', stroke-linecap='round')
button.result__reset(type='reset') Play again
//- .result__shield
- for (let c = 0; c < 30; c++)
.result__firework-icon(style=`--y: ${Math.floor(Math.random() * 300) + 200}; --r: ${Math.floor(Math.random() * 360)}`) 🎉
.board__result.board__result--draw
dl.result__content
dt.result__title Draw!
dd.result__details
.result__emoji ðŸ˜
button.result__reset(type='reset') Play again
View Compiled
*
box-sizing border-box
$bg = #1f3a93
$naught = #f62459
$cross = #36dbd7
$line = #fafafa
$size = 300px
$animDuration = .5s
body
html
align-items center
background-color $bg
color #fafafa
display flex
flex-direction column
font-family 'Arial', sans-serif
justify-content center
height 100vh
width 100vw
overflow hidden
position relative
svg
height ($size / 3)
width ($size / 3)
// hide all inputs from being visible
input
opacity 0
label
cursor pointer
height ($size / 3)
width ($size / 3)
z-index 2
// position each cells elements using css variables
input
span
label
left "calc(var(--col) * %s)" % ($size / 3)
position absolute
top "calc(var(--row) * %s)" % ($size / 3)
// give svg elements animation properties
circle
path
animation-fill-mode forwards
animation-name draw
circle
animation-duration $animDuration
stroke $naught
path
animation-duration ($animDuration / 2)
stroke $cross
button
cursor pointer
position absolute
bottom 20px
padding 8px 24px
border-radius 4px
border 0
background $bg
font-size .75rem
color #fafafa
filter drop-shadow(0 5px 5px black)
transition transform .1s, filter .1s
&:hover
filter drop-shadow(0 5px 4px black)
transform translateY(1px)
&:active
transform translateY(5px)
filter drop-shadow(0 0 0 transparent)
// span displays which player is occupying a cell
span
display none
transform translate3d(0, 0, 3px)
// only once an input is checked for a cell, show the appropriate span
input:checked + span
display block
.o
transform rotateY(180deg) rotate(-35deg)
.x
path:nth-of-type(2)
animation-delay ($animDuration / 2)
.board
height $size
left 50%
position absolute
top 50%
transform translate(-50%, -50%)
transform-style preserve-3d
width $size
&__line
height 10px
left "calc(var(--x) * %s)" % ($size / 3)
position absolute
top "calc(var(--y) * %s)" % ($size / 3)
width $size
path
stroke $line
&:nth-of-type(1)
&:nth-of-type(2)
transform rotate(90deg) translate(-5px, 0)
transform-origin left center
&:nth-of-type(3)
&:nth-of-type(4)
transform translate(0, -50%)
for $line in (1..4)
&:nth-of-type({$line}) path
animation-delay ($line * ($animDuration / 2))
&__result
animation fadeBg .25s $animDuration
animation-fill-mode backwards
background rgba(31, 58, 147, 1)
display none
height 100%
left 0
margin 0
padding 0
position absolute
top 0
transform translate3d(0, 0, 4px)
width 100%
.result
&__content
align-items center
animation flyIn .25s (.25s + $animDuration)
animation-fill-mode backwards
background #fafafa
border-radius 10px
color $bg
display flex
filter drop-shadow(0 10px 10px black)
flex-direction column
height 100%
justify-content center
left 0
margin 0
position absolute
top 0
width 100%
z-index 3
&__title
font-size 1.5rem
font-weight bolder
text-transform uppercase
&__details
margin 0
&__shield
animation fadeBg .25s $animDuration
animation-fill-mode backwards
background rgba(31, 58, 147, 1)
height 100%
left 0
position absolute
top 0
width 100%
z-index 2
&__emoji
font-size 5rem
&__icon
path:nth-of-type(1)
animation-delay (.5s + $animDuration)
path:nth-of-type(2)
animation-delay (0.9s + $animDuration)
circle
animation-delay (.5s + $animDuration)
&__firework-icon
animation fly .75s (.5s + $animDuration)
animation-fill-mode backwards
animation-timing-function cubic-bezier(0,.64,.25,1.01)
font-size 2rem
height 2rem
left 50%
margin-left -1rem
margin-top -1rem
opacity 0
position absolute
top 50%
transform rotate(calc(var(--r) * 1deg)) translateY(calc(var(--y) * -1px))
width 2rem
// animations
@keyframes draw
to
stroke-dashoffset 0
@keyframes fadeBg
from
background rgba(31, 58, 147, 0)
@keyframes fly
0%
opacity 0
transform translateY(0)
5%, 50%
opacity 1
100%
opacity 0
@keyframes flyIn
from
transform translateY(100%) scale(0)
// there are 9 moves to make alternating between even and odd labels showing
:checked ~ label:nth-of-type(odd)
:checked ~ :checked ~ :checked ~ label:nth-of-type(odd)
:checked ~ :checked ~ :checked ~ :checked ~ :checked ~ label:nth-of-type(odd)
:checked ~ :checked ~ :checked ~ :checked ~ :checked ~ :checked ~ :checked ~ label:nth-of-type(odd)
:checked ~ :checked ~ label:nth-of-type(even)
:checked ~ :checked ~ :checked ~ :checked ~ label:nth-of-type(even)
:checked ~ :checked ~ :checked ~ :checked ~ :checked ~ :checked ~ label:nth-of-type(even)
:checked ~ :checked ~ :checked ~ :checked ~ :checked ~ :checked ~ :checked ~ :checked ~ label:nth-of-type(even)
transform translate3d(0, 0, 2px)
:checked ~ label:nth-of-type(even)
:checked ~ :checked ~ :checked ~ label:nth-of-type(even)
:checked ~ :checked ~ :checked ~ :checked ~ :checked ~ label:nth-of-type(even)
:checked ~ :checked ~ :checked ~ :checked ~ :checked ~ :checked ~ :checked ~ label:nth-of-type(even)
:checked ~ :checked ~ label:nth-of-type(odd)
:checked ~ :checked ~ :checked ~ :checked ~ label:nth-of-type(odd)
:checked ~ :checked ~ :checked ~ :checked ~ :checked ~ :checked ~ label:nth-of-type(odd)
:checked ~ :checked ~ :checked ~ :checked ~ :checked ~ :checked ~ :checked ~ :checked ~ label:nth-of-type(odd)
transform translate3d(0, 0, -1px)
:checked ~ :checked ~ :checked ~ :checked ~ :checked ~ :checked ~ :checked ~ :checked ~ :checked
// if the last move is played and there isn't a winner, show a draw
~ .board__result--draw
display block
// winning combos
#x--0:checked ~ #x--1:checked ~ #x--2:checked ~ .board__result--x
#x--3:checked ~ #x--4:checked ~ #x--5:checked ~ .board__result--x
#x--6:checked ~ #x--7:checked ~ #x--8:checked ~ .board__result--x
#x--0:checked ~ #x--3:checked ~ #x--6:checked ~ .board__result--x
#x--1:checked ~ #x--4:checked ~ #x--7:checked ~ .board__result--x
#x--2:checked ~ #x--5:checked ~ #x--8:checked ~ .board__result--x
#x--0:checked ~ #x--4:checked ~ #x--8:checked ~ .board__result--x
#x--2:checked ~ #x--4:checked ~ #x--6:checked ~ .board__result--x
#o--0:checked ~ #o--1:checked ~ #o--2:checked ~ .board__result--o
#o--3:checked ~ #o--4:checked ~ #o--5:checked ~ .board__result--o
#o--6:checked ~ #o--7:checked ~ #o--8:checked ~ .board__result--o
#o--0:checked ~ #o--3:checked ~ #o--6:checked ~ .board__result--o
#o--1:checked ~ #o--4:checked ~ #o--7:checked ~ .board__result--o
#o--2:checked ~ #o--5:checked ~ #o--8:checked ~ .board__result--o
#o--0:checked ~ #o--4:checked ~ #o--8:checked ~ .board__result--o
#o--2:checked ~ #o--4:checked ~ #o--6:checked ~ .board__result--o
display block
// if there's a winner on the last move, don't show a draw!
~ .board__result--draw
display none
View Compiled
// NOT FOUND
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.