<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<!------ Include the above in your HEAD tag ---------->
<h1>Pure CSS Connect 4</h1>
<form>
<div class="board">
<div class="field">
<div class="grid column">
<input type="radio" name="slot11" tabindex="-1" required>
<input type="radio" name="slot11" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot12" tabindex="-1" required>
<input type="radio" name="slot12" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot13" tabindex="-1" required>
<input type="radio" name="slot13" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot14" tabindex="-1" required>
<input type="radio" name="slot14" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot15" tabindex="-1" required>
<input type="radio" name="slot15" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot16" tabindex="-1" required>
<input type="radio" name="slot16" tabindex="-1" required>
<div class="disc"></div>
<!--Column 1 after-->
<div class="column">
<input type="radio" name="slot21" tabindex="-1" required>
<input type="radio" name="slot21" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot22" tabindex="-1" required>
<input type="radio" name="slot22" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot23" tabindex="-1" required>
<input type="radio" name="slot23" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot24" tabindex="-1" required>
<input type="radio" name="slot24" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot25" tabindex="-1" required>
<input type="radio" name="slot25" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot26" tabindex="-1" required>
<input type="radio" name="slot26" tabindex="-1" required>
<div class="disc"></div>
<!--Column 2 after-->
<div class="column">
<input type="radio" name="slot31" tabindex="-1" required>
<input type="radio" name="slot31" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot32" tabindex="-1" required>
<input type="radio" name="slot32" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot33" tabindex="-1" required>
<input type="radio" name="slot33" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot34" tabindex="-1" required>
<input type="radio" name="slot34" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot35" tabindex="-1" required>
<input type="radio" name="slot35" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot36" tabindex="-1" required>
<input type="radio" name="slot36" tabindex="-1" required>
<div class="disc"></div>
<!--Column 3 after-->
<div class="column">
<input type="radio" name="slot41" tabindex="-1" required>
<input type="radio" name="slot41" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot42" tabindex="-1" required>
<input type="radio" name="slot42" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot43" tabindex="-1" required>
<input type="radio" name="slot43" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot44" tabindex="-1" required>
<input type="radio" name="slot44" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot45" tabindex="-1" required>
<input type="radio" name="slot45" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot46" tabindex="-1" required>
<input type="radio" name="slot46" tabindex="-1" required>
<div class="disc"></div>
<!--Column 4 after-->
<div class="column">
<input type="radio" name="slot51" tabindex="-1" required>
<input type="radio" name="slot51" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot52" tabindex="-1" required>
<input type="radio" name="slot52" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot53" tabindex="-1" required>
<input type="radio" name="slot53" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot54" tabindex="-1" required>
<input type="radio" name="slot54" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot55" tabindex="-1" required>
<input type="radio" name="slot55" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot56" tabindex="-1" required>
<input type="radio" name="slot56" tabindex="-1" required>
<div class="disc"></div>
<!--Column 5 after-->
<div class="column">
<input type="radio" name="slot61" tabindex="-1" required>
<input type="radio" name="slot61" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot62" tabindex="-1" required>
<input type="radio" name="slot62" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot63" tabindex="-1" required>
<input type="radio" name="slot63" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot64" tabindex="-1" required>
<input type="radio" name="slot64" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot65" tabindex="-1" required>
<input type="radio" name="slot65" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot66" tabindex="-1" required>
<input type="radio" name="slot66" tabindex="-1" required>
<div class="disc"></div>
<!--Column 6 after-->
<div class="column">
<input type="radio" name="slot71" tabindex="-1" required>
<input type="radio" name="slot71" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot72" tabindex="-1" required>
<input type="radio" name="slot72" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot73" tabindex="-1" required>
<input type="radio" name="slot73" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot74" tabindex="-1" required>
<input type="radio" name="slot74" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot75" tabindex="-1" required>
<input type="radio" name="slot75" tabindex="-1" required>
<div class="disc"></div>
<input type="radio" name="slot76" tabindex="-1" required>
<input type="radio" name="slot76" tabindex="-1" required>
<div class="disc"></div>
<!--Column 7 after-->
<div class="column"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="front"></div>
</div>
<button type="reset">New Game</button>
</form>
body {
margin: 0;
font-family: "Helvetica", "Verdana", "Roboto", sans-serif;
}
h1 {
margin: 0 0 15px;
padding: 15px;
color: #fff;
font-size: 40px;
font-weight: normal;
text-align: center;
background-color: #1f90ff;
}
form {
display: flex;
flex-flow: column nowrap;
align-items: center;
}
.board {
position: relative;
width: 450px;
height: 450px;
}
.field {
position: absolute;
top: 0;
left: 15px;
padding: 75px 0 0 0;
box-sizing: border-box;
width: 420px;
height: 435px;
overflow: hidden;
cursor: not-allowed;
}
.grid {
display: inline-flex;
flex-flow: column wrap;
position: relative;
min-width: 420px;
height: 360px;
counter-reset: player 1;
}
.column {
display: inline-flex;
flex-flow: column wrap;
height: 360px;
}
.front {
position: absolute;
top: 60px;
border: 15px solid #007fff;
border-radius: 4px;
box-sizing: border-box;
width: 450px;
height: 390px;
pointer-events: none;
background: radial-gradient(circle, transparent, transparent 18px, #007fff 20px, #007fff 23px, #1f90ff 23px, #1f90ff 36px, #007fff) center top/60px 60px;
}
/* Invisible inputs */
input {
display: none;
position: absolute;
top: -90px;
margin: 0;
width: 60px;
height: 450px;
cursor: pointer;
opacity: 0;
}
input:indeterminate {
display: initial;
}
/* Inputs for red */
.column > input:nth-of-type(2n) {
right: 360px;
}
.column > .column > input:nth-of-type(2n) {
right: 300px;
}
.column > .column > .column > input:nth-of-type(2n) {
right: 240px;
}
.column > .column > .column > .column > input:nth-of-type(2n) {
right: 180px;
}
.column > .column > .column > .column > .column > input:nth-of-type(2n) {
right: 120px;
}
.column > .column > .column > .column > .column > .column > input:nth-of-type(2n) {
right: 60px;
}
.column > .column > .column > .column > .column > .column > .column > input:nth-of-type(2n) {
right: 0;
}
/* Inputs for yellow */
.column > input:nth-of-type(2n+1) {
left: 0;
}
.column > .column > input:nth-of-type(2n+1) {
left: 60px;
}
.column > .column > .column > input:nth-of-type(2n+1) {
left: 120px;
}
.column > .column > .column > .column > input:nth-of-type(2n+1) {
left: 180px;
}
.column > .column > .column > .column > .column > input:nth-of-type(2n+1) {
left: 240px;
}
.column > .column > .column > .column > .column > .column > input:nth-of-type(2n+1) {
left: 300px;
}
.column > .column > .column > .column > .column > .column > .column > input:nth-of-type(2n+1) {
left: 360px;
}
/* Disc */
.disc {
position: relative;
top: 0;
width: 60px;
height: 60px;
color: #fff;
background: radial-gradient(circle, currentcolor 12px, #666 13px, currentcolor 14px, currentcolor 21px, #666 22px, transparent 23px, transparent) center/60px;
opacity: 0;
pointer-events: none;
transition: opacity 0.2s, top 0s 0.2s, color 0s 0.2s;
}
/* Red's turn */
input:hover + .disc {
color: #ff010b;
opacity: 1;
transition: opacity 0.2s, top 0s;
}
input:checked + .disc {
color: #ff010b;
opacity: 1;
}
/* Yellow's turn */
input:hover + input + .disc {
color: #ffd918;
opacity: 1;
transition: opacity 0.2s, top 0s;
}
input:checked + input + .disc {
color: #ffd918;
opacity: 1;
}
/* Height and time of disc fall per row */
input:hover + .disc:nth-of-type(1),
input:hover + input + .disc:nth-of-type(1){
top: -75px;
}
input:checked + .disc:nth-of-type(1),
input:checked + input + .disc:nth-of-type(1){
transition: top 0.14s cubic-bezier(0.56, 0, 1, 1);
}
input:hover + .disc:nth-of-type(2),
input:hover + input + .disc:nth-of-type(6n+2) {
top: -135px;
}
input:checked + .disc:nth-of-type(2),
input:checked + input + .disc:nth-of-type(2){
transition: top 0.19s cubic-bezier(0.56, 0, 1, 1);
}
input:hover + .disc:nth-of-type(3),
input:hover + input + .disc:nth-of-type(3) {
top: -195px;
}
input:checked + .disc:nth-of-type(3),
input:checked + input + .disc:nth-of-type(3) {
transition: top 0.23s cubic-bezier(0.56, 0, 1, 1);
}
input:hover + .disc:nth-of-type(4),
input:hover + input + .disc:nth-of-type(4) {
top: -255px;
}
input:checked + .disc:nth-of-type(4),
input:checked + input + .disc:nth-of-type(4) {
transition: top 0.26s cubic-bezier(0.56, 0, 1, 1);
}
input:hover + .disc:nth-of-type(5),
input:hover + input + .disc:nth-of-type(5){
top: -315px;
}
input:checked + .disc:nth-of-type(5),
input:checked + input + .disc:nth-of-type(5){
transition: top 0.29s cubic-bezier(0.56, 0, 1, 1);
}
input:hover + .disc:nth-of-type(6n),
input:hover + input + .disc:nth-of-type(6n) {
top: -375px;
}
input:checked + .disc:nth-of-type(6n),
input:checked + input + .disc:nth-of-type(6n) {
transition: top 0.32s cubic-bezier(0.56, 0, 1, 1);
}
/* Tracking turns */
input:checked + .disc {
counter-increment: player 2;
}
input:checked + input + .disc {
counter-increment: player -2;
}
.grid::after {
content: counter(player, lower-roman);
display: inline-block;
max-width: 840px;
min-width: 420px;
letter-spacing: 375px;
font-family: monospace;
font-size: 1px;
overflow: hidden;
}
/* Draw outcome */
form:valid .column > .column > .column > .column > .column > .column > .column > .column::after {
content: "It's a draw!";
z-index: 1;
position: absolute;
left: 0;
top: -75px;
width: 420px;
height: 435px;
visibility: visible;
color: #1f90ff;
font-size: 30px;
text-align: center;
line-height: 60px;
cursor: initial;
pointer-events: auto;
animation: outcome 1.5s;
}
/* Red column win */
input:checked + .disc + input + input:checked + .disc + input + input:checked + .disc + input + input:checked ~ .column::after,
/* Red row win */
input:nth-of-type(2):checked ~ .column > input:nth-of-type(2):checked ~ .column > input:nth-of-type(2):checked ~ .column > input:nth-of-type(2):checked ~ .column::after,
input:nth-of-type(4):checked ~ .column > input:nth-of-type(4):checked ~ .column > input:nth-of-type(4):checked ~ .column > input:nth-of-type(4):checked ~ .column::after,
input:nth-of-type(6):checked ~ .column > input:nth-of-type(6):checked ~ .column > input:nth-of-type(6):checked ~ .column > input:nth-of-type(6):checked ~ .column::after,
input:nth-of-type(8):checked ~ .column > input:nth-of-type(8):checked ~ .column > input:nth-of-type(8):checked ~ .column > input:nth-of-type(8):checked ~ .column::after,
input:nth-of-type(10):checked ~ .column > input:nth-of-type(10):checked ~ .column > input:nth-of-type(10):checked ~ .column > input:nth-of-type(10):checked ~ .column::after,
input:nth-of-type(12):checked ~ .column > input:nth-of-type(12):checked ~ .column > input:nth-of-type(12):checked ~ .column > input:nth-of-type(12):checked ~ .column::after,
/* Red diagonal win */
input:nth-of-type(2):checked ~ .column > input:nth-of-type(4):checked ~ .column > input:nth-of-type(6):checked ~ .column > input:nth-of-type(8):checked ~ .column::after,
input:nth-of-type(4):checked ~ .column > input:nth-of-type(6):checked ~ .column > input:nth-of-type(8):checked ~ .column > input:nth-of-type(10):checked ~ .column::after,
input:nth-of-type(6):checked ~ .column > input:nth-of-type(8):checked ~ .column > input:nth-of-type(10):checked ~ .column > input:nth-of-type(12):checked ~ .column::after,
input:nth-of-type(8):checked ~ .column > input:nth-of-type(6):checked ~ .column > input:nth-of-type(4):checked ~ .column > input:nth-of-type(2):checked ~ .column::after,
input:nth-of-type(10):checked ~ .column > input:nth-of-type(8):checked ~ .column > input:nth-of-type(6):checked ~ .column > input:nth-of-type(4):checked ~ .column::after,
input:nth-of-type(12):checked ~ .column > input:nth-of-type(10):checked ~ .column > input:nth-of-type(8):checked ~ .column > input:nth-of-type(6):checked ~ .column::after {
content: "Red wins! :)";
z-index: 2;
position: absolute;
left: 0;
top: -75px;
width: 420px;
height: 435px;
visibility: visible;
color: #ff010b;
font-size: 30px;
text-align: center;
line-height: 60px;
cursor: initial;
pointer-events: auto;
animation: outcome 1s;
}
/* Yellow column win */
input:checked + input + .disc + input:checked + input + .disc + input:checked + input + .disc + input:checked ~ .column::after,
/* Yellow row win */
input:nth-of-type(1):checked ~ .column > input:nth-of-type(1):checked ~ .column > input:nth-of-type(1):checked ~ .column > input:nth-of-type(1):checked ~ .column::after,
input:nth-of-type(3):checked ~ .column > input:nth-of-type(3):checked ~ .column > input:nth-of-type(3):checked ~ .column > input:nth-of-type(3):checked ~ .column::after,
input:nth-of-type(5):checked ~ .column > input:nth-of-type(5):checked ~ .column > input:nth-of-type(5):checked ~ .column > input:nth-of-type(5):checked ~ .column::after,
input:nth-of-type(7):checked ~ .column > input:nth-of-type(7):checked ~ .column > input:nth-of-type(7):checked ~ .column > input:nth-of-type(7):checked ~ .column::after,
input:nth-of-type(9):checked ~ .column > input:nth-of-type(9):checked ~ .column > input:nth-of-type(9):checked ~ .column > input:nth-of-type(9):checked ~ .column::after,
input:nth-of-type(11):checked ~ .column > input:nth-of-type(11):checked ~ .column > input:nth-of-type(11):checked ~ .column > input:nth-of-type(11):checked ~ .column::after,
/* Yellow diagonal win */
input:nth-of-type(1):checked ~ .column > input:nth-of-type(3):checked ~ .column > input:nth-of-type(5):checked ~ .column > input:nth-of-type(7):checked ~ .column::after,
input:nth-of-type(3):checked ~ .column > input:nth-of-type(5):checked ~ .column > input:nth-of-type(7):checked ~ .column > input:nth-of-type(9):checked ~ .column::after,
input:nth-of-type(5):checked ~ .column > input:nth-of-type(7):checked ~ .column > input:nth-of-type(9):checked ~ .column > input:nth-of-type(11):checked ~ .column::after,
input:nth-of-type(7):checked ~ .column > input:nth-of-type(5):checked ~ .column > input:nth-of-type(3):checked ~ .column > input:nth-of-type(1):checked ~ .column::after,
input:nth-of-type(9):checked ~ .column > input:nth-of-type(7):checked ~ .column > input:nth-of-type(5):checked ~ .column > input:nth-of-type(3):checked ~ .column::after,
input:nth-of-type(11):checked ~ .column > input:nth-of-type(9):checked ~ .column > input:nth-of-type(7):checked ~ .column > input:nth-of-type(5):checked ~ .column::after {
content: "Yellow wins! :)";
z-index: 2;
position: absolute;
left: 0;
top: -75px;
width: 420px;
height: 435px;
visibility: visible;
color: #ffd918;
font-size: 30px;
text-align: center;
line-height: 60px;
background: linear-gradient(#fff 60px, transparent 60px, transparent);
cursor: initial;
pointer-events: auto;
animation: outcome 1s;
}
/* Button style */
button {
margin: 20px auto;
border: none;
border-radius: 2px;
padding: 12px 18px;
font-size: 16px;
text-transform: uppercase;
cursor: pointer;
color: #fff;
background: #2196f3 center;
box-shadow: 0 0 4px #999;
outline: none;
transition: background 0.5s;
}
button:hover {
background: #47a7f5 radial-gradient(circle, transparent 1%, #47a7f5 1%) center/15000%;
}
button:active {
background-color: #6eb9f7;
background-size: 100%;
transition: background 0s;
}
@keyframes outcome {
0% {
opacity: 0;
}
35% {
opacity: 0;
}
100% {
opacity: 1;
}
}