MBL
Frontend / ЛР1: разбор многостраничного HTML-сайта на примере лендинга керамики
Frontend вводный

ЛР1: разбор многостраничного HTML-сайта на примере лендинга керамики

htmlsemanticsitmo

Разбор реальной ЛР1 курса "Средства гипертекстовой разметки документа": сайт ремесленного бренда керамики из четырёх HTML-страниц, свёрстанных только тегами, без единой строки CSS или JavaScript. Каждый тег выбран осознанно под конкретную задачу разметки — ниже построчный разбор всех четырёх файлов.

Зачем несколько файлов, а не один

lab1/
├── index.html     — главная: промо, витрина, новости рассылки
├── catalog.html   — каталог товаров
├── blog.html      — блог
├── about.html     — история бренда, форма связи, карта
└── assets/        — общие картинки для всех страниц

Это классическая многостраничная схема (MPA) — самый простой способ разбить сайт на разделы средствами одного HTML, без JavaScript-роутера. Каждый .html-файл — полностью самостоятельный документ: свои <head>, свой <title>, свой <body>. Переходы между страницами — обычные ссылки <a href="catalog.html">, браузер честно загружает новый файл с сервера при каждом клике.

Из этого следует важное практическое ограничение: шапку и подвал приходится дублировать в каждом файле — не существует способа "подключить" общий кусок HTML в другой HTML без сервера или инструмента сборки (в отличие от <link> для CSS). Проверить это легко: <header> и <footer> во всех четырёх файлах лабы побайтово одинаковы, кроме одной детали — ссылки навигации не помечают текущую страницу никак (class="active" было бы CSS-решением, а его в лабе нет), так что определить "где я сейчас" можно только по <title> вкладки.

Заголовок документа: doctype, html, head

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Ceramic Soul, catalog</title>
</head>

<!DOCTYPE html> — не HTML-элемент, а декларация для браузера: "рендери эту страницу в современном стандартном режиме", а не в устаревшем quirks-режиме, унаследованном от HTML 4. Без неё браузер по-прежнему пытается что-то показать, но с непредсказуемыми расхождениями в раскладке между браузерами — сама декларация ничего не рендерит и не закрывается.

Атрибут lang="en" на <html> — язык содержимого документа, не интерфейса браузера. Здесь en, потому что текст сайта на английском, а не потому что так короче написать. Скринридеры используют это значение, чтобы выбрать правильное произношение.

<title> у каждой из четырёх страниц свой ("handmade ceramics", "catalog", "blog", "about") — именно <title>, а не какой-то заголовок в <body>, определяет то, что видно на вкладке браузера и в закладках, и то, по чему проще всего отличить один открытый файл лабы от другого.

<head> во всех файлах лабы намеренно минимальный — только charset и title, без <meta name="description">, без иконки, без подключения шрифтов и стилей: задание ЛР1 — чистая семантика, CSS и оптимизации появятся в следующих лабораторных.

Общая шапка: логотип и навигация

<header>
    <a href="index.html">
        <img src="assets/logo.png" alt="Ceramic Soul logo">
    </a>
    <nav>
        <ul>
            <li><a href="catalog.html">Catalog</a></li>
            <li><a href="blog.html">Blog</a></li>
            <li><a href="about.html">About</a></li>
        </ul>
    </nav>
</header>

Логотип — картинка, обёрнутая в ссылку на главную. У <img> обязателен alt — текстовая альтернатива на случай, если картинка не загрузилась или её читает голосовой ассистент. alt="Ceramic Soul logo" описывает смысл изображения, а не файл.

<nav> оборачивает именно навигационные ссылки — семантика тега говорит "это один из значимых навигационных блоков документа". Ссылки — относительные пути (catalog.html, а не /catalog.html и тем более не полный URL): все четыре файла лежат рядом в одной папке, поэтому браузер резолвит catalog.html относительно текущего открытого файла, и сайт одинаково работает что при открытии напрямую с диска (file://), что после выкладки на любой хостинг — абсолютные пути с ведущим слэшом на локальном диске сработали бы неправильно.

Внутри <nav> — <ul>, а не <ol>: порядок пунктов меню (Catalog / Blog / About) не несёт смысловой нагрузки, список неупорядоченный.

Главная (index.html): промо, витрина, рассылка

<section>
    <h1>Make your dream come true or decorate your home</h1>
    <img src="assets/ceramic-vase.png" alt="Handmade ceramic vase">
    <p><strong>Ceramic Soul</strong> makes <em>handmade</em> ceramics for every home.</p>
    <p><a href="catalog.html">Shop now</a></p>
</section>

<h1> — единственный заголовок первого уровня на странице. Дальше по документу используются только <h2> и <h3> — иерархия не перескакивает уровни вниз без причины.

<strong> и <em> — смысловое, а не визуальное выделение. <strong> означает "это важно по содержанию" (название бренда), <em> — "здесь логическое ударение при чтении вслух". У обоих есть визуально идентичные, но не семантические аналоги — <b> и <i> — их используют, когда нужен просто другой шрифт без придания тексту важности.

<article>
    <h3>Our workshop</h3>
    <img src="assets/workshop.png" alt="Workshop table with clay and tools">
    <p>At <strong>Ceramic Soul</strong> workshop, we don't just craft ceramics...</p>
    <ol>
        <li>Choose your clay and tools</li>
        <li>Shape the piece on the wheel</li>
        <li>Fire and glaze it in the kiln</li>
    </ol>
</article>

<blockquote>
    <p>Every piece that leaves our studio carries a bit of our story...</p>
    <cite>From the Ceramic Soul story, "Where It All Began"</cite>
</blockquote>

<article> — тег для контента, который имел бы смысл сам по себе, будучи вырванным из страницы. Описания магазина и мастерской именно такие: два независимых самодостаточных блока со своим подзаголовком <h3>.

Внутри — <ol>, нумерованный список: порядок здесь принципиален, нельзя "обжечь изделие в печи" раньше, чем "слепить на круге" — <ol> семантически кодирует именно это, а не просто "хочу циферки вместо точек".

<blockquote> — блочная цитата. <cite> внутри — атрибуция источника (по спецификации это название цитируемой работы, здесь — заголовок истории бренда со страницы about.html, а не имя человека). Если бы нужно было процитировать слово посреди предложения — использовался бы инлайн-тег <q>, а не блочный <blockquote>.

<section>
    <h2>Check out our works</h2>
    <ul>
        <li><img src="assets/tea-1.png" alt="Handmade ceramic tea set, piece 1"></li>
        <li><img src="assets/tea-2.png" alt="Handmade ceramic tea set, piece 2"></li>
        <li><img src="assets/tea-3.png" alt="Handmade ceramic tea set, piece 3"></li>
    </ul>
    <p>Limited collection price: <del>4990 rubliks</del> <ins>3990 rubliks</ins></p>
</section>

Галерея — снова <ul> (порядок фотографий друг относительно друга не несёт смысла), каждая картинка в своём <li>. Alt-тексты не дублируются дословно — у каждого добавлен порядковый номер, чтобы пользователь скринридера мог отличить один элемент списка от другого.

<del> и <ins> — смысловые теги правки документа: "этот фрагмент удалён из текста", "этот фрагмент добавлен взамен". Визуально браузер по умолчанию рисует <del> зачёркнутым, а <ins> — подчёркнутым, но выбирают эти теги не ради эффекта зачёркивания (для этого есть <s> без смысловой нагрузки), а когда факт правки — часть сообщения: старая цена, вычеркнутая в пользу новой.

На главной странице нет блока "Get in touch" — форма обратной связи есть только на about.html; на главной вместо неё — блок подписки на новости в <aside>:

<aside>
    <h2>Newsletter</h2>
    <p>Keep up to date with news and promotions.</p>
    <form>...</form>
</aside>

<aside> — контент, косвенно связанный с основным потоком страницы: если убрать блок подписки целиком, смысл главной страницы не пострадает. Изначально форма связи была продублирована и на главной, и на странице "about" — дублирование одной и той же формы на двух страницах не несёт пользы ни читателю, ни разметке, поэтому с главной её убрали, оставив единственным источником about.html.

Каталог (catalog.html): карточки товара

<section>
    <h1>Our pottery</h1>

    <article>
        <img src="assets/catalog-1.png" alt="Terracotta Whisper ceramic piece">
        <h2>Terracotta Whisper</h2>
        <p>19.99 rubliks</p>
    </article>
    ...
</section>

Каждый товар — свой <article>: карточка товара самодостаточна и имела бы смысл, будучи вырезанной из каталога и вставленной, например, в письмо рассылки. <h1> здесь — уже не "Make your dream...", а "Our pottery": на каждой странице сайта свой единственный <h1>, соответствующий именно её теме, а не сквозной на весь сайт.

Блог (blog.html): те же принципы, другой контент

<article>
    <img src="assets/blog-1.png" alt="Pottery Secrets article cover">
    <h2>Pottery Secrets</h2>
    <p>Discover the timeless art of pottery...</p>
</article>

Структура зеркалит каталог: <article> на каждую самостоятельную единицу контента (здесь — статью), картинка с описательным alt, <h2> — заголовок конкретной статьи. Разница в семантике, а не в наборе тегов: один и тот же паттерн "картинка + заголовок + текст в своём article" подходит и для товара, и для статьи, потому что оба — самодостаточные единицы контента.

О бренде (about.html): текст, форма, карта

<section>
    <h2>Get in touch</h2>
    <form>
        <p>
            <label for="name">Name</label>
            <input type="text" id="name" name="name">
        </p>
        ...
        <button type="button">Send request</button>
    </form>
</section>

Каждое поле формы — пара <label>+<input>, связанных через for/id. Это не декоративная подпись рядом с полем, а программная связь: клик по тексту "Name" переносит фокус в поле, а скринридер озвучивает текст <label>, попав на связанный <input>. type="email" у соответствующего поля включает базовую браузерную валидацию формата и на мобильных переключает раскладку клавиатуры.

Кнопка отправки здесь — type="button", а не type="submit": в HTML без JavaScript у кнопки типа button нет встроенного поведения — клик по ней ничего не делает сам по себе, в отличие от submit, который бы попытался отправить форму как HTTP-запрос. Для чисто HTML-лабы, где форма не подключена ни к какому обработчику, это осознанный выбор — не создавать видимость рабочей отправки там, где её нет.

<section>
    <h2>Find us</h2>
    <img src="assets/map.png" alt="Map showing Clay Space Ceramic Center location">
    <p>Clay Space Ceramic Center, 275 Calyer St, Brooklyn, NY 11222</p>
</section>

Блок с местоположением сделан как обычная картинка со скриншотом карты и подписью-адресом, а не как встроенная интерактивная карта через <iframe>. Оба варианта технически возможны и одинаково укладываются в набор тегов ЛР1 (<iframe> был на слайде лекции про видео/аудио/встраивание), но статичный скриншот проще и не тянет за собой внешний интерактивный виджет ради одной лабораторной.

Итог: что осталось за кадром сознательно

Ни в одном из четырёх файлов нет класса, атрибута style, <link rel="stylesheet"> или <script> — не потому что про них не знали, а потому что задание ЛР1 явно требует чистую HTML-семантику без оформления и поведения: то, "что это такое", без того, "как это выглядит" и "что происходит по клику". Разбиение на четыре страницы уже сейчас закладывает структуру, поверх которой на следующих лабораторных появится общий CSS (тогда <header>/<footer> в разных файлах должны будут выглядеть идентично) и, возможно, JavaScript.

Самопроверка 0 / 6
Понимаю, что doctype — не HTML-тег, а декларация режима рендеринга браузера
Могу объяснить, почему для блока с товарами выбран section, а не div
Понимаю разницу между ul и ol и умею выбрать нужный по смыслу, а не "на глаз"
Знаю, зачем у label атрибут for должен совпадать с id поля
Понимаю, что del и ins — не про зачёркнутый текст визуально, а про смысл правки
Понимаю, зачем сайт разбит на несколько html-файлов, а не собран в один
Как усвоено?