Pages Medium
Restaurant Menu Page (Editorial)
Editorial, printable two-column menu page — dotted-leader prices, course separators, wine pairings sidebar, allergen legend, and @media print styles for an A4 PDF.
Open in Lab
MCP
html css vanilla-js
Targets: JS HTML
Code
:root {
--cream: #f5f0e8;
--cream-2: #ece4d4;
--bone: #faf7f1;
--terracotta: #c1714a;
--terracotta-d: #a05a38;
--forest: #2d4a3e;
--forest-d: #1e3329;
--gold: #c9a84c;
--gold-light: #e6c97a;
--ink: #2c1a0e;
--ink-2: #4a3828;
--warm-gray: #7a6a58;
--success: #4f7a3a;
--danger: #b3432a;
--warning: #d99020;
--font-display: "Playfair Display", Georgia, serif;
--font-body: "Inter", system-ui, sans-serif;
--font-mono: "JetBrains Mono", ui-monospace, monospace;
--r-sm: 6px;
--r-md: 10px;
--r-lg: 16px;
--shadow-1: 0 1px 2px rgba(44, 26, 14, 0.08), 0 2px 6px rgba(44, 26, 14, 0.06);
--shadow-2: 0 8px 24px rgba(44, 26, 14, 0.12);
}
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: var(--font-body);
background: var(--cream-2);
color: var(--ink);
min-height: 100vh;
-webkit-font-smoothing: antialiased;
}
/* Topbar */
.topbar {
display: flex;
align-items: center;
gap: 16px;
padding: 14px 28px;
background: var(--bone);
border-bottom: 1px solid rgba(44, 26, 14, 0.08);
}
.brand {
font-family: var(--font-display);
font-weight: 800;
font-size: 1.1rem;
color: var(--ink);
text-decoration: none;
}
.meta {
font-size: 0.78rem;
color: var(--warm-gray);
}
.print-btn {
margin-left: auto;
background: var(--forest);
color: var(--bone);
border: none;
border-radius: 999px;
padding: 9px 14px 9px 12px;
font-family: inherit;
font-size: 0.84rem;
font-weight: 700;
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 6px;
}
.print-btn:hover {
background: var(--forest-d);
}
/* Paper */
.paper {
padding: 36px 24px 64px;
display: flex;
justify-content: center;
}
.menu {
width: 100%;
max-width: 880px;
background: var(--bone);
padding: 56px 64px;
border: 1px solid rgba(44, 26, 14, 0.1);
box-shadow: var(--shadow-2);
position: relative;
color: var(--ink);
}
.menu::before,
.menu::after {
content: "";
position: absolute;
left: 50%;
width: 80px;
height: 1px;
background: var(--gold);
}
.menu::before {
top: 36px;
transform: translateX(-50%);
}
.menu::after {
bottom: 36px;
transform: translateX(-50%);
}
/* Header */
.menu-head {
text-align: center;
margin-bottom: 36px;
padding-bottom: 16px;
border-bottom: 1px solid rgba(44, 26, 14, 0.12);
}
.kicker {
font-size: 0.72rem;
text-transform: uppercase;
letter-spacing: 0.24em;
color: var(--terracotta);
font-weight: 700;
margin-bottom: 8px;
}
.menu-head h1 {
font-family: var(--font-display);
font-size: clamp(2.2rem, 5vw, 3.2rem);
font-weight: 500;
letter-spacing: -0.005em;
line-height: 1.05;
}
.menu-head h1 em {
font-style: italic;
color: var(--terracotta-d);
font-weight: 400;
}
.hours {
margin-top: 14px;
font-size: 0.86rem;
color: var(--warm-gray);
font-style: italic;
}
/* Two-column grid */
.menu-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 48px;
}
@media (max-width: 720px) {
.menu-grid {
grid-template-columns: 1fr;
gap: 24px;
}
.menu {
padding: 36px 30px;
}
}
/* Course */
.course {
margin-bottom: 32px;
}
.course-title {
font-family: var(--font-display);
font-size: 1.4rem;
font-weight: 700;
margin-bottom: 14px;
padding-bottom: 6px;
border-bottom: 1px solid var(--terracotta);
display: flex;
align-items: baseline;
gap: 10px;
}
.course-sub {
font-size: 0.74rem;
text-transform: uppercase;
letter-spacing: 0.14em;
color: var(--warm-gray);
font-weight: 600;
font-family: var(--font-body);
}
/* Dishes (dotted leaders) */
.dishes {
list-style: none;
}
.dishes > li {
display: grid;
grid-template-columns: auto 1fr auto;
gap: 6px;
align-items: baseline;
font-size: 0.98rem;
padding-top: 8px;
}
.dishes > li.dish-desc {
display: block;
font-size: 0.84rem;
font-style: italic;
color: var(--warm-gray);
padding-top: 2px;
padding-bottom: 6px;
border-bottom: 1px dashed rgba(44, 26, 14, 0.1);
margin-bottom: 4px;
}
.dish-name {
font-weight: 600;
color: var(--ink);
display: inline-flex;
align-items: baseline;
gap: 6px;
}
.dish-leader {
border-bottom: 1px dotted rgba(44, 26, 14, 0.4);
min-width: 24px;
margin: 0 4px 4px;
height: 0;
}
.dish-price {
font-family: var(--font-mono);
font-weight: 700;
font-size: 0.94rem;
color: var(--terracotta-d);
}
.dish-price::before {
content: "$";
color: var(--warm-gray);
margin-right: 1px;
font-weight: 500;
}
/* Tags */
.tags {
display: inline-flex;
gap: 3px;
}
.tag {
display: inline-grid;
place-items: center;
font-family: var(--font-mono);
font-size: 0.6rem;
font-weight: 700;
width: 18px;
height: 18px;
border-radius: 999px;
background: var(--cream-2);
color: var(--ink-2);
letter-spacing: -0.02em;
}
.tag-star {
background: var(--gold);
color: var(--ink);
}
/* Tasting pull-out */
.tasting {
margin-top: 12px;
margin-bottom: 36px;
background: var(--forest);
color: var(--bone);
border-radius: var(--r-md);
padding: 26px 28px;
}
.tasting-kicker {
font-size: 0.72rem;
letter-spacing: 0.18em;
text-transform: uppercase;
font-weight: 700;
color: var(--gold-light);
margin-bottom: 8px;
}
.tasting h3 {
font-family: var(--font-display);
font-size: 1.5rem;
font-weight: 500;
letter-spacing: -0.005em;
line-height: 1.2;
}
.tasting-desc {
margin-top: 10px;
font-size: 0.92rem;
color: rgba(250, 247, 241, 0.85);
}
.tasting-meta {
margin-top: 14px;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 14px;
}
.tasting-meta div {
display: flex;
flex-direction: column;
gap: 2px;
}
.tasting-meta dt {
font-size: 0.66rem;
letter-spacing: 0.14em;
text-transform: uppercase;
color: var(--gold-light);
font-weight: 700;
}
.tasting-meta dd {
font-size: 0.92rem;
font-weight: 600;
color: var(--bone);
}
.tasting-meta dd.m {
font-family: var(--font-mono);
}
@media (max-width: 720px) {
.tasting-meta {
grid-template-columns: 1fr;
}
}
/* Bottom: wine + legend */
.bottom {
display: grid;
grid-template-columns: 1.4fr 1fr;
gap: 32px;
padding-top: 16px;
border-top: 1px solid rgba(44, 26, 14, 0.12);
}
.bottom h2 {
font-family: var(--font-display);
font-size: 1.2rem;
font-weight: 700;
margin-bottom: 12px;
border-bottom: 1px solid var(--terracotta);
padding-bottom: 6px;
}
.wine .dishes > li {
font-size: 0.9rem;
}
.wine-note,
.legend-note {
margin-top: 12px;
font-size: 0.78rem;
color: var(--warm-gray);
font-style: italic;
}
.legend ul {
list-style: none;
display: flex;
flex-direction: column;
gap: 6px;
}
.legend li {
display: flex;
align-items: center;
gap: 10px;
font-size: 0.88rem;
color: var(--ink-2);
}
@media (max-width: 720px) {
.bottom {
grid-template-columns: 1fr;
gap: 20px;
}
}
/* Foot */
.menu-foot {
margin-top: 36px;
text-align: center;
font-size: 0.76rem;
color: var(--warm-gray);
border-top: 1px solid rgba(44, 26, 14, 0.12);
padding-top: 18px;
}
.foot-brand {
margin-top: 6px;
font-family: var(--font-display);
font-weight: 700;
font-size: 0.88rem;
color: var(--ink-2);
letter-spacing: 0.04em;
}
/* Print */
@media print {
body {
background: white;
}
.no-print {
display: none !important;
}
.paper {
padding: 0;
}
.menu {
box-shadow: none;
border: none;
max-width: 100%;
padding: 18mm 14mm;
}
.tasting {
page-break-inside: avoid;
}
.course {
page-break-inside: avoid;
}
}document.getElementById("printBtn").addEventListener("click", () => {
window.print();
});<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,500;0,700;0,800;1,400;1,500&family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@500;600;700&display=swap"
/>
<link rel="stylesheet" href="style.css" />
<title>Carta · Casa Olivar</title>
</head>
<body>
<header class="topbar no-print">
<a class="brand" href="#">Casa Olivar</a>
<span class="meta">Carta · Spring menu · v. 12 May 2026</span>
<button class="print-btn" type="button" id="printBtn">
<svg viewBox="0 0 24 24" width="14" height="14" aria-hidden="true">
<path
d="M6 9V3h12v6M6 18H4a1 1 0 0 1-1-1v-5a1 1 0 0 1 1-1h16a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1h-2M6 14h12v7H6z"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linejoin="round"
/>
</svg>
Print menu
</button>
</header>
<main class="paper">
<article class="menu">
<header class="menu-head">
<p class="kicker">Casa Olivar</p>
<h1>Carta de la <em>primavera</em></h1>
<p class="hours">
Dinner · Tuesday – Sunday · 19:00 – 23:30 · Tasting menu by
reservation only
</p>
</header>
<div class="menu-grid">
<!-- Left column -->
<section>
<section class="course">
<h2 class="course-title">
Para empezar <span class="course-sub">to start</span>
</h2>
<ul class="dishes">
<li>
<span class="dish-name">Pan de masa madre</span>
<span class="dish-leader"></span>
<span class="dish-price">8</span>
</li>
<li class="dish-desc">
Sourdough baked each morning, smoked olive oil, Maldon salt.
</li>
<li>
<span class="dish-name">
Burrata huerta
<span class="tags"><span class="tag" title="Vegetarian">V</span><span class="tag" title="Contains dairy">D</span></span>
</span>
<span class="dish-leader"></span>
<span class="dish-price">16</span>
</li>
<li class="dish-desc">
Heirloom tomato, garden basil, aged balsamic, focaccia crumble.
</li>
<li>
<span class="dish-name">
Pulpo a la brasa
<span class="tags"><span class="tag" title="Gluten-free">GF</span></span>
</span>
<span class="dish-leader"></span>
<span class="dish-price">19</span>
</li>
<li class="dish-desc">
Charred octopus, smoked paprika potato, salsa verde.
</li>
<li>
<span class="dish-name">Croquetas de jamón</span>
<span class="dish-leader"></span>
<span class="dish-price">14</span>
</li>
<li class="dish-desc">
Iberico ham croquettes, six pieces, lemon aioli.
</li>
<li>
<span class="dish-name">
Ensalada de huerta
<span class="tags"><span class="tag" title="Vegan">VG</span><span class="tag" title="Gluten-free">GF</span></span>
</span>
<span class="dish-leader"></span>
<span class="dish-price">13</span>
</li>
<li class="dish-desc">
Garden lettuces, radish, soft herbs, lemon-shallot vinaigrette.
</li>
</ul>
</section>
<section class="course">
<h2 class="course-title">
Pastas y arroces <span class="course-sub">made in-house</span>
</h2>
<ul class="dishes">
<li>
<span class="dish-name">Pappardelle al ragú de cordero</span>
<span class="dish-leader"></span>
<span class="dish-price">24</span>
</li>
<li class="dish-desc">
Hand-cut pasta, slow-braised lamb shoulder, gremolata.
</li>
<li>
<span class="dish-name">
Risotto de hongos
<span class="tags"><span class="tag" title="Vegetarian">V</span></span>
</span>
<span class="dish-leader"></span>
<span class="dish-price">26</span>
</li>
<li class="dish-desc">
Carnaroli rice, wild mushrooms, brown butter, aged parmesan.
</li>
<li>
<span class="dish-name">Spaghetti alle vongole</span>
<span class="dish-leader"></span>
<span class="dish-price">28</span>
</li>
<li class="dish-desc">
Clams, white wine, parsley, garlic, breadcrumbs.
</li>
</ul>
</section>
</section>
<!-- Right column -->
<section>
<section class="course">
<h2 class="course-title">
Del fuego <span class="course-sub">from the hearth</span>
</h2>
<ul class="dishes">
<li>
<span class="dish-name">
Ribeye 14oz
<span class="tags"><span class="tag" title="Gluten-free">GF</span><span class="tag tag-star" title="Signature">★</span></span>
</span>
<span class="dish-leader"></span>
<span class="dish-price">48</span>
</li>
<li class="dish-desc">
Dry-aged 28 days, bone marrow butter, house chimichurri.
</li>
<li>
<span class="dish-name">
Branzino entero
<span class="tags"><span class="tag" title="Gluten-free">GF</span></span>
</span>
<span class="dish-leader"></span>
<span class="dish-price">38</span>
</li>
<li class="dish-desc">
Whole roasted sea bass, fennel, preserved lemon, herb oil.
</li>
<li>
<span class="dish-name">Pollo al carbón</span>
<span class="dish-leader"></span>
<span class="dish-price">28</span>
</li>
<li class="dish-desc">
Half free-range chicken, garlic confit, herb salad.
</li>
<li>
<span class="dish-name">Costilla de cordero</span>
<span class="dish-leader"></span>
<span class="dish-price">42</span>
</li>
<li class="dish-desc">
Lamb ribs, honey-mint glaze, charred onion.
</li>
</ul>
</section>
<section class="course">
<h2 class="course-title">
Postres <span class="course-sub">made in-house</span>
</h2>
<ul class="dishes">
<li>
<span class="dish-name">
Tarta de queso quemada
<span class="tags"><span class="tag tag-star" title="Signature">★</span></span>
</span>
<span class="dish-leader"></span>
<span class="dish-price">11</span>
</li>
<li class="dish-desc">
Basque burnt cheesecake, salted caramel, sea salt.
</li>
<li>
<span class="dish-name">Olive oil cake</span>
<span class="dish-leader"></span>
<span class="dish-price">10</span>
</li>
<li class="dish-desc">
Citrus olive oil cake, crème fraîche, candied orange.
</li>
<li>
<span class="dish-name">
Chocolate ganache
<span class="tags"><span class="tag" title="Gluten-free">GF</span></span>
</span>
<span class="dish-leader"></span>
<span class="dish-price">12</span>
</li>
<li class="dish-desc">
Bittersweet dark chocolate, hazelnut praline, espresso ice.
</li>
</ul>
</section>
</section>
</div>
<!-- Tasting menu pull-out -->
<aside class="tasting">
<p class="tasting-kicker">Tasting menu</p>
<h3>
Seven courses, three hours, one olive tree.
</h3>
<p class="tasting-desc">
A curated seven-course progression from garden to hearth to dessert,
with three wine pairings from the natural list. Tuesday – Thursday,
booked at least 24 h ahead.
</p>
<dl class="tasting-meta">
<div><dt>Tasting</dt><dd class="m">$96 per guest</dd></div>
<div><dt>+ Pairings</dt><dd class="m">$54 per guest</dd></div>
<div><dt>Whole table</dt><dd>Yes — minimum 2</dd></div>
</dl>
</aside>
<!-- Wine + legend grid -->
<section class="bottom">
<article class="wine">
<h2>Wine — by the glass</h2>
<ul class="dishes">
<li>
<span class="dish-name">Tinto natural · Bierzo · Mencía 2022</span>
<span class="dish-leader"></span>
<span class="dish-price">12</span>
</li>
<li>
<span class="dish-name">Blanco · Rías Baixas · Albariño 2023</span>
<span class="dish-leader"></span>
<span class="dish-price">11</span>
</li>
<li>
<span class="dish-name">Vermut casa · on tap</span>
<span class="dish-leader"></span>
<span class="dish-price">9</span>
</li>
<li>
<span class="dish-name">Sherry · Manzanilla en rama</span>
<span class="dish-leader"></span>
<span class="dish-price">10</span>
</li>
</ul>
<p class="wine-note">
Full 140-bottle list available — ask Iria.
</p>
</article>
<article class="legend">
<h2>Legend</h2>
<ul>
<li><span class="tag">V</span> Vegetarian</li>
<li><span class="tag">VG</span> Vegan</li>
<li><span class="tag">GF</span> Gluten-free</li>
<li><span class="tag">D</span> Contains dairy</li>
<li><span class="tag tag-star">★</span> Signature dish</li>
</ul>
<p class="legend-note">
Allergies? Tell your server — most dishes can be adapted with 10
minutes' notice.
</p>
</article>
</section>
<footer class="menu-foot">
<p>
Prices in USD · 8.25% tax not included · 10% service on parties
of 6+
</p>
<p class="foot-brand">Casa Olivar · 42 Calle del Olivar · Madrid</p>
</footer>
</article>
</main>
<script src="script.js"></script>
</body>
</html>Restaurant Menu Page
The editorial menu — the one diners read at the table or print as a take-home PDF. Two-column layout with classic dotted-leader prices, course separators, a wine-pairing sidebar, an allergen legend, and a “Tasting menu · 7 courses” pull-out box.
@media print strips the sticky header and CTA so a single Cmd/Ctrl+P produces a clean two-page A4. Distinct from rest-menu-carta (web-first browse) and rest-menu-qr (mobile-first).