Building a restaurant landing page
A landing page is a one-page site that tells about one thing and leads to one action. For a restaurant that action is booking a table. Let us build such a page from the course elements without writing a single line of our own CSS: only Bulma classes and a short script for the burger.
The page plan
| Part | Bulma elements |
|---|---|
| Header | navbar with a burger |
| Banner | hero is-primary is-medium |
| Features | columns and has-text-centered |
| Menu | grid with card cards |
| Booking | box, field, control, columns |
| Footer | footer |
Each part except the header is a separate section with a container inside, as in the page skeleton lesson.
The whole page
Create an index.html file — or replace the markup in the Vite project:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@1.0.4/css/bulma.min.css">
<nav class="navbar" aria-label="Main menu">
<div class="container">
<div class="navbar-brand">
<a class="navbar-item has-text-weight-bold" href="#">Trattoria Oliva</a>
<a role="button" class="navbar-burger" aria-label="Open menu" aria-expanded="false" data-target="nav">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
</div>
<div class="navbar-menu" id="nav">
<div class="navbar-end">
<a class="navbar-item" href="#menu">Menu</a>
<a class="navbar-item" href="#booking">Booking</a>
</div>
</div>
</div>
</nav>
<section class="hero is-primary is-medium">
<div class="hero-body">
<div class="container has-text-centered">
<h1 class="title is-1">Trattoria Oliva</h1>
<p class="subtitle">Handmade pasta and bread from our own oven</p>
<a class="button is-dark is-medium" href="#booking">Book a table</a>
</div>
</div>
</section>
<section class="section">
<div class="container">
<div class="columns has-text-centered">
<div class="column">
<p class="title is-4">Since 2012</p>
<p>We cook from Tuscan recipes.</p>
</div>
<div class="column">
<p class="title is-4">Fresh pasta</p>
<p>We roll the dough every morning.</p>
</div>
<div class="column">
<p class="title is-4">Terrace</p>
<p>12 outdoor tables in summer.</p>
</div>
</div>
</div>
</section>
<section class="section has-background-light" id="menu">
<div class="container">
<h2 class="title">Menu</h2>
<div class="grid is-col-min-10">
<div class="cell card">
<div class="card-image">
<figure class="image is-16by9"><img src="/media/photo-800x500.jpg" alt="Carbonara"></figure>
</div>
<div class="card-content">
<p class="title is-5">Carbonara <span class="tag is-warning">Popular</span></p>
<p>€12</p>
</div>
</div>
<div class="cell card">
<div class="card-image">
<figure class="image is-16by9"><img src="/media/photo-800x500.jpg" alt="Risotto"></figure>
</div>
<div class="card-content">
<p class="title is-5">Risotto</p>
<p>€14</p>
</div>
</div>
<div class="cell card">
<div class="card-image">
<figure class="image is-16by9"><img src="/media/photo-800x500.jpg" alt="Tiramisu"></figure>
</div>
<div class="card-content">
<p class="title is-5">Tiramisu</p>
<p>€7</p>
</div>
</div>
</div>
</div>
</section>
<section class="section" id="booking">
<div class="container is-max-tablet">
<div class="box">
<h2 class="title is-4">Booking</h2>
<div class="columns">
<div class="column field">
<label class="label" for="b-name">Name</label>
<div class="control"><input class="input" id="b-name" placeholder="Anna"></div>
</div>
<div class="column field">
<label class="label" for="b-date">Date</label>
<div class="control"><input class="input" id="b-date" type="date"></div>
</div>
</div>
<button class="button is-primary is-fullwidth">Book</button>
</div>
</div>
</section>
<footer class="footer">
<p class="has-text-centered">Trattoria Oliva · 12 Garden Street · daily 12:00–23:00</p>
</footer>
<script>
document.querySelectorAll('.navbar-burger').forEach((burger) => {
burger.addEventListener('click', () => {
const isOpen = burger.classList.toggle('is-active');
document.getElementById(burger.dataset.target).classList.toggle('is-active', isOpen);
burger.setAttribute('aria-expanded', String(isOpen));
});
});
</script>The preview shows a whole page: a white header with a burger, a turquoise banner with a button, three features (stacked in the narrow preview, in a row on a wide screen), a grey section with dish cards, a form in a white box and a footer. The header links scroll the page to the sections with id="menu" and id="booking".
What matters here
- The header is wrapped in a
container, so on a wide screen the logo and links line up with the edges of the rest of the content. - The grid cells are the cards themselves (
cell card): no extra wrapper is needed. - The form is limited by
container is-max-tabletso the fields do not stretch across the whole monitor. - The banner button is
is-dark: on a turquoise background it stands out more than another turquoise one would.
You can now restyle the page with the CSS variables or Sass lessons: the classes stay the same.
Common mistake
Adding your own styles for small things that have a helper: style="text-align: center", style="margin-top: 24px". Such rules are scattered through the markup and hard to find. Look for a helper first — has-text-centered, mt-5 — and keep your own CSS for what Bulma does not have.