<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);
}

/* Fix stuck disc */
input:checked + .disc,
input:checked + input + .disc {
  top: 0 !important;
}

/* 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;
  }
}
// ¯\_(ツ)_/¯

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.