HTML, DOM и CSS: платформа под React
HTML описывает структуру и смысл документа. DOM — дерево объектов, которое браузер построил после разбора HTML; JavaScript может менять это дерево. CSS задаёт представление. React вычисляет описание интерфейса и согласует его с DOM, но доступность и правила layout остаются правилами браузера.
Исходник схемы
flowchart LR HTML[HTML] --> DOM[DOM] CSS[CSS] --> Layout[Стили и layout] DOM --> Layout Layout --> Paint[Отрисовка] DOM --> Accessibility[Дерево доступности]
Семантика прежде внешнего вида
Ссылка переводит на адрес, кнопка выполняет действие. Заголовок обозначает
уровень структуры, а не размер шрифта. main выделяет главное содержимое,
nav — навигацию, список — связанные пункты. Нативная кнопка уже поддерживает
клавиатуру и disabled; у div с обработчиком клика этих свойств нет.
В своём worktree создайте временный каталог var/lesson-web и сохраните в нём
index.html. Откройте файл двойным щелчком в браузере; приложение и CMS
для этого опыта не нужны. После лаборатории удалите только этот учебный каталог.
<!doctype html>
<html lang="ru">
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Учебное расписание</title>
<link rel="stylesheet" href="./style.css" />
<main>
<h1>Расписание</h1>
<form>
<label for="query">Название события</label>
<input id="query" name="query" type="search" />
<button type="submit">Найти</button>
</form>
<ul class="events">
<li><a href="#first">Тренировка</a></li>
<li><a href="#second">Открытый урок</a></li>
</ul>
</main>
</html>
Без JavaScript отправка формы меняет адрес с query string. У кнопки внутри
формы по умолчанию тип submit; для локального действия нужен type="button".
Связь for/id даёт полю доступное имя. Placeholder не заменяет label.
Для содержательной фотографии нужен осмысленный alt; для декоративной — пустой.
DOM может отличаться от исходной строки: браузер исправляет некорректную вложенность. Это одна из причин ошибки гидратации. Проверяйте Elements и исходный HTML, а не только JSX. Внешний HTML нельзя без проверки считать безопасным: React экранирует обычные текстовые значения, но вставка HTML отдельным API требует отдельной модели доверия.
Каскад и геометрия
Каскад выбирает объявление с учётом происхождения, важности, слоя, специфичности и порядка. «Последнее правило выигрывает» верно только после сравнения предыдущих факторов. Наследование передаёт некоторые свойства от родителя; размеры блока обычно не наследуются. В DevTools смотрите Computed и источник победившего объявления. В проекте порядок Mantine layer и UIKit разобран отдельно.
Рядом с index.html создайте style.css и поместите в него CSS ниже.
Тег link в HTML подключает этот файл по относительному адресу. Сохраните оба
файла и обновите страницу; в DevTools → Network проверьте загрузку style.css:
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: system-ui, sans-serif;
}
main {
max-width: 60rem;
margin-inline: auto;
padding: 1rem;
}
form {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
align-items: center;
}
input {
min-width: 0;
max-width: 100%;
}
.events {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
gap: 1rem;
padding: 0;
list-style: none;
}
.events li {
padding: 1rem;
border: 1px solid currentColor;
}
a:focus-visible,
button:focus-visible,
input:focus-visible {
outline: 3px solid #2166d1;
outline-offset: 3px;
}
В box model содержимое окружено padding, border и margin. При border-box
заданная ширина включает padding и border. Flex удобен для одной оси, Grid —
для сетки. min-width: 0 разрешает flex-элементу сжиматься; фиксированная ширина
не гарантирует адаптивность. rem зависит от корневого размера шрифта.
Не переставляйте Grid/Flex элементы ради красоты, если это делает порядок
клавиатурного фокуса непонятным: DOM остаётся источником порядка чтения.
Адаптивность: условное правило
Media query применяет стиль только при выполнении условия. Добавьте в конец
style.css:
@media (max-width: 40rem) {
form {
flex-direction: column;
align-items: stretch;
}
}
Узкое окно делает элементы формы вертикальными; широкое возвращает исходную
раскладку. Сравните обе стороны порога в DevTools. Media query меняет стили,
а не DOM и не порядок чтения. Responsive layout также может обойтись без
явного порога, как сетка auto-fit выше.
Лаборатория браузера
- Отключите CSS. Смысл документа и подписи должны сохраниться.
- Пройдите Tab и Shift+Tab, активируйте кнопку клавиатурой. Фокус должен быть виден.
- Проверьте 320 px, широкий экран и увеличенный текст: без горизонтального переполнения формы, с сохранённым порядком событий.
- В Elements временно измените padding; найдите источник в Computed. Изменение DevTools не сохраняется в файле.
- В Network отправьте форму и найдите URL с
query. Различите запрос документа и запрос данных; Console покажет ошибки JavaScript, а не все ошибки сети. - В дереве доступности проверьте имя поля и роль кнопки. Это полезная проверка, но она не заменяет использование экранного диктора.
Результат: объясняете одну проблему на каждом уровне: семантика, layout, фокус и загрузка. Браузерные проверки в этой лаборатории выполняет читатель; разбор HTML в happy-dom не подтверждает layout и доступность в настоящем браузере. В проекте CSS Modules ограничивают область имён классов, а не отменяют каскад.
Источники: HTML, каскад, Grid и доступность.