Модуль 1: HTML
В этом модуле вы освоите базовую разметку HTML: узнаете, как устроен каркас документа, какие теги бывают, как использовать атрибуты, семантические элементы и создавать формы.
Подготовительный этап (0.1–0.2): установка редактора (VS Code), браузеров (Chrome/Firefox), Git и GitHub, публикация «Hello, World!» на GitHub Pages.
Введение в HTML. Базовый каркас документа
Представьте, что вы строите дом. HTML — это как чертёж и каркас здания. Он не красит стены (это делает CSS) и не добавляет электричество (это JavaScript), но без него не было бы ни стен, ни комнат, ни самого дома. HTML (HyperText Markup Language) — это язык разметки, который создаёт структуру веб-страницы. Он не программирует логику, а просто говорит браузеру: "здесь заголовок", "здесь абзац", "здесь кнопка". Основные строительные блоки HTML — это элементы (теги) и их атрибуты.
Что такое HTML и зачем он нужен
Если бы интернет был книгой, HTML был бы её содержанием и структурой. Он определяет, где находится каждая глава, где начинается новый абзац, какие слова важные (заголовки), а какие обычные (текст). Браузер читает этот "чертёж" и превращает его в красивую страницу, которую вы видите на экране. Без HTML веб-страница просто не существовала бы — это фундамент, на котором строится всё остальное.
Давайте разберёмся с основными понятиями на простых примерах:
- Элемент — это как контейнер с содержимым. Представьте коробку с подарком:
<p>— это открывающая крышка,Текст абзаца— это сам подарок, а</p>— закрывающая крышка. Получается:<p>Текст абзаца</p>. Внутри элемента может быть текст, другие элементы (как матрёшка) или он может быть пустым. - Атрибут — это как наклейка на коробке, которая говорит: "хрупкое", "верх не переворачивать" или "адрес получателя". Например, в ссылке
<a href="/about" target="_blank">О нас</a>атрибутhref— это адрес, куда ведёт ссылка, аtarget="_blank"— инструкция открыть её в новой вкладке. Без атрибутов элементы были бы "слепыми" — они бы знали, что это ссылка, но не знали бы, куда она ведёт. - Структура документа — это как паспорт и адрес дома. Каждый HTML-документ должен иметь обязательные элементы:
<!DOCTYPE html>говорит браузеру "это современный HTML",<html>— корневой контейнер (весь документ),<head>— "служебная информация" (метаданные, стили, скрипты),<body>— "видимое содержимое" (то, что видит пользователь). Без этой структуры браузер не поймёт, что делать с вашим кодом.
Как браузер превращает код в страницу: магия DOM
Вы написали HTML-код, нажали F5, и на экране появилась красивая страница. Что произошло за эти миллисекунды? Браузер проделал удивительную работу, превратив ваш текст в визуальную реальность. Давайте заглянем "под капот":
- Парсинг — чтение кода — браузер читает ваш HTML-код, как человек читает книгу, но со скоростью света. Он анализирует каждую строку, распознаёт теги, атрибуты и содержимое. Всё это преобразуется в дерево DOM (Document Object Model) — особую структуру данных, похожую на генеалогическое древо.
- Построение DOM — создание структуры — представьте семейное дерево:
<html>— это прародитель,<body>— его ребёнок,<div>— внук, а<p>внутри — правнук. Каждый элемент становится узлом этого дерева со своими атрибутами (как характеристики человека) и дочерними элементами (как дети). Это создаёт иерархию, которую браузер понимает. - Рендеринг — рисование на экране — теперь браузер берёт это дерево и "рисует" его на экране. Он смотрит на каждый элемент: "Это заголовок? Сделаю его большим и жирным. Это ссылка? Подчеркну и сделаю синим." CSS добавляет краски и стили, превращая чёрно-белую структуру в красочную страницу.
- Интерактивность — оживление — JavaScript может "шевелить ветками" этого дерева в реальном времени. Нажали кнопку? JavaScript добавил новый элемент в DOM. Ввели текст? DOM обновился. Всё это происходит без перезагрузки страницы — магия современного веба!
DOM — это не просто структура, это живой организм. Представьте, что DOM — это кукольный театр, а JavaScript — кукловод, который может двигать кукол, менять их костюмы и даже создавать новых персонажей прямо во время представления. Любые изменения в DOM мгновенно отражаются на экране — это и есть основа интерактивности современных сайтов.
Пустые элементы: теги-одиночки
Большинство HTML-элементов — это "контейнеры" с открывающим и закрывающим тегом. Но есть особые элементы, которые не могут содержать внутри себя ничего — они самодостаточные, как дверной звонок или выключатель. Их называют пустыми (void) элементами, и они не требуют закрывающего тега.
Почему они пустые? Потому что их "содержимое" — это не текст, а что-то другое: файл изображения, метаданные или просто действие (перенос строки). Вот основные "одиночки":
<br>— перенос строки. Как нажатие Enter в текстовом редакторе. Совет: используйте осторожно! Чаще лучше управлять отступами через CSS — это даёт больше контроля.<img>— изображение. Его содержимое — это сам файл картинки, а не текст. Поэтому тег самозакрывающийся:<img src="photo.jpg" alt="Описание">.<input>— поле ввода формы. Это как пустая коробочка, куда пользователь вводит данные. Само по себе поле не содержит текста — текст появляется, когда пользователь что-то печатает.<meta>— метаинформация о странице. Это "заметки на полях" для браузера и поисковиков. Они не видны пользователю, но очень важны для SEO.<link>— подключение внешних ресурсов. Как провод, который подключает CSS-файл или иконку сайта. Сам тег ничего не содержит, он просто указывает путь к файлу.<hr>— горизонтальная линия-разделитель. Визуально разделяет контент, как линия в тетради между темами.
Интересный факт: В HTML5 можно писать эти теги как <br> или <br /> — оба варианта валидны. Но если вы работаете с XHTML (более строгий стандарт), обязательно нужен слэш: <br />. Большинство современных разработчиков используют короткий вариант без слэша.
Глобальные атрибуты: универсальные инструменты
Представьте, что у вас есть набор универсальных инструментов, которые работают с любым элементом на странице. Это и есть глобальные атрибуты — они как швейцарский нож веб-разработчика. Их можно применить к любому тегу, и они всегда работают одинаково. Давайте познакомимся с самыми полезными:
id— это как паспорт элемента, его уникальное имя. Представьте класс в школе: у каждого ученика уникальный номер в журнале. Так и здесь —idдолжен быть единственным на странице. Используется для создания якорей (ссылок внутри страницы типа#section1), для JavaScript-селекторов и CSS. Важно помнить: если два элемента имеют одинаковыйid, браузер запутается — это как если бы у двух людей был один паспорт!class— это как ярлык или категория. В отличие отid, класс можно использовать многократно. Представьте наклейки: наклейка "важное" может быть на нескольких документах. Один элемент может иметь несколько классов через пробел:class="button primary large"— это элемент одновременно и кнопка, и основная, и большая. Очень удобно для стилизации!data‑*— это ваш личный "карман" для хранения информации. Можно создать любой атрибут видаdata-название="значение", напримерdata-user-id="123"илиdata-price="999". Это как заметки, которые вы приклеиваете к элементу. JavaScript может легко их прочитать:element.dataset.userId(обратите внимание: дефисы превращаются в camelCase). Очень полезно для передачи данных из HTML в JavaScript!aria‑*— это "переводчик" для людей с ограниченными возможностями. Скринридеры (программы, которые читают страницу вслух) используют эти атрибуты, чтобы понять, что происходит на странице. Например,aria-label="Закрыть меню"подскажет, что кнопка закрывает меню, даже если на ней только иконка. Делая сайт доступным, вы помогаете миллионам людей!hidden— это как невидимая шапка-невидимка. Элемент остаётся в коде (в DOM), но пользователь его не видит. Полезно, когда элемент должен быть скрыт по умолчанию, но может появиться при определённых условиях. В отличие отdisplay: noneв CSS, это семантический способ скрытия.title— это как подсказка в игре. При наведении курсора появляется маленькое окошко с дополнительной информацией. Полезно для уточнений, но помните: не все пользователи видят подсказки (особенно на мобильных), поэтому не кладите туда критически важную информацию.tabindex— это как номер в очереди для клавиатурной навигации. Когда пользователь нажимает Tab, фокус переходит от элемента к элементу.tabindex="0"— элемент в естественном порядке,tabindex="-1"— элемент пропускается при Tab, но может получить фокус программно. Осторожно: положительные значения (tabindex="1"и выше) — это как "пройти без очереди", они нарушают естественный порядок и могут запутать пользователей.lang— это как флаг страны для текста. Браузер, поисковики и скринридеры используют его, чтобы правильно обработать текст. Например,lang="ru"для русского илиlang="en"для английского. Это особенно важно для правильного произношения скринридерами и для SEO.contenteditable— это как превращение обычного текста в блокнот. Элемент становится редактируемым прямо на странице, как в Google Docs. Используется редко, в основном для WYSIWYG-редакторов (What You See Is What You Get — "что видишь, то и получаешь").
Пути к файлам: как найти нужный файл
Представьте, что вы в большом городе и вам нужно найти адрес. В HTML тоже есть "адреса" — пути к файлам. Когда вы хотите подключить картинку, стили или перейти на другую страницу, нужно указать, где этот файл находится. Есть три способа "навигации" по файловой структуре сайта, и каждый подходит для своих задач:
1. Абсолютные пути — полный адрес с индексом
Это как сказать: "Москва, улица Ленина, дом 10, квартира 5" — полный адрес от страны до квартиры. В вебе это выглядит так: https://site.ru/page или http://example.com/images/logo.png.
Когда это полезно: когда вы ссылаетесь на внешние сайты (другие домены), подключаете ресурсы с CDN (Content Delivery Network — сеть доставки контента), или когда нужно гарантировать, что путь точно не изменится.
Подводные камни: если вы решите сменить домен (например, с mysite.com на newsite.com), все абсолютные пути сломаются, и вам придётся искать и заменять их по всему сайту. Также они не работают, если вы просто открываете HTML-файл в браузере без сервера — браузер не знает, что такое "site.ru".
2. Относительные пути — "от того места, где я нахожусь"
Это как сказать: "иди на два квартала вперёд, потом поверни направо" — инструкция относительно вашего текущего положения. Браузер ищет файл, начиная от места, где находится текущий HTML-файл.
Примеры "навигации":
about.html— "файл в той же папке, где я нахожусь" (как сосед по лестничной площадке)images/logo.png— "зайди в папку images, там найдёшь logo.png" (как "спустись на этаж ниже")../img/cat.png— "поднимись на уровень выше (родительская папка), затем зайди в img" (две точки..означают "на уровень выше")../../css/styles.css— "поднимись на два уровня выше, затем зайди в css" (как "поднимись на два этажа")
Когда это удобно: для всех внутренних ссылок на вашем сайте. Это самый гибкий вариант для локальной разработки — вы можете перемещать папки, и пути будут работать, пока структура относительно друг друга не изменится.
Важный нюанс: относительные пути — это как маршрут от точки A до точки B. Если вы переместите точку A (ваш HTML-файл), маршрут может сломаться. Например, если файл был в /pages/about.html и ссылался на ../images/logo.png, а вы переместили его в /about.html, путь сломается.
3. Пути от корня сайта — "от главного входа"
Это как сказать: "от главного входа в здание иди в комнату 205" — всегда от одной фиксированной точки. Путь начинается со слэша /, что означает "корень сайта" (главная папка вашего сайта). Примеры: /images/icon.ico, /css/styles.css, /about.html.
Когда это идеально: когда файл всегда находится в одном и том же месте относительно корня сайта, независимо от того, на какой странице вы находитесь. Это самый надёжный вариант для продакшена (готового сайта).
Преимущества: пути не ломаются, когда вы перемещаете страницы по структуре сайта. Легко понять структуру — сразу видно, что /images/ — это папка с изображениями в корне.
Ограничение: не работают, если вы просто открываете HTML-файл двойным кликом в браузере (без запущенного сервера). Браузер не знает, что такое "корень сайта" без сервера. Но это не проблема, если вы используете локальный сервер для разработки (что и рекомендуется).
Практический совет от опытных разработчиков: Используйте пути от корня (/) для продакшена — это надёжнее. Для локальной разработки можно использовать относительные пути, если вам так удобнее. Многие современные сборщики (Webpack, Vite, Parcel) автоматически преобразуют относительные пути в правильные при сборке проекта, так что вы можете писать как удобно, а они всё исправят.
Экранирование специальных символов: когда символы "бунтуют"
Представьте ситуацию: вы хотите написать в тексте "<div>", но браузер видит это и думает: "О! Это HTML-тег, нужно его обработать!" И вместо текста на странице появляется пустой блок. Проблема? Да! Решение? Экранирование.
Некоторые символы в HTML имеют "магические" свойства — браузер воспринимает их как команды, а не как обычный текст. Чтобы показать эти символы как текст, нужно их "экранировать" — заменить на специальные коды, которые браузер понимает как "это просто символ, не команда".
Вот основные "бунтари" и как с ними справиться (HTML-сущности):
<или<→<(символ "меньше", открывающая скобка тега)>или>→>(символ "больше", закрывающая скобка тега)&или&→&(амперсанд, используется для начала сущности)"или"→"(двойная кавычка)'или'→'(одинарная кавычка, но можно использовать обычную) → неразрывный пробел (полезен для предотвращения переноса слов)©→©(символ копирайта)—→—(длинное тире)
<!-- Примеры использования -->
<p>Чтобы написать <div> в тексте, используйте &lt;div&gt;</p>
<p>Цена: 1000 ₽ (неразрывный пробел)</p>
<p>Компания © 2026</p>
Когда нужно экранировать — три главных случая:
- Показываете код как текст — например, в учебных материалах (как сейчас в этом курсе!), в документации или в комментариях. Если вы пишете статью "Как использовать тег <div>", вам нужно экранировать угловые скобки, иначе браузер попытается создать реальный div.
- Специальные символы в атрибутах — иногда в значении атрибута нужно использовать кавычки или другие специальные символы. Экранирование помогает браузеру понять, где заканчивается атрибут.
- Гарантия безопасности — когда вы не уверены, как браузер интерпретирует символ, лучше перестраховаться и экранировать. Особенно это важно при динамической вставке контента через JavaScript.
Хорошая новость: В большинстве случаев современные браузеры умные и правильно обрабатывают символы даже без экранирования. Но для "большой тройки" — <, > и & — экранирование обязательно, если они не являются частью разметки. Это как правило дорожного движения: можно не всегда следовать, но лучше следовать всегда, чтобы избежать проблем.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Моя первая страница</title>
<meta name="description" content="Краткое описание страницы" />
<link rel="icon" href="/images/icon.ico" type="image/x-icon" />
<link rel="stylesheet" href="/css/styles.css" />
</head>
<body>
<header><h1>О себе</h1></header>
<main>
<p>Привет! Это моя первая HTML‑страница.</p>
</main>
<footer>© 2025</footer>
<script src="/js/script.js"></script>
</body>
</html>
Важно: <meta name="viewport"> обеспечивает адаптивность. Атрибут lang="ru" у <html> помогает SEO и ассистивным технологиям.
Частые мета‑теги
<meta name="robots" content="index, follow" />
<meta name="author" content="Имя автора" />
<meta property="og:title" content="Заголовок для соцсетей" />
Практика
- Создайте
index.htmlс корректным доктайпом,lang,charset,viewport. - Подключите внешний CSS/JS, добавьте осмысленный
<title>иdescription.
Работа с текстовым контентом
Текст — это душа любого веб-сайта. Без текста даже самый красивый дизайн останется пустой оболочкой. Но просто написать текст недостаточно — нужно сделать его структурированным, понятным и доступным. Представьте книгу без глав, параграфов и абзацев — читать её было бы невозможно! Так и с веб-страницами: правильная структура текста критически важна для читаемости, SEO (чтобы поисковики понимали ваш контент) и доступности (чтобы люди с ограниченными возможностями могли легко навигироваться).
Заголовки: создаём иерархию, как в книге
HTML предоставляет вам шесть уровней заголовков — от <h1> (самый важный, как название книги) до <h6> (наименее важный, как подпункт в подразделе). Это как система заголовков в учебнике: сначала название главы (h1), потом разделы (h2), подразделы (h3) и так далее. Заголовки создают "скелет" документа — они помогают и людям, и поисковым системам понять структуру и важность информации.
Правила использования заголовков:
<h1>— главный заголовок страницы. Должен быть только один на странице. Обычно содержит название страницы или основную тему.<h2>— основные разделы страницы. Используйте для крупных тематических блоков.<h3>— подразделы внутриh2. Для более детального деления контента.<h4>— подпункты внутриh3. И так далее доh6.
Золотое правило: Не пропускайте уровни! Это как лестница — нельзя перепрыгнуть со второго этажа на четвёртый, минуя третий. Нельзя использовать h1, затем сразу h3, минуя h2. Представьте оглавление книги: сначала "Глава 1", потом "Раздел 1.1", затем "Подраздел 1.1.1" — всё по порядку. Правильная последовательность: h1 → h2 → h3 → h4... Это не просто формальность — нарушение иерархии сбивает с толку и людей, и поисковые системы.
<!-- Правильная структура заголовков -->
<h1>Главный заголовок страницы</h1>
<h2>Первый основной раздел</h2>
<h3>Подраздел первого раздела</h3>
<h2>Второй основной раздел</h2>
<h3>Подраздел второго раздела</h3>
<h4>Детали подраздела</h4>
Почему правильная иерархия заголовков — это не просто "хороший тон", а необходимость:
- SEO — дружба с поисковиками: Google и другие поисковые системы "читают" заголовки, чтобы понять структуру и важность контента. Правильная иерархия помогает вашему сайту лучше ранжироваться в поиске. Это как правильно оформленная научная работа — её легче понять и оценить.
- Доступность — помощь всем пользователям: скринридеры (программы для людей с нарушениями зрения) используют заголовки для навигации. Пользователь может "прыгать" от заголовка к заголовку, быстро находя нужный раздел. Представьте, что вы читаете книгу вслепую — оглавление с правильной структурой критически важно!
- UX — удобство для всех: исследования показывают, что пользователи не читают страницы слово за словом — они сканируют их глазами, останавливаясь на заголовках. Правильная структура помогает людям быстро найти нужную информацию, не тратя время на чтение всего текста.
- Стилизация — радость для разработчика: когда заголовки правильно структурированы, CSS-стили применяются логично и предсказуемо. Вы можете легко задать стили для всех h2 или всех h3, зная, что они используются по назначению.
Абзацы: создаём читаемый текст
Абзацы — это как дыхание в тексте. Они разбивают длинный текст на логические куски, делая его читаемым и понятным. В HTML абзацы создаются тегом <p>. Каждый абзац — это отдельный "блок" текста, который визуально отделён от других абзацев отступами (обычно сверху и снизу).
Представьте, что вы читаете статью без абзацев — сплошная стена текста. Глаза устают, сложно найти нужное место, если отвлёкся. Абзацы делают текст "дышащим" и структурированным.
<p>Это первый абзац текста. Он содержит несколько предложений, которые образуют законченную мысль. Когда мысль закончена, начинается новый абзац.</p>
<p>Это второй абзац. Он отделён от первого визуально (отступом) и логически (новой мыслью). Каждый абзац — это как отдельный "кирпичик" в здании текста.</p>
Перенос строки — инструмент, который требует осторожности: Тег <br> создаёт принудительный перенос строки внутри абзаца. Это как нажатие Enter в середине предложения. Используйте его очень осторожно! В 95% случаев лучше использовать отдельные абзацы или управлять отступами через CSS. Почему? Потому что <br> — это "жёсткий" перенос, который сложно контролировать. На разных экранах он может выглядеть по-разному, а CSS даёт вам полный контроль.
Когда <br> действительно нужен — редкие, но важные случаи:
- Адреса — каждая строка адреса должна быть на новой строке: улица, дом, город. Это не разные абзацы, а части одного адреса.
- Стихи или тексты с фиксированной структурой — когда важна именно структура строк, а не смысловые блоки.
- Короткие подписи — например, под изображением, где нужен перенос, но это не полноценный абзац.
Во всех остальных случаях — используйте <p> для абзацев и CSS для управления отступами. Ваш будущий я (и ваши коллеги) скажут вам спасибо!
Когда НЕ использовать <br>:
- Для создания отступов между абзацами (используйте
<p>или CSSmargin) - Для создания списков (используйте
<ul>или<ol>) - Для структурирования контента (используйте семантические теги)
<!-- Плохо: много <br> для структуры -->
<p>Имя: Иван<br>Фамилия: Петров<br>Email: ivan@example.com</p>
<!-- Хорошо: используйте списки или структурированные данные -->
<dl>
<dt>Имя:</dt>
<dd>Иван</dd>
<dt>Фамилия:</dt>
<dd>Петров</dd>
</dl>
Списки
<ul>
<li>Маркированный пункт</li>
<li>Ещё пункт</li>
</ul>
<ol>
<li>Нумерованный пункт</li>
<li>Ещё пункт</li>
</ol>
<dl>
<dt>Термин</dt>
<dd>Определение</dd>
</dl>
Блочные и строчные элементы: два разных мира
Представьте, что HTML-элементы живут в двух разных "мирах" по способу отображения: блочные и строчные (inline). Это как разница между кирпичами и цементом: кирпичи (блочные) занимают целую строку и создают структуру, а цемент (строчные) заполняет пространство между кирпичами. Понимание этой разницы — это фундамент верстки. Без него вы будете бороться с элементами, которые ведут себя не так, как ожидаете.
Блочные элементы: "захватчики строк"
Блочные элементы — это "эгоисты" пространства. Они занимают всю доступную ширину родителя (как будто говорят: "Вся эта строка моя!") и всегда начинаются с новой строки, выталкивая следующий элемент вниз. Они создают "блок" контента — визуально отдельный прямоугольник.
Характеристики:
- Занимают всю ширину контейнера
- Начинаются с новой строки
- Могут содержать другие блочные и строчные элементы
- Можно задавать ширину, высоту, отступы (margin, padding)
Примеры блочных элементов: <div>, <p>, <section>, <article>, <header>, <footer>, <h1>-<h6>, <ul>, <ol>, <li>.
Строчные элементы: "скромные помощники"
Строчные элементы — полная противоположность блочным. Они скромные и занимают только столько места, сколько им нужно для содержимого. Они не создают новую строку и "встраиваются" в поток текста, как слова в предложении. Если блочный элемент — это отдельный абзац, то строчный — это выделенное слово внутри абзаца.
Характеристики:
- Занимают только необходимое пространство
- Не создают новую строку
- Могут содержать только текст и другие строчные элементы
- Нельзя задавать ширину и высоту (игнорируются)
- Вертикальные отступы (margin-top, margin-bottom) не работают
Примеры строчных элементов: <span>, <a>, <em>, <strong>, <code>, <img>, <button>.
<!-- Блочные элементы -->
<div>Это блочный элемент</div>
<p>Это тоже блочный элемент</p>
<!-- Строчные элементы -->
<p>Это <strong>строчный</strong> элемент внутри <em>абзаца</em>.</p>
<span>Строчный элемент</span> <span>рядом со строчным</span>
Важно: В HTML5 появились inline-block элементы и можно изменить тип отображения через CSS свойство display. Но базовое понимание блочных и строчных элементов остаётся фундаментальным.
Пробелы и переносы: когда браузер "упрощает" ваш код
HTML имеет интересную особенность, которая часто удивляет новичков: браузер автоматически "схлопывает" множественные пробелы и переносы строк в один пробел. Представьте, что вы написали в коде:
<p>Это текст с множественными пробелами</p>
А браузер показывает: "Это текст с множественными пробелами" (все пробелы стали одним). Это сделано для удобства — вы можете форматировать код как угодно (с отступами, переносами), и браузер всё равно покажет текст правильно. Но иногда это создаёт неожиданные результаты, особенно когда вы хотите сохранить форматирование "как есть".
<!-- В коде много пробелов -->
<p>Это текст с множественными пробелами</p>
<!-- В браузере отобразится как: -->
<!-- Это текст с множественными пробелами (все пробелы схлопнуты в один) -->
Как сохранить форматирование:
<pre>— сохраняет все пробелы и переносы строк как есть. Используется для кода, стихов, ASCII-арта.- CSS
white-space: pre— сохраняет пробелы и переносы - CSS
white-space: pre-wrap— сохраняет пробелы, но переносит текст по ширине - HTML-сущность
— неразрывный пробел (не схлопывается)
<!-- Сохранение форматирования -->
<pre>
function hello() {
console.log('Hello, World!');
}
</pre>
<!-- Или через CSS -->
<p style="white-space: pre-wrap">Текст
с пробелами
и переносами</p>
Семантические инлайн‑элементы для форматирования
HTML предоставляет семантические теги для выделения текста. Важно использовать их по назначению, а не только для визуального оформления (для этого есть CSS).
<strong>— важный текст. Используется для логически важной информации. По умолчанию отображается жирным, но смысл — в важности, а не в оформлении.<em>— акцент/интонация. Используется для выделения интонации или акцента. По умолчанию отображается курсивом, но смысл — в интонации.<mark>— выделенный текст. Используется для выделения текста, как маркером (например, результаты поиска).<small>— мелкий текст. Используется для мелкого текста (например, копирайт, юридическая информация).<code>—код. Используется для фрагментов кода внутри текста.<kbd>— клавиши. Используется для обозначения клавиш клавиатуры.<samp>— пример вывода. Используется для примеров вывода программы.<var>— переменная. Используется для обозначения переменных в коде.<span>— универсальный строчный контейнер без семантического значения. Используется для группировки элементов для стилизации или JavaScript.
<p>
Это <strong>важный</strong> текст.
Обратите <em>особое внимание</em> на это.
Для кода используйте <code>console.log()</code>.
Нажмите <kbd>Ctrl</kbd> + <kbd>C</kbd> для копирования.
</p>
Правило: Используйте семантические теги по их назначению, а не только для визуального оформления. Если нужно просто сделать текст жирным или курсивом без смысловой нагрузки, используйте CSS (font-weight: bold или font-style: italic).
Практика
Добавьте на страницу «О себе» разделы с заголовками, абзацами, маркированным и нумерованным списками, а также списком определений.
Ссылки и изображения
Ссылки и изображения — это основа навигации и визуального контента на веб-страницах. Правильное использование этих элементов критически важно для пользовательского опыта, SEO и доступности.
Ссылки: создание навигации
Тег <a> (anchor — якорь) создаёт гиперссылки — основной способ навигации в интернете. Ссылки могут вести на другие страницы, файлы, секции текущей страницы или выполнять специальные действия (открыть почту, позвонить).
Типы ссылок
1. Внешние ссылки — ведут на другие сайты:
<a href="https://example.com" target="_blank" rel="noopener noreferrer">
Внешняя ссылка
</a>
Атрибуты:
href— обязательный атрибут, содержит URL назначенияtarget="_blank"— открывает ссылку в новой вкладкеrel="noopener noreferrer"— обязательно приtarget="_blank"для безопасности
Безопасность: Без rel="noopener" новая страница получает доступ к объекту window.opener вашей страницы и может выполнить вредоносный код. noreferrer также скрывает информацию о том, откуда пришёл пользователь.
2. Внутренние ссылки — ведут на другие страницы вашего сайта:
<a href="/about.html">О нас</a>
<a href="contact.html">Контакты</a>
<a href="../blog/index.html">Блог</a>
3. Якорные ссылки — прокручивают к секции на текущей странице:
<!-- Ссылка на секцию -->
<a href="#contacts">Перейти к контактам</a>
<!-- Секция с соответствующим id -->
<section id="contacts">
<h2>Контакты</h2>
<p>Наши контакты...</p>
</section>
Как это работает: Браузер ищет элемент с id, равным значению после #, и плавно прокручивает к нему. Это полезно для навигации по длинным страницам.
4. Специальные протоколы — для выполнения действий:
<!-- Email ссылка -->
<a href="mailto:hi@example.com?subject=Вопрос&body=Здравствуйте!">
Написать письмо
</a>
<!-- Телефон (работает на мобильных) -->
<a href="tel:+79001234567">+7 (900) 123-45-67</a>
<!-- SMS (на мобильных) -->
<a href="sms:+79001234567?body=Привет!">Отправить SMS</a>
<!-- Скачать файл -->
<a href="/files/document.pdf" download>Скачать PDF</a>
Дополнительные атрибуты ссылок
title— всплывающая подсказка при наведении. Полезно для дополнительной информации, но не полагайтесь на него для важного контента.download— заставляет браузер скачать файл вместо перехода по ссылке. Можно указать имя файла:download="myfile.pdf".rel— отношения между документами. Значения:nofollow(не передавать вес страницы),noopener,noreferrer,external.hreflang— язык целевой страницы:hreflang="en"для английской версии.
<!-- Полный пример ссылки с атрибутами -->
<a
href="https://example.com/article"
target="_blank"
rel="noopener noreferrer"
title="Откроется в новой вкладке"
hreflang="ru"
>
Читать статью
</a>
Изображения: выбор формата и оптимизация
Изображения делают веб-страницы визуально привлекательными, но неправильное их использование может замедлить загрузку страницы и ухудшить пользовательский опыт. Важно правильно выбирать формат и оптимизировать изображения.
Выбор формата изображения
Разные форматы подходят для разных задач:
- JPEG — для фотографий и изображений с множеством цветов. Хорошее сжатие, но без прозрачности. Используйте качество 80-85% для веба.
- PNG — для графики с прозрачностью, скриншотов, изображений с текстом. Больший размер файла, но сохраняет качество.
- WebP — современный формат от Google. На 25-35% меньше размер при том же качестве, чем JPEG/PNG. Поддерживает прозрачность. Рекомендуется использовать везде, где возможно.
- AVIF — ещё более современный формат. На 50% меньше размер, чем JPEG. Поддержка в браузерах растёт, но пока не везде.
- SVG — векторный формат для иконок, логотипов, простой графики. Масштабируется без потери качества, маленький размер для простых изображений.
- GIF — только для анимаций. Для статичных изображений не используйте — размер файла будет огромным.
<!-- Базовое использование изображения -->
<img
src="/images/cat.png"
alt="Милый котёнок сидит на подоконнике"
width="400"
height="300"
loading="lazy"
>
Обязательные и важные атрибуты
src— обязательный атрибут. Путь к файлу изображения.alt— обязательный атрибут. Описательный текст для изображения. Критически важен для:- Доступности: скринридеры читают этот текст пользователям с нарушениями зрения
- SEO: поисковые системы используют alt для понимания содержания изображения
- UX: отображается, если изображение не загрузилось
Правила написания alt:
- Описывайте содержание изображения, а не его назначение
- Будьте конкретны, но кратки (до 125 символов)
- Для декоративных изображений используйте пустой
alt="" - Не начинайте с "Изображение..." или "Картинка..." — скринридеры уже сообщают, что это изображение
widthиheight— настоятельно рекомендуется указывать. Помогают браузеру:- Резервировать место для изображения до его загрузки
- Избегать CLS (Cumulative Layout Shift) — "прыжков" верстки
- Улучшить Core Web Vitals и SEO
Указывайте реальные размеры изображения в пикселях. CSS может изменить визуальный размер, но браузер использует эти значения для резервирования места.
loading="lazy"— отложенная загрузка. Изображение загружается только когда пользователь прокручивает страницу к нему. Используйте для всех изображений, кроме первого (LCP-изображения).decoding="async"— асинхронное декодирование. Изображение декодируется параллельно с рендерингом страницы, не блокируя его.fetchpriority="high"— приоритет загрузки. Используйте только для LCP-изображения (самого важного изображения на странице).
Семантическая обёртка: <figure> и <figcaption>
Для изображений с подписями используйте семантическую структуру:
<figure>
<img
src="/images/cat.png"
alt="Милый котёнок сидит на подоконнике"
width="400"
height="300"
loading="lazy"
>
<figcaption>Наш талисман — котёнок по имени Мурзик</figcaption>
</figure>
<figure> — семантический контейнер для иллюстраций, диаграмм, фотографий с подписями. Может содержать несколько изображений или другой контент.
<figcaption> — подпись к содержимому <figure>. Может быть до или после изображения, но обычно размещается после.
Адаптивные изображения: srcset и sizes
Современные веб-сайты должны корректно отображаться на устройствах с разными размерами экранов и плотностью пикселей (retina-дисплеи). HTML5 предоставляет инструменты для адаптивных изображений.
srcset для разных размеров
Атрибут srcset позволяет указать несколько версий изображения для разных размеров экрана:
<img
src="/images/photo-800.jpg"
srcset="/images/photo-400.jpg 400w,
/images/photo-800.jpg 800w,
/images/photo-1200.jpg 1200w"
sizes="(max-width: 600px) 100vw, 600px"
alt="Красивый пейзаж"
width="600"
height="400"
loading="lazy"
>
Как это работает:
400w,800w,1200w— ширина изображения в пикселях (descriptor)- Браузер выбирает подходящее изображение на основе размера экрана и плотности пикселей
sizes— указывает браузеру, какой размер будет у изображения на экране
Разбор sizes:
(max-width: 600px) 100vw— если экран меньше 600px, изображение займёт 100% ширины viewport600px— иначе изображение будет 600px шириной
srcset для retina-дисплеев
Для поддержки дисплеев с высокой плотностью пикселей (2x, 3x):
<img
src="/images/logo@1x.png"
srcset="/images/logo@1x.png 1x,
/images/logo@2x.png 2x,
/images/logo@3x.png 3x"
alt="Логотип компании"
width="200"
height="50"
>
Браузер автоматически выберет подходящую версию: на обычном экране — 1x, на retina — 2x или 3x.
Оптимизация изображений: практические советы
- Сжимайте изображения: используйте инструменты типа TinyPNG, ImageOptim, Squoosh для уменьшения размера без потери качества
- Используйте современные форматы: WebP или AVIF вместо JPEG/PNG где возможно
- Создавайте несколько размеров: не загружайте огромное изображение на мобильный
- Указывайте width/height: предотвращает CLS и улучшает производительность
- Lazy loading: загружайте изображения по мере необходимости
- CDN: используйте CDN для быстрой доставки изображений пользователям по всему миру
Практика
Соберите меню из 4 ссылок (включая якорь и mailto) и вставьте 2 изображения: обычное и адаптивное с srcset.
Семантическая разметка
Семантические теги описывают смысл блоков: поисковики и ассистивные технологии лучше понимают структуру, пользователям проще навигация.
<header>
<nav>Меню</nav>
</header>
<main>
<article>
<header><h1>Заголовок статьи</h1></header>
<section aria-labelledby="s1">
<h2 id="s1">Основной контент</h2>
...
</section>
<footer>Автор и дата</footer>
</article>
<aside>Боковая колонка</aside>
</main>
<footer>Подвал</footer>
Лендмарки доступности
<header>,<footer>— могут быть у страницы и у статьи/секции<main>— только один на странице, основной контент<nav>— группы ссылок (меню/хлебные крошки)<aside>— боковой/вспомогательный контент<article>— самостоятельный, самодостаточный блок (статья, карточка)
Если подходящего тега нет — используйте <div> (блочный) или <span> (строчный) и при необходимости ARIA‑атрибуты.
Практика
Преобразуйте страницу «О себе» в семантический макет с header, nav, main, article, aside, footer.
Формы: сбор данных от пользователей
Формы — это основной способ взаимодействия пользователей с веб-сайтом. Они позволяют собирать данные, отправлять запросы, выполнять поиск и многое другое. Правильная работа с формами критически важна для пользовательского опыта и безопасности.
Структура формы
Форма создаётся тегом <form>, который содержит поля ввода и кнопку отправки. Каждая форма должна иметь атрибуты action (куда отправлять) и method (как отправлять).
<form action="/submit" method="post" autocomplete="on" novalidate>
<!-- Поля формы -->
<button type="submit">Отправить</button>
</form>
Атрибуты формы
action— URL, куда отправляются данные. Может быть относительным (/submit) или абсолютным (https://api.example.com/submit). Если не указан, форма отправляется на текущую страницу.method— HTTP-метод отправки:GETилиPOST(по умолчаниюGET).autocomplete— включает/выключает автозаполнение браузера. Значения:on(включено) илиoff(выключено).novalidate— отключает встроенную HTML5-валидацию. Используйте, если валидация выполняется через JavaScript.enctype— тип кодирования данных. По умолчаниюapplication/x-www-form-urlencoded. Для загрузки файлов используйтеmultipart/form-data.
Типы полей ввода
HTML5 предоставляет множество типов полей <input>, каждый оптимизирован для своего типа данных:
Текстовые поля
<!-- Обычный текст -->
<input type="text" name="username" placeholder="Введите имя">
<!-- Email с валидацией -->
<input type="email" name="email" required>
<!-- Пароль (скрывается) -->
<input type="password" name="password" minlength="8">
<!-- Поиск -->
<input type="search" name="q" placeholder="Поиск...">
<!-- URL -->
<input type="url" name="website">
<!-- Телефон -->
<input type="tel" name="phone" pattern="[0-9]{10}">
<!-- Число -->
<input type="number" name="age" min="18" max="100" step="1">
<!-- Ползунок для чисел -->
<input type="range" name="volume" min="0" max="100" value="50">
Дата и время
<!-- Дата -->
<input type="date" name="birthday">
<!-- Время -->
<input type="time" name="meeting-time">
<!-- Дата и время -->
<input type="datetime-local" name="event-datetime">
<!-- Месяц -->
<input type="month" name="month">
<!-- Неделя -->
<input type="week" name="week">
Выбор значений
<!-- Чекбокс (можно выбрать несколько) -->
<label>
<input type="checkbox" name="interests" value="coding" checked>
Программирование
</label>
<label>
<input type="checkbox" name="interests" value="design">
Дизайн
</label>
<!-- Радио-кнопки (можно выбрать только одно) -->
<label>
<input type="radio" name="gender" value="male" checked>
Мужской
</label>
<label>
<input type="radio" name="gender" value="female">
Женский
</label>
<!-- Выпадающий список -->
<select name="country" required>
<option value="">Выберите страну</option>
<option value="ru" selected>Россия</option>
<option value="us">США</option>
<option value="de">Германия</option>
</select>
<!-- Множественный выбор -->
<select name="languages" multiple size="4">
<option value="ru">Русский</option>
<option value="en">Английский</option>
<option value="de">Немецкий</option>
</select>
Специальные поля
<!-- Цвет -->
<input type="color" name="fav-color" value="#4f46e5">
<!-- Файл -->
<input type="file" name="avatar" accept="image/*">
<!-- Скрытое поле (не видно пользователю) -->
<input type="hidden" name="token" value="abc123">
<!-- Кнопка отправки -->
<button type="submit">Отправить</button>
<!-- Кнопка сброса -->
<button type="reset">Очистить</button>
<!-- Обычная кнопка (для JavaScript) -->
<button type="button">Нажми меня</button>
Многострочный текст: textarea
Для длинных текстов используйте <textarea>:
<label for="message">Сообщение</label>
<textarea
id="message"
name="message"
rows="6"
cols="50"
placeholder="Введите ваше сообщение..."
maxlength="500"
required
></textarea>
<small>Осталось символов: <span id="char-count">500</span></small>
Атрибуты:
rows— количество видимых строк (можно изменить через CSS)cols— количество видимых символов в строке (устаревший, лучше управлять через CSSwidth)maxlength— максимальное количество символовwrap— перенос строк:soft(по умолчанию) илиhard
Связывание label и input
Каждое поле должно иметь связанную метку (<label>). Это критически важно для доступности и UX.
Способ 1: через атрибут for (рекомендуется)
<label for="email">Email адрес</label>
<input id="email" type="email" name="email" required>
<!-- При клике на label фокус переходит на input -->
Способ 2: обёртка
<label>
Email адрес
<input type="email" name="email" required>
</label>
<!-- label автоматически связан с input внутри -->
Почему это важно:
- Скринридеры объявляют метку при фокусе на поле
- Клик по метке активирует поле (особенно удобно для чекбоксов и радио)
- Улучшает UX на мобильных устройствах
- Помогает SEO и поисковым системам
Валидация форм
HTML5 предоставляет встроенную валидацию без JavaScript. Это первая линия защиты от некорректных данных.
Атрибуты валидации
required— поле обязательно для заполненияminlength/maxlength— минимальная/максимальная длина текстаmin/max— минимальное/максимальное значение для чиселstep— шаг для чисел (например, 0.5 для десятичных)pattern— регулярное выражение для проверки форматаtype— тип поля автоматически валидируется (email, url, number и т.д.)
<!-- Примеры валидации -->
<input
type="email"
name="email"
required
placeholder="example@mail.com"
>
<input
type="password"
name="password"
required
minlength="8"
pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}"
title="Пароль должен содержать минимум 8 символов, включая цифру, строчную и заглавную букву"
>
<input
type="number"
name="age"
min="18"
max="100"
step="1"
required
>
<input
type="tel"
name="phone"
pattern="[0-9]{10}"
placeholder="1234567890"
title="Введите 10 цифр"
>
Сообщения об ошибках
Браузер автоматически показывает сообщения об ошибках при невалидных данных. Можно кастомизировать через JavaScript или использовать атрибут title для подсказки.
<input
type="email"
name="email"
required
oninvalid="this.setCustomValidity('Пожалуйста, введите корректный email')"
oninput="this.setCustomValidity('')"
>
Группировка полей: fieldset и legend
Для логической группировки связанных полей используйте <fieldset> и <legend>:
<fieldset>
<legend>Контактная информация</legend>
<label for="name">Имя</label>
<input id="name" type="text" name="name" required>
<label for="email">Email</label>
<input id="email" type="email" name="email" required>
</fieldset>
<fieldset>
<legend>Предпочтения</legend>
<label>
<input type="checkbox" name="news">
Подписаться на новости
</label>
<label>
<input type="checkbox" name="promo">
Получать промо-предложения
</label>
</fieldset>
Преимущества: улучшает доступность (скринридеры объявляют группу), визуально группирует связанные поля, улучшает UX.
GET vs POST: когда что использовать
Выбор метода отправки формы критически важен для безопасности и правильной работы приложения.
GET — для получения данных
Характеристики:
- Данные отправляются в URL как параметры:
?name=Иван&email=ivan@mail.com - Запрос можно закладкировать, отправить ссылкой
- Ограничение длины URL (обычно ~2000 символов)
- Данные видны в истории браузера, логах сервера
- Идемпотентный — повторный запрос не изменяет состояние
Когда использовать:
- Поисковые запросы
- Фильтры и сортировка
- Пагинация
- Любые запросы, которые только читают данные
<!-- Форма поиска -->
<form action="/search" method="get">
<input type="search" name="q" placeholder="Поиск...">
<button type="submit">Найти</button>
</form>
<!-- Результат: /search?q=python -->
POST — для отправки данных
Характеристики:
- Данные отправляются в теле запроса, не видны в URL
- Нет ограничений по размеру (практически)
- Безопаснее для чувствительных данных
- Не идемпотентный — повторная отправка может создать дубликаты
- Нельзя закладкировать результат
Когда использовать:
- Регистрация и авторизация
- Отправка форм обратной связи
- Загрузка файлов
- Любые действия, которые изменяют данные на сервере
<!-- Форма регистрации -->
<form action="/register" method="post" enctype="application/x-www-form-urlencoded">
<input type="text" name="username" required>
<input type="email" name="email" required>
<input type="password" name="password" required>
<button type="submit">Зарегистрироваться</button>
</form>
<!-- Данные отправляются в теле запроса, не видны в URL -->
Важно для безопасности:
- Никогда не используйте GET для паролей, персональных данных, финансовых операций
- Валидация на клиенте (HTML5) — это только удобство для пользователя. Всегда валидируйте данные на сервере
- Для защиты от CSRF-атак используйте токены
- Используйте HTTPS для всех форм с чувствительными данными
Атрибуты autocomplete: улучшение UX
Атрибут autocomplete помогает браузерам и менеджерам паролей правильно заполнять формы. Это значительно улучшает пользовательский опыт.
<form autocomplete="on">
<input type="text" name="name" autocomplete="name">
<input type="email" name="email" autocomplete="email">
<input type="tel" name="phone" autocomplete="tel">
<input type="text" name="address" autocomplete="street-address">
<input type="text" name="city" autocomplete="address-level2">
<input type="text" name="zip" autocomplete="postal-code">
<input type="password" name="current-password" autocomplete="current-password">
<input type="password" name="new-password" autocomplete="new-password">
</form>
Популярные значения autocomplete:
name,given-name,family-name— имяemail— email адресtel— телефонstreet-address,address-level1(регион),address-level2(город),postal-code— адресcurrent-password,new-password— паролиcc-name,cc-number,cc-exp— данные кредитной карты
Загрузка файлов
Для загрузки файлов нужно:
- Использовать
type="file" - Установить
enctype="multipart/form-data"в форме - Использовать метод
POST
<form action="/upload" method="post" enctype="multipart/form-data">
<label for="avatar">Загрузить аватар</label>
<input
id="avatar"
type="file"
name="avatar"
accept="image/png, image/jpeg, image/webp"
multiple
>
<small>Максимальный размер: 5MB. Форматы: PNG, JPEG, WebP</small>
<button type="submit">Загрузить</button>
</form>
Атрибут accept: ограничивает типы файлов, которые можно выбрать. Можно указать MIME-типы (image/*, application/pdf) или расширения (.pdf,.doc).
Практические советы по формам
- Всегда используйте label: не заменяйте его на placeholder. Placeholder — это подсказка, label — это описание поля.
- Группируйте связанные поля: используйте
fieldsetдля визуальной и логической группировки - Показывайте прогресс: для длинных форм используйте индикаторы прогресса или разбивайте на шаги
- Валидируйте в реальном времени: показывайте ошибки сразу, а не только при отправке
- Используйте правильные типы полей: это улучшает UX на мобильных (правильная клавиатура) и валидацию
- Предоставляйте обратную связь: показывайте сообщения об успешной отправке или ошибках
- Защищайте от спама: используйте CAPTCHA, honeypot-поля или другие методы
Практика
Создайте полноценную форму регистрации со следующими полями:
- Имя и фамилия (отдельные поля)
- Email с валидацией
- Пароль с требованиями (минимум 8 символов, буквы и цифры)
- Подтверждение пароля
- Дата рождения (date picker)
- Пол (radio buttons)
- Интересы (checkboxes — можно выбрать несколько)
- Страна (select с несколькими опциями)
- О себе (textarea)
- Согласие с условиями (checkbox, обязательное)
- Кнопка отправки
Требования:
- Все поля должны иметь связанные label
- Используйте правильные типы input
- Добавьте валидацию через HTML5-атрибуты
- Используйте fieldset для группировки
- Добавьте autocomplete атрибуты
- Используйте метод POST
Доступность (A11y) и ARIA
Доступность — это про то, чтобы интерфейсом могли пользоваться люди с разными возможностями и устройствами. Следуйте стандартам WCAG, используйте нативную семантику и дополняйте её ARIA, когда это необходимо.
Фокус и клавиатурная навигация
- Порядок табуляции следует логике документа. Не используйте
tabindex> 0, предпочитайте нативный порядок. - Кнопки должны быть
<button>, а не<div role="button">. Если всё же нужен кастом — добавляйтеrole,tabindex="0", обрабатывайте клавиши Enter/Space. - Добавляйте ссылку «пропустить к содержимому» в самом начале:
<a class="skip-link" href="#content">К основному содержимому</a>.
ARIA-атрибуты и лендмарки
roleдля уточнения роли, когда нет подходящего тега.aria-label,aria-labelledby,aria-describedby— альтернативные/связанные подписи.aria-expanded,aria-controls— состояние раскрывающихся областей.aria-live="polite|assertive",aria-busy— живые области и загрузка.
<button aria-expanded="false" aria-controls="acc-1" id="acc-btn-1">Развернуть</button>
<section id="acc-1" role="region" aria-labelledby="acc-btn-1" hidden>
<p>Скрываемый контент</p>
</section>
Формы и ошибки
- Каждое поле связано с
<label for>. Не используйтеplaceholderвместо метки. - Ошибки сообщайте текстом, связывайте с полем через
aria-describedby, фокусируйте первую ошибку.
<label for="email">Email</label>
<input id="email" type="email" aria-describedby="email-err" required>
<p id="email-err" role="alert" hidden>Введите корректный email</p>
Контраст и медиа
- Контраст текста к фону: минимум 4.5:1 для обычного текста.
- У изображений обязателен осмысленный
alt(декоративным — пустойalt=""). - Для иконок SVG: добавляйте
role="img"иaria-labelпри необходимости.
Правило: Сначала используйте семантические теги. ARIA — только если нельзя иначе.
SEO для HTML
- Title/Description: уникальные на страницу; title ≈ 50–60 знаков, description ≈ 140–160.
- Заголовки: один
h1, далее иерархияh2–h3. - Open Graph/Twitter: корректные превью при шаринге.
- Canonical: укажите канонический URL, чтобы избежать дублей.
- Structured Data: JSON‑LD для статей, курсов, хлебных крошек (см. в <head>).
- robots.txt / sitemap.xml: помогайте поисковикам индексировать сайт.
- Core Web Vitals: LCP, CLS, INP влияют на ранжирование — оптимизируйте критический рендеринг и изображения.
<link rel="canonical" href="https://example.com/page" />
<meta property="og:title" content="Заголовок" />
<meta property="og:description" content="Описание" />
<meta property="og:image" content="https://example.com/preview.jpg" />
Адаптивные изображения и ретина
Используйте правильные форматы и отдавайте изображения под размер экрана и плотность пикселей. Указывайте явные width/height для предотвращения CLS.
<picture>, srcset и плотности
<picture>
<source type="image/avif" srcset="/img/hero@1x.avif 1x, /img/hero@2x.avif 2x">
<source type="image/webp" srcset="/img/hero@1x.webp 1x, /img/hero@2x.webp 2x">
<img src="/img/hero@1x.jpg" srcset="/img/hero@2x.jpg 2x" sizes="(max-width: 768px) 100vw, 1200px" alt="Обложка" width="1200" height="600" loading="lazy" decoding="async" fetchpriority="high">
</picture>
SVG и иконки
- Для одноцветных иконок используйте SVG‑спрайты, меняйте цвет через CSS.
- Добавляйте
aria-hidden="true"декоративным иконкам.
Фоновые изображения и ретина в CSS
.hero {
background-image: image-set(
url('/img/hero-bg@1x.jpg') 1x,
url('/img/hero-bg@2x.jpg') 2x
);
aspect-ratio: 2 / 1;
object-fit: cover;
}
Подсказка: Для LCP‑изображения используйте fetchpriority="high" и не лените загрузку.
Практика
Замените изображения на главной на AVIF/WebP с ретина‑вариантами, добавьте width/height и корректные alt.
Итоговый проект модуля 1
Сверстайте главную страницу портфолио без стилей. Обязательные секции: «Обо мне», «Навыки», «Проекты», «Контакты»; шапка с меню, подвал. Используйте семантические теги и добавьте форму обратной связи.
- Структура:
<header>,<nav>,<main>с 3–4<section>,<footer> - Доступность: корректные
altу изображений, иерархия заголовков - Проверка: валидируйте документ на W3C Validator