<form>
  <div class="board-wrapper">
    <div class="board-outer">
      <div class="board">
        <div class="board-inner">
          <input type="radio" name="pos11" id="pos11-blue" class="blue" required>
          <input type="radio" name="pos11" id="pos11-red" class="red" required>
          <div class="marque"></div>

          <input type="radio" name="pos12" id="pos12-blue" class="blue" required>
          <input type="radio" name="pos12" id="pos12-red" class="red" required>
          <div class="marque"></div>

          <input type="radio" name="pos13" id="pos13-blue" class="blue" required>
          <input type="radio" name="pos13" id="pos13-red" class="red" required>
          <div class="marque"></div>

          <input type="radio" name="pos21" id="pos21-blue" class="blue" required>
          <input type="radio" name="pos21" id="pos21-red" class="red" required>
          <div class="marque"></div>

          <input type="radio" name="pos22" id="pos22-blue" class="blue" required>
          <input type="radio" name="pos22" id="pos22-red" class="red" required>
          <div class="marque"></div>

          <input type="radio" name="pos23" id="pos23-blue" class="blue" required>
          <input type="radio" name="pos23" id="pos23-red" class="red" required>
          <div class="marque"></div>

          <input type="radio" name="pos31" id="pos31-blue" class="blue" required>
          <input type="radio" name="pos31" id="pos31-red" class="red" required>
          <div class="marque"></div>

          <input type="radio" name="pos32" id="pos32-blue" class="blue" required>
          <input type="radio" name="pos32" id="pos32-red" class="red" required>
          <div class="marque"></div>

          <input type="radio" name="pos33" id="pos33-blue" class="blue" required>
          <input type="radio" name="pos33" id="pos33-red" class="red" required>
          <div class="marque"></div>

          <div id="win-blue" class="win-message"><div class="wrapper">Blue wins!</div></div>
          <div id="win-red" class="win-message"><div class="wrapper">Red wins!</div></div>
          <div id="no-winner" class="win-message"><div class="wrapper">It's a draw!</div></div>
        </div>
      </div>
    </div>
  </div>
  <div class="actions">
    <button type="reset">Restart</button>
  </div>
</form>
* {
	margin:0;
	padding:0;
	box-sizing:border-box;
}
html, body {
	background:#000;
}

/*vars*/
$red:#c50878;
$redhover:rgba(197, 9, 120, .3);
$blue:#5039ff;
$bluehover:rgba(80, 57, 255, .3);

:root {
	--blocksize:20vw;
	--boardsize:60vw;
	--spacing:45vw;
	--winmsgsize:8vw;
}
@media (min-width: 750px) {
	:root {
		--blocksize:150px;
		--boardsize:450px;
		--spacing:400px;
		--winmsgsize:3rem;
	}
}

/*board*/
.board-wrapper {
	overflow:hidden;
	margin:3rem 0 0 calc( 50vw - var(--boardsize) / 2 );
	width:var(--boardsize);
}
.board-outer {
	width:100vw;
}
.board-inner {
	width:var(--boardsize); height:var(--boardsize);
}
.board {
	float:left;
	position:relative;

	&:before {
		position:absolute;
		left:-999px;
		content:counter(player);
	}
	&:after {
		content:counter(player, lower-roman);
		display:inline-block;
		height:0;
		background:grey;
		font-family:monospace;
		letter-spacing:var(--spacing);
		overflow:hidden;
	}
}

/*input radio*/
.board input {
	position:absolute;
	width:var(--blocksize);
	height:var(--blocksize);
	cursor:pointer;
	opacity:0;
	-webkit-appearance:none;

	&:indeterminate {
		display:block;
	}
	&:checked,
	&:checked + input {
		display:none;
	}

	&.blue {
		background:$blue;
	}
	&.red {
		background:$red;
		left:auto !important;
	}

	&[name="pos11"] {
		top:0; left:0;
		& + input { right:calc( 2 * var(--blocksize) ); }
	}
	&[name="pos12"] {
		top:0; left:var(--blocksize);
		& + input { right:var(--blocksize); }
	}
	&[name="pos13"] {
		top:0; left:calc( 2 * var(--blocksize) );
		& + input { right:0; }
	}
	&[name="pos21"] {
		top:var(--blocksize); left:0;
		& + input { right:calc( 2 * var(--blocksize) ); }
	}
	&[name="pos22"] {
		top:var(--blocksize); left:var(--blocksize);
		& + input { right:var(--blocksize); }
	}
	&[name="pos23"] {
		top:var(--blocksize); left:calc( 2 * var(--blocksize) );
		& + input { right:0; }
	}
	&[name="pos31"] {
		top:calc( 2 * var(--blocksize) ); left:0;
		& + input { right:calc( 2 * var(--blocksize) ); }
	}
	&[name="pos32"] {
		top:calc( 2 * var(--blocksize) ); left:var(--blocksize);
		& + input { right:var(--blocksize); }
	}
	&[name="pos33"] {
		top:calc( 2 * var(--blocksize) ); left:calc( 2 * var(--blocksize) );
		& + input { right:0; }
	}
}

/*marque*/
.marque {
	float:left;
	display:flex;
	padding:1px;
	width:var(--blocksize); height:var(--blocksize);
	justify-content:center;
	align-items:center;
	background:#1d1d1d;
	background-clip:content-box;
	&:before {
		content:"";
		position:static;
		display:block;
		width:50%; height:50%;
	}
}

/* marque hover*/
.blue:hover + .red + .marque:before {
	background:$bluehover;
	border-radius:3px;
}
.blue + .red:hover + .marque:before {
	background:$redhover;
	border-radius:50%;
}

/* marque checked*/
.blue:checked + .red + .marque {
	counter-increment:player 2;
	position:relative;
	z-index:100;
	&:before {
		background:$blue;
		border-radius:3px;
	}
}
.blue + .red:checked + .marque {
	counter-increment:player -2;
	position:relative;
	z-index:100;
	&:before {
		background:$red;
		border-radius:50%
	}
}

/* results */
@mixin winners($val) {
	//1st line
	#pos11-#{$val}:checked ~ #pos12-#{$val}:checked ~ #pos13-#{$val}:checked ~ #win-#{$val},
	//2nd line
	#pos21-#{$val}:checked ~ #pos22-#{$val}:checked ~ #pos23-#{$val}:checked ~ #win-#{$val},
	//3rd line
	#pos31-#{$val}:checked ~ #pos32-#{$val}:checked ~ #pos33-#{$val}:checked ~ #win-#{$val},
	//1st column
	#pos11-#{$val}:checked ~ #pos21-#{$val}:checked ~ #pos31-#{$val}:checked ~ #win-#{$val},
	//2nd column
	#pos12-#{$val}:checked ~ #pos22-#{$val}:checked ~ #pos32-#{$val}:checked ~ #win-#{$val},
	//3rd column
	#pos13-#{$val}:checked ~ #pos23-#{$val}:checked ~ #pos33-#{$val}:checked ~ #win-#{$val},
	//1st diagonal
	#pos11-#{$val}:checked ~ #pos22-#{$val}:checked ~ #pos33-#{$val}:checked ~ #win-#{$val},
	//2nd diagonal
	#pos13-#{$val}:checked ~ #pos22-#{$val}:checked ~ #pos31-#{$val}:checked ~ #win-#{$val} {
		display:block;
		& ~ #no-winner {
			display:none;
		}
	}
}

.win-message {
	position:absolute;
	top:0;
	display:none;
    height:100%; width:100%;
	color:#FFF;
	font-size:var(--winmsgsize);
	font-weight:bold;
    z-index:200;
    .wrapper {
    	display:flex;
		justify-content:center;
		align-items:center;
    	width:var(--boardsize); height:var(--boardsize);
    	background:rgba(0,0,0,.6);
    }
}

/*blue wins*/
@include winners(blue);
/*red wins*/
@include winners(red);

/**/
form:valid {
	#no-winner {
		display:block;
	}
}
/* reset */
.actions {
	clear:both;
  margin-bottom:2rem;
	text-align:center;

	button {
		margin-top:1rem;
		padding:0.8rem 2rem;
		border:1px solid #1d1d1d;
		color:#555;
		background:#000;
		font-size:0.9rem;
		cursor:pointer;
		transition:background .3s ease-out, border .3s ease-out;
		&:hover {
			border-color:#303030;
			background:#0a0a0a;
		}
	}
}
View Compiled
/*
Modern browsers that support vw units, css counter, and css variables only!

Highly inspired by Bence Szabó's Pure CSS Connect 4
https://codepen.io/finnhvman/pen/xXpzVN
https://css-tricks.com/roman-empire-made-pure-css-connect-4-possible/
*/

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.