<div class="grid">
	<div class="grid__item grid__item--lg">
		<h1>Aspect ratio grid - now with variable ratios!</h1>
		<h2>Current ratio: 16:9</h2>
		<p>I noticed that using the CSS aspect ratio hack was causing issues with CSS Grid (when I needed all grid cells to be a 1:1 aspect ratio but some grid children to span more than one cell) so this is a solution with CSS Variables and a sprinkling of calc() instead. It does rely on knowing the outer width of the wrapper though (doesn’t work as a percentage value).</p>
		<p>If you change the wrapper and / or gutter variables you’ll see the blocks still maintain their aspect ratio <em>except</em> where the content in longer than the block, then they grow to fit.</p>
		<p>Some other solutions <a href="https://css-tricks.com/aspect-ratios-grid-items/" target="_blank">here</a> by Chris Coyier.</p>
	<div class="grid__item grid__item--sm">2</div>
	<div class="grid__item grid__item--sm">3</div>
	<div class="grid__item grid__item--db">4</div>
	<div class="grid__item grid__item--lg grid__item--right">5</div>
	<div class="grid__item grid__item--sm">6</div>
	<div class="grid__item grid__item--db">7</div>
	<div class="grid__item grid__item--sm">8</div>
* {
	box-sizing: border-box;

p {
	font-size: 1.4rem;
	line-height: 1.3;

a {
	color: darken(steelBlue, 20%);
	&:focus {
		color: black;

:root {
	// We just need to know these 3 values up front:
	--wrapper: 100vw;
	--gutter: 10px;
	--noOfColumns: 4;
	// Number of gutters is columns minus 1:
	--noOfGutters: calc(var(--noOfColumns) - 1);
	// Aspect ratio goes here, e.g. 16:9:
	--ratioA: 16;
	--ratioB: 9;
	// --ratio: 16/9;
	// Use the aspect ratio to calculate the factor for multiplication:
	--factor: calc(var(--ratioB) / var(--ratioA));
	// Calculating the row height:
	--rh: calc(( (var(--wrapper) - (var(--noOfGutters) * var(--gutter))) 
		/ var(--noOfColumns)) * var(--factor));

.grid {
	max-width: var(--wrapper);
	display: grid;
	grid-template-columns: repeat(var(--noOfColumns), 1fr);
	grid-auto-flow: dense;
	grid-auto-rows: minmax(var(--rh), auto); // If the content is taller then the box will grow to fit. This is only going to work if the column value is 1fr
	grid-gap: var(--gutter);
	margin: var(--gutter);

.grid__item {
	background-color: steelBlue;
	padding: 20px;

.grid__item--lg {
	grid-column: span 2;
	grid-row: span 2;
	background-color: coral;

.grid__item--right {
	grid-column: 3 / span 2;

.grid__item--db {
	grid-column: span 2;
	background-color: lightBlue;

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.