Олег Марков
Атрибут class в HTML - как правильно использовать и организовывать стили
Введение
Атрибут class в HTML — один из самых часто используемых инструментов при верстке и разработке интерфейсов. Через него вы связываете разметку с CSS и JavaScript, задаете структуру страницы, группируете элементы и управляете их поведением.
По сути, значение атрибута class — это "ярлык", который вы прикрепляете к HTML-элементу. Потом по этому ярлыку к элементу обращаются стили и скрипты. Чем понятнее и аккуратнее вы организуете классы, тем проще поддерживать и развивать проект.
В этой статье мы подробно разберем, как работает атрибут class, как правильно его использовать, как не запутаться в множестве классов и как организовать удобную систему именования. Я буду опираться на примеры и реальные сценарии из верстки, чтобы вам было проще перенести все это в свои проекты.
Что такое атрибут class и зачем он нужен
Роль class в HTML
Атрибут class — глобальный атрибут HTML. Это значит, что вы можете указать его почти на любом элементе: div, p, span, button, input и т.д.
Пример простой разметки с классом:
<div class="card">
<h2 class="card__title">Заголовок карточки</h2>
<p class="card__text">Краткое описание содержимого.</p>
</div>
Комментарии:
<div class="card">
<!-- card - класс, по которому мы сможем применить стили к блоку -->
<h2 class="card__title">
<!-- card__title - класс для заголовка внутри блока card -->
Заголовок карточки
</h2>
<p class="card__text">
<!-- card__text - класс для текста внутри блока card -->
Краткое описание содержимого.
</p>
</div>
Через class вы решаете сразу несколько задач:
- подключаете CSS-стили к элементу;
- используете селекторы в JavaScript для поиска элементов;
- задаете "семантику интерфейса" — описываете назначение и роль элементов с точки зрения верстки;
- группируете похожие элементы (например, все кнопки одного типа);
- управляете состояниями (активный, выделенный, скрытый и т.п.).
Отличие от id
Многие начинающие разработчики путают class и id. Смотрите, я кратко покажу разницу:
- class можно использовать много раз на странице;
- id должен быть уникальным в рамках документа;
- в CSS селектор по классу пишется через точку (
.button), а по id — через решетку (#main); - в JavaScript методы вроде
document.querySelector('.button')используют селектор по классу, аdocument.getElementById('main')— по id.
В общем случае для оформления и большинства задач по стилям и поведению вы будете использовать именно классы, а id — только там, где реально нужна уникальность (якоря, связи с формами и т.п.).
Синтаксис и базовые правила использования class
Как задается атрибут class
Общий вид:
<tag class="список-классов">...</tag>
Например:
<button class="button primary">Купить</button>
Комментарии:
<button class="button primary">
<!-- button - базовый класс для оформления кнопки -->
<!-- primary - дополнительный класс, например для "главной" кнопки -->
Купить
</button>
Несколько классов на одном элементе
В HTML вы можете указать сразу несколько классов. Для этого используйте разделение пробелом:
<div class="card card--featured theme-dark">
Содержимое карточки
</div>
Комментарии:
<div class="card card--featured theme-dark">
<!-- card - основной класс компонента -->
<!-- card--featured - модификатор, указывает на "особую" карточку -->
<!-- theme-dark - класс темы, задает темное оформление -->
Содержимое карточки
</div>
Важно: внутри значений class пробел — это разделитель классов. Если вы случайно поставите лишний пробел в середине названия, это уже станет другим, отдельным классом.
Допустимые символы в именах классов
С точки зрения спецификации HTML имя класса — это просто строка. Но чаще всего вы используете классы в CSS, поэтому нужно учитывать именно правила CSS-селекторов.
На практике:
- можно использовать буквы (a-z, A-Z), цифры (0-9), дефис (-) и нижнее подчеркивание (_);
- имя не должно начинаться с цифры, если вы планируете использовать класс в CSS без экранирования;
- пробелы недопустимы внутри одного имени — они разделяют классы на несколько;
- старайтесь использовать понятные осмысленные имена, а не
a1,b2,red1и т.п.
Примеры удачных имен:
buttonbutton-primarycard__titleheader-menuis-activelayout-main
Неудачные:
1button(начинается с цифры, в CSS потребует экранирования)кнопка(кириллица допустима, но это осложнит поддержку и инструменты)red(цвет в имени часто сигнализирует о "жестко зашитом" оформлении)big-green-button(слишком специфичное оформление в имени, лучше описывать роль:button-primary)
Регистр символов
Имена классов чувствительны к регистру в CSS и JavaScript. То есть .Button и .button — разные селекторы.
Чтобы не запутаться, придерживайтесь одного стиля:
- чаще всего используют только строчные буквы и дефисы:
main-nav,page-header,footer-links.
<nav class="main-nav">
<!-- main-nav - класс навигации -->
</nav>
Связь атрибута class с CSS
Базовый пример использования class в CSS
Давайте разберемся на простом примере. У вас есть кнопка:
<button class="button-primary">Отправить</button>
Подключим к ней стили:
/* Селектор по классу пишется через точку */
.button-primary {
background-color: #007bff; /* Синий фон */
color: #ffffff; /* Белый текст */
padding: 8px 16px; /* Отступы внутри кнопки */
border: none; /* Убираем рамку */
border-radius: 4px; /* Скругляем углы */
cursor: pointer; /* Курсор "рука" при наведении */
}
Теперь вы видите, как значение атрибута class стало связующим звеном: HTML-элемент получает стили по имени класса.
Один класс — много элементов
Главная сила class — возможность применять один и тот же набор стилей к нескольким элементам:
<button class="button-primary">Сохранить</button>
<button class="button-primary">Отправить</button>
<a href="#" class="button-primary">Подробнее</a>
Комментарии:
<!-- Три разных элемента, но все используют один и тот же класс button-primary -->
<button class="button-primary">Сохранить</button>
<button class="button-primary">Отправить</button>
<a href="#" class="button-primary">Подробнее</a>
Все эти элементы получат одинаковое оформление, описанное один раз в CSS.
Комбинации классов и уточнение стилей
Вы можете "накладывать" классы друг на друга. Покажу вам, как это выглядит.
HTML:
<button class="button button--primary">Купить</button>
<button class="button button--secondary">Отмена</button>
CSS:
/* Базовый стиль для всех кнопок */
.button {
padding: 8px 16px; /* Общие отступы */
border-radius: 4px; /* Общие скругления */
cursor: pointer; /* Общий курсор */
border: 1px solid #ccc; /* Базовая рамка */
}
/* Модификация для основной кнопки */
.button--primary {
background-color: #007bff; /* Синий фон */
color: #ffffff; /* Белый текст */
border-color: #007bff; /* Синяя рамка */
}
/* Модификация для второстепенной кнопки */
.button--secondary {
background-color: #ffffff; /* Белый фон */
color: #333333; /* Темный текст */
border-color: #cccccc; /* Серая рамка */
}
Комментарии: общий класс .button задает базовый вид, а дополнительные классы .button--primary и .button--secondary накладывают поверх свои стили.
Селекторы по нескольким классам
Иногда вам нужно стилизовать элемент только если на нем есть одновременно несколько классов. Тогда в селекторе вы пишете оба класса подряд:
<button class="button button--primary is-active">Сохранено</button>
CSS:
/* Стили применятся только к элементу, у которого есть и button--primary, и is-active */
.button--primary.is-active {
background-color: #0056b3; /* Более темный синий для активного состояния */
}
Комментарии:
/* Здесь точка перед button--primary и is-active означает селектор по классу,
а отсутствие пробела между ними - что оба класса должны быть на одном элементе */
Связь атрибута class с JavaScript
Поиск элементов по классу
Очень часто классы используются как "якоря" для JavaScript-кода. Теперь вы увидите, как это работает на практике.
HTML:
<button class="js-open-modal button-primary">Открыть окно</button>
<div class="modal is-hidden">
<!-- содержимое модального окна -->
</div>
JavaScript:
// Ищем кнопку по классу js-open-modal
const openButton = document.querySelector('.js-open-modal');
// Ищем модальное окно по классу modal
const modal = document.querySelector('.modal');
// Вешаем обработчик клика на кнопку
openButton.addEventListener('click', () => {
// Удаляем класс is-hidden, чтобы показать модальное окно
modal.classList.remove('is-hidden');
});
Комментарии:
// document.querySelector('.js-open-modal')
// Используем селектор по классу .js-open-modal для поиска элемента
//
// modal.classList.remove('is-hidden')
// Через classList управляем классами на элементе (удаляем класс скрытия)
Обратите внимание на класс js-open-modal. Часто для "технических" классов, которые нужны только JavaScript (а не CSS), используют специальные префиксы (js-, data- через data-атрибуты и т.п.), чтобы не путать поведенческие классы со стилизующими.
Управление классами через classList
В JavaScript есть удобное свойство element.classList, которое работает как коллекция классов элемента. С его помощью вы можете добавлять, удалять и переключать классы.
Пример:
<button class="button toggle">Переключить</button>
<div class="box"></div>
JavaScript:
// Находим кнопку и блок по классам
const button = document.querySelector('.toggle');
const box = document.querySelector('.box');
// Вешаем обработчик события на кнопку
button.addEventListener('click', () => {
// Переключаем класс box--active на элементе box
box.classList.toggle('box--active');
});
Комментарии:
// box.classList.toggle('box--active')
// Если класса box--active нет - он будет добавлен
// Если класс уже есть - он будет удален
Похожим образом работают:
classList.add('имя-класса')— добавить класс;classList.remove('имя-класса')— удалить класс;classList.contains('имя-класса')— проверить, есть ли этот класс.
Организация имен классов: подходы и практики
Почему важна система именования
Если на странице 10 элементов — можно назвать классы как угодно. Но в реальных проектах у вас десятки и сотни блоков, которые переиспользуются. Без системы именования все быстро превращается в хаос:
- вы не понимаете, за что отвечает класс
red-boxи можно ли его переиспользовать; - сложно предсказать, к чему приведет изменение стилей по какому-то классу;
- появляются дублирующие классы с похожими именами (
btn,button,button-main,main-button).
Поэтому мы говорим не только про сам атрибут class, но и про то, как сделать его использование системным.
Методология БЭМ (BEM) и класс как часть структуры
Один из самых распространенных подходов — БЭМ (Блок Элемент Модификатор). Смотрите, я коротко покажу вам принцип, без излишней теории.
Пример разметки по БЭМ:
<div class="card card--featured">
<h2 class="card__title">Заголовок</h2>
<p class="card__text">Описание карточки.</p>
<button class="card__button button button--primary">Подробнее</button>
</div>
Комментарии:
<div class="card card--featured">
<!-- card - блок -->
<!-- card--featured - модификатор блока card -->
<h2 class="card__title">
<!-- card__title - элемент блока card -->
Заголовок
</h2>
<p class="card__text">
<!-- card__text - еще один элемент блока card -->
Описание карточки.
</p>
<button class="card__button button button--primary">
<!-- card__button - элемент блока card -->
<!-- button, button--primary - отдельный переиспользуемый блок кнопки -->
Подробнее
</button>
</div>
Правила в таком подходе:
card— блок (самостоятельная сущность);card__title— элемент блокаcard(часть блока);card--featured— модификатор блокаcard(вариант оформления или состояния).
Преимущества:
- по имени класса сразу понятно, к какому компоненту он относится;
- меньше конфликтов стилей между разными частями проекта;
- легче искать нужные фрагменты кода (поиск по
card__быстро покажет все элементы карточки).
Разделение "что это" и "какое оно"
Хорошая практика — разделять классы:
- по роли/структуре (
button,card,header,menu-item); - по состоянию (
is-active,is-open,is-hidden); - по теме (
theme-dark,theme-light).
Например:
<button class="button button--primary is-active">Сохранено</button>
Комментарии:
<!-- button - базовая кнопка -->
<!-- button--primary - тип кнопки (внешний вид) -->
<!-- is-active - состояние кнопки (активна) -->
Такой подход делает классы более предсказуемыми: вы не смешиваете в одном имени и структуру, и оформление, и состояние.
Чего избегать в именах классов
Привязки к конкретным цветам и размерам:
- неудачно:
red-button,big-text; - лучше:
button-danger,title-large.
- неудачно:
Слишком абстрактных имен:
box,block,item— в большом проекте через неделю будет десятки таких классов;- если используете такие слова, добавляйте контекст:
cart-item,news-item.
Привязки к конкретной разметке:
- имя
left-columnможет потерять смысл, если верстка изменится; - лучше:
sidebar,content, которые описывают роль блока, а не его расположение.
- имя
Типичные сценарии использования атрибута class
Группировка однотипных элементов
Один из базовых сценариев — пометить одинаковые элементы одинаковым классом, чтобы стилизовать или обработать ихまとめ.
<ul class="nav">
<li class="nav__item"><a class="nav__link" href="#">Главная</a></li>
<li class="nav__item"><a class="nav__link" href="#">Новости</a></li>
<li class="nav__item"><a class="nav__link" href="#">Контакты</a></li>
</ul>
Комментарии:
<!-- nav - блок навигации -->
<!-- nav__item - элементы списка навигации -->
<!-- nav__link - ссылка навигации -->
CSS:
.nav__item {
display: inline-block; /* Располагаем элементы в линию */
margin-right: 16px; /* Добавляем отступ между пунктами */
}
.nav__link {
text-decoration: none; /* Убираем подчеркивание ссылок */
color: #333333; /* Цвет текста */
}
Все пункты меню стилизуются одинаково за счет повторяющихся классов.
Состояния элементов
Состояния удобно описывать отдельными классами, а не переписывать базовые стили.
Например, выбранный пункт меню:
<ul class="tabs">
<li class="tabs__item is-active">Описание</li>
<li class="tabs__item">Характеристики</li>
<li class="tabs__item">Отзывы</li>
</ul>
CSS:
.tabs__item {
padding: 8px 16px;
cursor: pointer;
}
.tabs__item.is-active {
border-bottom: 2px solid #007bff; /* Подчеркиваем активный таб */
font-weight: 600; /* Делаем шрифт полужирным */
}
Комментарии:
/* .tabs__item.is-active - селектор для элемента, у которого одновременно есть
классы tabs__item и is-active. Это позволяет изменить стиль только активного таба. */
Темы оформления
Иногда нужно менять тему страницы целиком (например, светлая/темная). Для этого часто используют класс на корневом элементе (body или обертке).
HTML:
<body class="theme-dark">
<div class="page">
<h1 class="page__title">Заголовок</h1>
<p class="page__text">Текст страницы.</p>
</div>
</body>
CSS:
/* Общие стили */
.page__title {
font-size: 24px;
}
/* Темная тема */
.theme-dark .page {
background-color: #121212; /* Темный фон всей страницы */
color: #f5f5f5; /* Светлый текст */
}
/* Светлая тема */
.theme-light .page {
background-color: #ffffff; /* Светлый фон */
color: #222222; /* Темный текст */
}
Комментарии:
/* .theme-dark .page - комбинированный селектор
Стили применяются к .page только если он находится внутри элемента с классом theme-dark */
Переключая класс theme-dark на theme-light через JavaScript, вы можете переключать тему без изменения разметки и CSS.
Вспомогательные и утилитарные классы
Часто используют "утилитарные" классы, которые задают простые повторяющиеся стили.
Например:
<p class="text-center mt-16">
Текст по центру с отступом сверху.
</p>
CSS:
.text-center {
text-align: center; /* Центрируем текст */
}
.mt-16 {
margin-top: 16px; /* Отступ сверху 16px */
}
Комментарии:
<!-- text-center - утилитарный класс для выравнивания текста -->
<!-- mt-16 - утилитарный класс для отступа сверху -->
Такие классы помогают не дублировать CSS, но важно не переборщить, чтобы разметка не превратилась в набор "шифров". Обычно их используют в ограниченном количестве и по понятной системе.
Типичные ошибки при работе с классами
Слишком общие классы
Ошибочно:
<div class="block">
...
</div>
<div class="block">
...
</div>
Если класс block используется в разных местах с разной ролью, стили начнут конфликтовать. Лучше выбирать более точные имена:
<div class="product-card">
...
</div>
<div class="news-card">
...
</div>
Смешивание стилей и поведения в одном классе
Ситуация, когда один и тот же класс используют и в CSS, и в JavaScript для разных задач, часто приводит к проблемам. Например:
<button class="open-modal">Открыть</button>
Если в CSS вы привяжете стили к .open-modal, а в JavaScript будете искать этот элемент через тот же класс, со временем вы можете захотеть изменить оформление, но "боитесь" переименовать класс, чтобы не сломать логику.
Решение — разделять:
<button class="button button--primary js-open-modal">Открыть</button>
Комментарии:
<!-- button, button--primary - классы для стилей -->
<!-- js-open-modal - класс только для JavaScript (поведение) -->
Использование классов вместо семантических тегов
Атрибут class удобен, но не стоит им подменять смысловую разметку. Например:
Ошибочно:
<div class="title">Заголовок страницы</div>
Лучше:
<h1 class="page-title">Заголовок страницы</h1>
Комментарии:
<!-- h1 передает смысл заголовка для браузера, поисковиков и вспомогательных технологий -->
<!-- page-title - класс для оформления заголовка -->
Семантические теги (h1–h6, nav, header, footer, main, section, article) помогают сделать страницу более понятной для поисковиков и скринридеров, а class — уже отвечает за стили и организацию кода.
Дублирование классов и "захламление" разметки
Иногда в процессе работы вы добавляете новые классы и забываете удалить старые. В итоге:
<div class="card card-new new-card card-1">
...
</div>
Здесь, скорее всего, часть классов уже не используется, но остается "на всякий случай". Это осложняет поддержку.
Решения:
- периодически проверяйте проект инструментами, которые ищут неиспользуемые классы;
- поддерживайте единый стиль именования, чтобы лишние классы легче замечать;
- документируйте основные компоненты и их классы (хотя бы кратко).
Практический пример: мини-компонент карточки
Смотрите, я покажу вам связный пример, где атрибут class используется сразу для структуры, стилей и поведения.
HTML:
<div class="product-card">
<img class="product-card__image" src="phone.jpg" alt="Смартфон">
<h3 class="product-card__title">Смартфон X100</h3>
<p class="product-card__price">29 990 ₽</p>
<button class="button button--primary js-add-to-cart">
Добавить в корзину
</button>
<p class="product-card__status is-hidden">
Товар добавлен в корзину
</p>
</div>
Комментарии:
<div class="product-card">
<!-- product-card - блок карточки товара -->
<img class="product-card__image" src="phone.jpg" alt="Смартфон">
<!-- product-card__image - элемент карточки (картинка товара) -->
<h3 class="product-card__title">Смартфон X100</h3>
<!-- product-card__title - заголовок товара -->
<p class="product-card__price">29 990 ₽</p>
<!-- product-card__price - цена товара -->
<button class="button button--primary js-add-to-cart">
<!-- button, button--primary - классы для оформления кнопки -->
<!-- js-add-to-cart - класс для JavaScript (обработчик клика) -->
Добавить в корзину
</button>
<p class="product-card__status is-hidden">
<!-- product-card__status - текст статуса -->
<!-- is-hidden - состояние "скрыт" -->
Товар добавлен в корзину
</p>
</div>
CSS:
.product-card {
border: 1px solid #e0e0e0; /* Рамка вокруг карточки */
padding: 16px; /* Внутренние отступы */
border-radius: 8px; /* Скругленные углы */
width: 260px; /* Фиксированная ширина */
}
.product-card__image {
width: 100%; /* Картинка растягивается на всю ширину карточки */
height: auto; /* Высота подстраивается пропорционально */
margin-bottom: 8px; /* Отступ снизу */
}
.product-card__title {
font-size: 16px;
margin: 8px 0;
}
.product-card__price {
font-weight: 700; /* Жирный текст цены */
margin-bottom: 12px;
}
.button {
padding: 8px 16px;
border-radius: 4px;
border: none;
cursor: pointer;
}
.button--primary {
background-color: #007bff; /* Синий фон */
color: #ffffff; /* Белый текст */
}
.product-card__status {
margin-top: 8px;
font-size: 14px;
color: #28a745; /* Зеленый цвет для положительного статуса */
}
.is-hidden {
display: none; /* Полностью скрываем элемент */
}
JavaScript:
// Находим все кнопки добавления в корзину по классу js-add-to-cart
const addToCartButtons = document.querySelectorAll('.js-add-to-cart');
// Перебираем найденные кнопки
addToCartButtons.forEach((button) => {
// Для каждой кнопки ищем родительский .product-card
const card = button.closest('.product-card');
// Внутри карточки ищем элемент статуса
const status = card.querySelector('.product-card__status');
// Вешаем обработчик клика на кнопку
button.addEventListener('click', () => {
// Удаляем класс is-hidden у статуса, чтобы показать сообщение
status.classList.remove('is-hidden');
});
});
Комментарии:
// document.querySelectorAll('.js-add-to-cart')
// Ищем все элементы, у которых есть класс js-add-to-cart
// button.closest('.product-card')
// Поднимаемся по дереву DOM к ближайшему родителю с классом product-card
// card.querySelector('.product-card__status')
// Ищем внутри карточки элемент с классом product-card__status
// status.classList.remove('is-hidden')
// Управляем классами состояния через classList
Здесь вы видите, как через атрибут class связываются сразу три слоя:
- HTML-структура (блоки и элементы);
- CSS-оформление;
- JavaScript-поведение.
Заключение
Атрибут class в HTML — это не просто способ "что-то покрасить". Это основной механизм связи между разметкой, стилями и поведением. От того, насколько аккуратно вы им пользуетесь, напрямую зависит читаемость кода, простота поддержки и возможность масштабировать проект.
Ключевые моменты, которые важно помнить:
- class можно использовать многократно и сочетать несколько классов на одном элементе;
- пробел в значении class разделяет разные классы;
- имена классов должны быть осмысленными и последовательными;
- классы — это хороший инструмент для:
- группировки элементов;
- управления состояниями;
- реализации тем оформления;
- взаимодействия с JavaScript;
- системы именования (например, БЭМ) сильно помогают удерживать структуру кода в порядке;
- лучше разделять классы для стилей и для поведения (
buttonиjs-open-modal), чтобы не мешать эти задачи.
Если вы выстроите понятную систему классов с самого начала, работа с CSS и JavaScript станет значительно проще, а верстка — более предсказуемой и устойчивой к изменениям.
Частозадаваемые технические вопросы по теме и ответы
Как добавить класс к элементу динамически на стороне сервера (например, в шаблонизаторе)?
Обычно шаблонизаторы позволяют собирать строку классов в зависимости от условий. Например, в шаблоне:
<div class="card {{ isFeatured ? 'card--featured' : '' }}">
...
</div>
Комментарии в общем виде:
- используйте условные выражения, чтобы добавлять модификаторы (
card--featured,is-active); - следите, чтобы между классами оставался пробел, иначе склеите имена в одно;
- для сложных условий лучше формировать массив классов и затем объединять его через пробел (возможности зависят от конкретного шаблонизатора).
Как проверить, какие классы у элемента сейчас есть через JavaScript?
Используйте свойство element.className или element.classList.
Пример:
const el = document.querySelector('.some-element');
// Получить строку классов
console.log(el.className);
// Проверить наличие конкретного класса
if (el.classList.contains('is-active')) {
// Выполнить действие, если элемент активен
}
Комментарии:
classNameвернет строку всех классов через пробел;classList.containsудобен именно для проверки наличия конкретного класса.
Как избежать конфликтов классов при подключении сторонних библиотек CSS?
Рекомендации:
- используйте "пространство имен" — префиксы в классах:
app-,my-,proj-(например,app-button); - оборачивайте свой код в корневой класс, а внутри пишите селекторы с уточнением:
.my-app .button { ... }; - по возможности знакомьтесь со схемой именования библиотек (Bootstrap, Tailwind и т.п.), чтобы не использовать такие же имена для своих компонентов.
Можно ли менять class напрямую через атрибут в JavaScript, а не через classList?
Да, вы можете работать со строкой className:
const el = document.querySelector('.item');
// Полностью заменить список классов
el.className = 'item item--active';
Но такой подход перезапишет все классы. Для добавления или удаления отдельных классов безопаснее использовать classList.add, classList.remove, classList.toggle, чтобы не потерять другие существующие классы.
Как лучше организовать классы при использовании CSS-фреймворков (Bootstrap, Tailwind)?
Общие советы:
- отделяйте "фреймворковые" классы от своих — например, свои начинайте с префикса (
app-), а классы фреймворка оставляйте как есть; - для сложных компонентов создавайте собственные обертки с классами (
app-card), а внутри уже используйте утилитарные классы фреймворка; - не смешивайте в одном элементе десятки утилитарных классов и собственных классов без системы — если разметка становится трудно читаемой, выносите часть стилей в отдельный CSS-класс.
Постройте личный план изучения Html до уровня Middle — бесплатно!
Html — часть карты развития Frontend
100+ шагов развития
30 бесплатных лекций
300 бонусных рублей на счет
Все гайды по Html
Лучшие курсы по теме

HTML и CSS
Антон Ларичев
TypeScript с нуля
Антон Ларичев