I have seen demos of pure CSS Tic-tac-toe games, but I was unable to find a version that truly works. If I have missed it, please send me link, so I can see how another dev has created it.
A Pen by Žiga Miklič on CodePen.
.tic-tac-toe | |
- for (var turn = 1; turn <= 9; turn++) | |
- for (var row = 1; row <= 3; row++) | |
- for (var column = 1; column <= 3; column++) | |
- var player = "1" | |
- var positionHorizontal = "" | |
- var positionVertical = "" | |
- var positionDiagonal = "" | |
if( turn % 2 == 0 ) | |
- var player = "2" | |
if( column == 1 ) | |
- var positionHorizontal = " left first-column" | |
else if( column == 2 ) | |
- var positionHorizontal = " middle second-column" | |
else if( column == 3 ) | |
- var positionHorizontal = " right third-column" | |
if( row == 1 ) | |
- var positionVertical = " top first-row" | |
else if( row == 2 ) | |
- var positionVertical = " center second-row" | |
else if( row == 3 ) | |
- var positionVertical = " bottom third-row" | |
if( row == 1 && column == 1 ) | |
- var positionDiagonal = " first-diagonal" | |
else if( row == 1 && column == 3 ) | |
- var positionDiagonal = " second-diagonal" | |
else if( row == 2 && column == 2 ) | |
- var positionDiagonal = " first-diagonal second-diagonal" | |
else if( row == 3 && column == 1 ) | |
- var positionDiagonal = " second-diagonal" | |
else if( row == 3 && column == 3 ) | |
- var positionDiagonal = " first-diagonal" | |
input(id="block" + turn + "-" + row + "-" + column type="radio" class="player-" + player + positionHorizontal + positionVertical + positionDiagonal + " turn-" + turn) | |
label(for="block" + turn + "-" + row + "-" + column class="turn-" + turn) | |
.end | |
h3 | |
a(href="") Restart | |
h5 Note: use the Full Page view for the best experience. |
I have seen demos of pure CSS Tic-tac-toe games, but I was unable to find a version that truly works. If I have missed it, please send me link, so I can see how another dev has created it.
A Pen by Žiga Miklič on CodePen.
// Look ma' no JS! :) | |
/* | |
I have seen demos of pure CSS Tic-tac-toe games, but I was unable to find a version that truly works. If I have missed it, please send me link, so I can see how another dev has created it. | |
My version works as any normal Tic-tac-toe game would: 2 players can play against each other, it can result in either a win or a tie. Players can also restart the game. | |
In my CodePen example, I used Jade and SASS, so that my code looks much cleaner and simpler to understand. | |
*/ | |
// How it works: http://codepen.io/ziga-miklic/blog/pure-css-tic-tac-toe/ |
@import "compass/css3"; | |
/* Variables | |
-------------------------------------------------------------- */ | |
$size-sm: 90px; | |
$size: 140px; | |
$spacing: 5px; | |
$player-1-icon: "\f00d"; | |
$player-2-icon: "\f10c"; | |
$player-1-color: #dc685a; | |
$player-2-color: #ecaf4f; | |
$hover-color: #3d4250; | |
/* Body and Notice styling | |
-------------------------------------------------------------- */ | |
body { | |
color: #b6b5ca; | |
font-family: 'Arial', sans-serif; | |
margin: 0; | |
text-align: center; | |
} | |
h5 { | |
font-weight: 400; | |
padding: 0 20px; | |
} | |
/* Tic-tac-toe game | |
-------------------------------------------------------------- */ | |
.tic-tac-toe { | |
font-family: 'Open Sans', sans-serif; | |
height: ($size-sm + $spacing*2)*3; | |
overflow: hidden; | |
margin: 50px auto 30px auto; | |
position: relative; | |
width: ($size-sm + $spacing*2)*3; | |
@media(min-width: 450px) { | |
height: ($size + $spacing*2)*3; | |
width: ($size + $spacing*2)*3; | |
} | |
input[type="radio"] { | |
// Hide radio buttons | |
display: none; | |
// Put the label above the rest, when checked | |
&:checked + label { | |
cursor: default; | |
z-index: 10 !important; | |
} | |
// Player 1 icon | |
&.player-1 + label:after { content: $player-1-icon; } | |
// Player 2 icon | |
&.player-2 + label:after { content: $player-2-icon; } | |
// Show icon when checked | |
&.player-1:checked + label:after, | |
&.player-2:checked + label:after { opacity: 1; } | |
// Player 1 color | |
&.player-1:checked + label { background-color: $player-1-color; } | |
// Player 2 color | |
&.player-2:checked + label { background-color: $player-2-color; } | |
// Stack each turn on top of another | |
@for $i from 1 through 9 { | |
&.turn-#{$i} + label { | |
z-index: $i; | |
} | |
} | |
// Display the first turn | |
&.turn-1 + label { display: block; } | |
// Show next turn, once the current label has been :checked | |
@for $i from 1 through 8 { | |
&.turn-#{$i}:checked ~ .turn-#{$i+1} + label { display: block; } | |
} | |
// Label positioning | |
&.left + label { left: 0; } | |
&.top + label { top: 0; } | |
&.middle + label { left: ($size-sm + $spacing*2); } | |
&.right + label { left: ($size-sm + $spacing*2)*2; } | |
&.center + label { top: ($size-sm + $spacing*2); } | |
&.bottom + label { top: ($size-sm + $spacing*2)*2; } | |
@media(min-width: 450px) { | |
&.middle + label { left: ($size + $spacing*2); } | |
&.right + label { left: ($size + $spacing*2)*2; } | |
&.center + label { top: ($size + $spacing*2); } | |
&.bottom + label { top: ($size + $spacing*2)*2; } | |
} | |
} | |
// If all 9 turns have been played, show the end pop-up and set the text to "It is a tie!" | |
input[type="radio"]:checked ~ input[type="radio"]:checked ~ input[type="radio"]:checked ~ | |
input[type="radio"]:checked ~ input[type="radio"]:checked ~ input[type="radio"]:checked ~ | |
input[type="radio"]:checked ~ input[type="radio"]:checked ~ input[type="radio"]:checked ~ .end { | |
display: block; | |
> h3:before { content: "It is a tie!"; } | |
} | |
// Check for all posibble victories, for both players individually | |
@for $i from 1 through 2 { | |
.player-#{$i}.first-column:checked ~ .player-#{$i}.first-column:checked ~ .player-#{$i}.first-column:checked ~ .end, | |
.player-#{$i}.second-column:checked ~ .player-#{$i}.second-column:checked ~ .player-#{$i}.second-column:checked ~ .end, | |
.player-#{$i}.third-column:checked ~ .player-#{$i}.third-column:checked ~ .player-#{$i}.third-column:checked ~ .end, | |
.player-#{$i}.first-row:checked ~ .player-#{$i}.first-row:checked ~ .player-#{$i}.first-row:checked ~ .end, | |
.player-#{$i}.second-row:checked ~ .player-#{$i}.second-row:checked ~ .player-#{$i}.second-row:checked ~ .end, | |
.player-#{$i}.third-row:checked ~ .player-#{$i}.third-row:checked ~ .player-#{$i}.third-row:checked ~ .end, | |
.player-#{$i}.first-diagonal:checked ~ .player-#{$i}.first-diagonal:checked ~ .player-#{$i}.first-diagonal:checked ~ .end, | |
.player-#{$i}.second-diagonal:checked ~ .player-#{$i}.second-diagonal:checked ~ .player-#{$i}.second-diagonal:checked ~ .end { | |
display: block; | |
h3:before { content: "Player #{$i} wins!" !important; } | |
} | |
} | |
// Label style | |
label { | |
background-color: #78bec5; | |
border-radius: 14px; | |
cursor: pointer; | |
color: #fff; | |
display: none; | |
height: $size-sm; | |
margin: $spacing; | |
position: absolute; | |
width: $size-sm; | |
@include transition(background-color .3s); | |
@media(min-width: 450px) { | |
height: $size; | |
width: $size; | |
} | |
// Label hover effect | |
&:hover { | |
background-color: $hover-color; | |
&:after { opacity: .4; } | |
} | |
// Icon style | |
&:after { | |
left: 0; | |
font-family: "FontAwesome"; | |
font-size: $size-sm*0.5; | |
margin-top: -($size-sm*0.5)/2; | |
opacity: 0; | |
position: absolute; | |
text-align: center; | |
text-shadow: 2px 2px 4px rgba(0, 0, 0, .2); | |
top: 50%; | |
width: 100%; | |
@media(min-width: 450px) { | |
font-size: $size*0.5; | |
margin-top: -($size*0.5)/2; | |
} | |
} | |
} | |
// End screen style | |
.end { | |
background: rgba(255, 255, 255, .8); | |
bottom: 5px; | |
color: #3d4250; | |
display: none; | |
left: 5px; | |
padding-top: 55px; | |
position: absolute; | |
right: 5px; | |
top: 5px; | |
text-align: center; | |
z-index: 11; | |
@media(min-width: 450px) { | |
padding-top: 110px; | |
} | |
h3 { | |
font-size: 30px; | |
font-weight: 300; | |
@media(min-width: 450px) { font-size: 40px; } | |
} | |
a { | |
background-color: #3d4250; | |
border-radius: 4px; | |
color: #fff; | |
padding: 14px 45px; | |
text-decoration: none; | |
@include transition(background-color .2s); | |
&:hover { | |
background-color: #262934; | |
cursor: pointer; | |
} | |
} | |
} | |
} |