In this exercise, we’re going to walk through typesetting a poster for a music festival using everything we’ve learned so far about layout, colour, fonts, and text, and learn a few more things along the way.
Here’s the code we’re going to start with:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Festival Poster</title>
<style>
</style>
</head>
<body>
<header>
<h1>Hot Metal</h1>
<p>The World's #1 Typographic Rock Festival</p>
<h2>22–24 August 2025</h2>
<address>Paratype Park, London, UK</address>
</header>
<main>
<section>
<header>
Friday 22.08
</header>
<h1 id="ellipsis">Ellipsis</h1>
<h2 id="typo-negative"><span>Typo</span> <span>Negative</span></h2>
<h3 id="drop-shadow"><span>Drop</span> <span>Shadow</span></h3>
<ul>
<li>Arial Black</li>
<li>Zero Width</li>
<li>Slab Serif</li>
<li>J-Bowl and the Descenders</li>
<li>Zapf Chancery</li>
<li>Hell Vetica</li>
</ul>
</section>
<section>
<header>
Saturday 23.08
</header>
<h1 id="the-ligatures"><span>The</span> <span>Ligatures</span></h1>
<h2 id="franklin-gothic"><span>Franklin</span> <span>Gothic</span></h2>
<h3 id="baseline-shift"><span>Baseline</span> <span>Shift</span></h3>
<ul>
<li>Times New Romantics</li>
<li>Scary Poppins</li>
<li>Cascadia Coda</li>
<li>Back to the Futura</li>
<li>Impact Statement</li>
<li>Trebuchet MSG</li>
</ul>
</section>
<section>
<header>
Sunday 24.08
</header>
<h1 id="forbidden-frutiger"><span>Forbidden</span> <span>Frutiger</span>
</h1>
<h2 id="tragic-sans"><span>Tragic</span> <span>Sans</span></h2>
<h3 id="monsters-of-rockwell"><span>Monsters</span>
<span>of</span> <span>Rockwell</span>
</h3>
<ul>
<li>Optima’s Prime</li>
<li>Pino Palatino</li>
<li>Courier New Wave</li>
<li>Richie Verdana</li>
<li>Cambria Explosion</li>
<li>Georgia Satellites</li>
</ul>
</section>
</main>
<footer>
<h1>TICKETS</h1>
<a href="#">www.hotmetal.dev</a>
<a href="#">www.ticketmaster.com</a>
</footer>
</body>
</html>We’ve got a header, with the name of the festival, the strapline, the date and the venue, then a <main> element with a <section> for each day of the festival, then inside each section we’ve got another <header> with the date, an <h1> with the name of the headline act, <h2> and <h3> for the second and third acts on that bill, an undordered list of the other acts appearing on that date, and a <footer> with details of where we can go to get tickets.
Now, this is a fantastic place to start: it’s accessible, responsive, the whole thing is less than 2kb of HTML - and we’ve got a unique ID on all of the featured bands, which is going to make life a lot easier when we start targeting those elements with complex typographic rules.
Doesn’t look like much, though:
So, let’s fix it up.
Normalize
First, let’s add a few normalize styles - these will set everything to use border-box sizing, and remove any margins and padding from the html and body elements.
*,
::before,
::after {
box-sizing: border-box;
}
html,
body {
margin: 0;
padding: 0;
}Layout
Next up, we’ll create our layout rules:
/* Outline all the things while we figure out the layout */
html * {
outline: 1px solid #f0f;
}
body {
max-width: 720px;
margin: 0px auto;
padding: 0px 0;
&>header {
text-align: center;
margin-bottom: 2em;
padding: 20px 0;
p {
padding: 0.5rem;
}
}
&>footer {
position: sticky;
bottom: 0px;
clear: both;
padding: 1em;
h1 {
width: 50%;
float: left;
margin: 0;
}
a {
display: block;
}
}
}
section {
text-align: center;
width: 33%;
float: left;
header {
padding: 1rem 0 0.2rem 0;
}
ul {
margin: 0;
padding: 0;
li {
display: block;
}
}
}Colours and Borders
Then we’ll add rules for colours and borders:
*,
::before,
::after {
box-sizing: border-box;
}
html,
body {
margin: 0;
padding: 0;
}
html {
background: #000;
color: #fff;
}
body {
max-width: 720px;
margin: 0px auto;
padding: 0px 0;
border-width: 0 3px;
border-color: #06b;
border-style: double;
box-sizing: border-box;
&>header {
text-align: center;
margin-bottom: 2em;
background-color: #012;
padding: 20px 0;
p {
padding: 0.5rem;
background-color: #036;
border-width: 3px 0;
border-style: double;
border-color: #06b;
}
}
&>footer {
position: sticky;
bottom: 0px;
clear: both;
padding: 1em;
background-color: #012;
border-width: 1px 0;
border-style: solid;
border-color: #06b;
h1 {
width: 50%;
float: left;
margin: 0;
}
a {
color: white;
text-decoration: none;
display: block;
}
}
}
section {
text-align: center;
width: 33%;
float: left;
padding: 0.5rem;
header {
border-bottom: 1px solid #fff;
padding: 1rem 0 0.2rem 0;
}
ul {
margin: 0;
padding: 0;
li {
display: block;
}
}
}Basic Typography
Let’s grab a font from Google Fonts to override the default font across the whole of that page. We’re going to use a font called Economica:
Click through to “Get Font”, grab the embed code, and we’re going to use the @import syntax - this is CSS’ mechanism to import styles and rules from an external URL.
Paste the import rule at the top of our file, and then we’re going to add some rules to apply that font, and to override the default formatting for some of our page elements:
@import url('https://fonts.googleapis.com/css2?family=Economica:ital,wght@0,400;0,700;1,400;1,700&display=swap');
*,
::before,
::after {
box-sizing: border-box;
}
html,
body {
margin: 0;
padding: 0;
}
html {
background: #000;
color: #fff;
}
body {
font-family: Economica;
max-width: 720px;
margin: 0px auto;
padding: 0px 0;
border-width: 0 3px;
border-color: #06b;
border-style: double;
box-sizing: border-box;
&>header {
text-align: center;
margin-bottom: 2em;
background-color: #012;
padding: 20px 0;
h1 {
font-weight: normal;
font-size: 3em;
letter-spacing: 1em;
text-indent: 1em;
text-transform: uppercase;
}
p {
padding: 0.5rem;
background-color: #036;
border-width: 3px 0;
border-style: double;
border-color: #06b;
letter-spacing: 0.3em;
text-transform: lowercase;
}
}
&>footer {
position: sticky;
bottom: 0px;
clear: both;
padding: 1em;
background-color: #012;
border-width: 1px 0;
border-style: solid;
border-color: #06b;
h1 {
width: 50%;
float: left;
margin: 0;
text-align: right;
padding-right: 0.2em;
&::after {
content: ':';
}
}
a {
color: white;
text-decoration: none;
display: block;
}
}
}
section {
text-align: center;
width: 33%;
float: left;
padding: 0.5rem;
header {
border-bottom: 1px solid #fff;
padding: 1rem 0 0.2rem 0;
}
ul {
margin: 0;
padding: 0;
line-height: 2.2rem;
li {
&:first-of-type {
font-size: 1.2rem;
font-weight: bold;
}
display: block;
}
}
}Artist Logotypes
Next, we’re going to use the names of the various featured artists to showcase many of the capabilities of CSS typography.
OK, listen up. This is a fun way to showcase what CSS typography can do, and see the effects of various font and text properties.
It is a terrible way to actually create artwork that incorporates anybody else’s logos or logotypes. If you were doing this for a real music festival, you’d get high-quality vector artwork from the artists and use SVG or PNG images to display their logos.
I wouldn’t do this on a real project unless the client explicitly told me to recreate their logo using CSS, and provided the colour specs and typefaces, and even then I’d be waiting for the angry email saying it doesn’t look right on the boss’ 2011 Macbook Pro.
We’ve done two things in the underlying HTML to make this part of the exercise a little easier; every featured artist element has an associated id attribute, and the individual words within each artist’s name are wrapped in <span> tags.
CSS has the
::first-letterand::first-linepseudo-elements, but no syntax for targeting specific words within a text element - there’s no::first-word,:nth-wordor anything comparable.
}
}
@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400..900&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Audiowide&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Faculty+Glyphic&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Roboto+Flex:opsz,slnt,wdth,wght,GRAD,XOPQ,XTRA,YOPQ,YTAS,YTDE,YTFI,YTLC,YTUC@8..144,-10..0,25..151,100..1000,-200..150,27..175,323..603,25..135,649..854,-305..-98,560..788,416..570,528..760&display=swap');
#ellipsis {
font-family: Orbitron;
font-weight: 400;
text-transform: lowercase;
color: #999;
text-shadow: 0px 0px 5px rgba(255, 255, 255);
letter-spacing: 0.5em;
text-indent: 0.5em;
}
#typo-negative {
color: #f90;
text-transform: uppercase;
font-family: Audiowide;
font-size: 1.2rem;
}
#drop-shadow {
font-family: "Faculty Glyphic", sans-serif;
color: #000;
text-shadow: 2px 2px 1px #fff9, -2px -2px 1px #fff9;
}
#the-ligatures {
span:first-child {
font-family: 'Times New Roman', Times, serif;
font-weight: normal;
font-style: italic;
position: relative;
left: 3px;
}
span:not(:first-child) {
font-family: Arial, Helvetica, sans-serif;
font-weight: 900;
position: relative;
left: -3px
}
}
#franklin-gothic {
font-family: "Faculty Glyphic", sans-serif;
color: transparent;
text-shadow: 0 0 2px #fff9;
span {
display: inline-block;
&::first-letter {
font-size: 1.8em;
}
}
span:first-child::first-letter {
position: relative;
top: -4px;
left: 10px;
}
}
#baseline-shift {
font-style: italic;
font-size: 2rem;
span:first-child {
border-bottom: 6px solid gold;
position: relative;
top: -8px;
color: royalblue;
}
span:last-child {
color: gold;
border-top: 6px solid royalblue;
position: relative;
top: 8px;
left: -2px;
}
}
#forbidden-frutiger {
text-decoration: underline overline 10px crimson;
font-weight: 900;
font-variant: small-caps;
font-size: 2em;
}
#tragic-sans {
font-family: cursive;
text-transform: lowercase;
&::after {
content: '🥲';
}
}
#monsters-of-rockwell {
font-size: 2.5rem;
font-family: "Roboto Flex",
sans-serif;
font-optical-sizing: auto;
font-weight: 100;
font-style: normal;
font-variation-settings:
"wdth" 25,
/* lowercase height */
"YTLC" 427,
/* uppercase height */
"YTUC" 760;
span:nth-child(2n) {
font-size: 50%;Review and Recap
In this exercise, we used CSS’ layout and typography features to lay out a poster advertising a musical festival.