CSS

Модуль 2: CSS

Разберём синтаксис и способы подключения CSS, каскадность и специфичность, типографику, модель коробки, позиционирование, Flexbox, Grid, адаптивность и анимации.

Введение в CSS. Синтаксис и подключение

CSS (Cascading Style Sheets — каскадные таблицы стилей) — это язык, который управляет внешним видом и оформлением HTML-элементов. Если HTML — это скелет страницы, то CSS — это её "кожа и одежда", которая делает страницу красивой и привлекательной.

Что такое CSS и зачем он нужен

CSS позволяет:

  • Изменять цвета, шрифты, размеры элементов
  • Создавать макеты и расположение элементов на странице
  • Добавлять анимации и интерактивные эффекты
  • Делать страницы адаптивными для разных устройств
  • Создавать единый стиль для всего сайта

Преимущества отделения стилей от структуры:

  • Один CSS-файл может стилизовать множество HTML-страниц
  • Легко изменить дизайн всего сайта, изменив один файл
  • HTML остаётся чистым и семантическим
  • Браузер может кэшировать CSS-файлы, ускоряя загрузку

Синтаксис CSS

CSS состоит из правил (rules). Каждое правило имеет следующую структуру:

селектор {
    свойство: значение;
    другое-свойство: другое-значение;
}

Компоненты правила:

  • Селектор — указывает, к каким элементам применяется правило
  • Декларация — пара "свойство: значение" в фигурных скобках
  • Свойство — что мы хотим изменить (цвет, размер, отступ и т.д.)
  • Значение — как мы это изменяем (конкретный цвет, размер в пикселях и т.д.)
/* Пример правила */
h1 {
    color: #4f46e5;        /* свойство: значение; */
    font-size: 2rem;        /* каждое свойство на новой строке */
    margin-bottom: 1rem;   /* точка с запятой обязательна */
}

Способы подключения CSS

Есть три способа добавить CSS к HTML-странице. Каждый имеет свои преимущества и недостатки.

1. Встроенные стили (inline styles)

Стили пишутся прямо в атрибуте style HTML-элемента:

<h1 style="color: #4f46e5; font-size: 2rem;">Заголовок</h1>

Когда использовать: только для одноразовых стилей, которые уникальны для конкретного элемента и не будут переиспользоваться.

Минусы: нарушает принцип разделения структуры и стилей, сложно поддерживать, увеличивает размер HTML, нельзя переиспользовать стили.

Рекомендация: избегайте встроенных стилей, используйте только в крайних случаях (динамические стили через JavaScript, email-верстка).

2. Внутренние стили (embedded styles)

Стили пишутся в теге <style> внутри <head>:

<head>
    <style>
        h1 { 
            color: #4f46e5; 
            font-size: 2rem; 
        }
        .card {
            border-radius: 10px;
            padding: 1rem;
        }
    </style>
</head>

Когда использовать: для стилей, специфичных для одной страницы, для критического CSS (стили, необходимые для первого рендера).

Минусы: стили не переиспользуются между страницами, увеличивают размер HTML-файла.

Рекомендация: используйте для критического CSS или одностраничных приложений.

3. Внешний файл (external stylesheet) — РЕКОМЕНДУЕТСЯ

Стили находятся в отдельном .css файле и подключаются через <link>:

<head>
    <link rel="stylesheet" href="../courses.css">
    <!-- или несколько файлов -->
    <link rel="stylesheet" href="reset.css">
    <link rel="stylesheet" href="main.css">
</head>

Преимущества:

  • Разделение структуры и стилей
  • Переиспользование стилей на множестве страниц
  • Кэширование браузером — файл загружается один раз
  • Легче поддерживать и изменять
  • Можно использовать препроцессоры (Sass, Less)

Рекомендация: это основной и предпочтительный способ подключения CSS.

Селекторы: как выбрать элементы для стилизации

Селекторы — это способ указать браузеру, к каким элементам применить стили. Понимание селекторов — основа работы с CSS.

Базовые селекторы

1. Селектор по тегу (элементу)

/* Стилизует все параграфы */
p { 
    line-height: 1.7; 
    margin-bottom: 1rem;
}

/* Стилизует все заголовки h1 */
h1 { 
    font-size: 2rem; 
    font-weight: 700;
}

Используется для базовых стилей, которые применяются ко всем элементам определённого типа.

2. Селектор по классу

/* Стилизует все элементы с классом "card" */
.card { 
    border-radius: 10px; 
    padding: 1.5rem;
    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
<div class="card">Карточка 1</div>
<div class="card">Карточка 2</div>

Классы — самый гибкий и переиспользуемый способ стилизации. Один класс можно применять к множеству элементов.

3. Селектор по ID

/* Стилизует элемент с id="mainTitle" */
#mainTitle { 
    font-weight: 700; 
    color: #1e293b;
}
<h1 id="mainTitle">Главный заголовок</h1>

Важно: ID должен быть уникальным на странице. Используйте ID для уникальных элементов, но предпочитайте классы для стилизации (они более гибкие).

Комбинированные селекторы

Селектор потомков — выбирает элементы внутри других:

/* Все ссылки внутри навигации */
nav a { 
    text-decoration: none; 
    color: #4f46e5;
}

/* Все параграфы внутри .card */
.card p {
    margin-bottom: 0.5rem;
}

Псевдоклассы — выбирают элементы в определённом состоянии:

/* Ссылка при наведении */
a:hover { 
    text-decoration: underline; 
    color: #6366f1;
}

/* Последний элемент списка */
li:last-child {
    margin-bottom: 0;
}

/* Чётные строки таблицы */
tr:nth-child(even) {
    background-color: #f8fafc;
}

/* Первая буква параграфа */
p::first-letter {
    font-size: 2em;
    font-weight: bold;
}

Группировка селекторов — применяйте одно правило к нескольким селекторам:

/* Одинаковые стили для h1, h2, h3 */
h1, h2, h3 {
    font-family: 'Montserrat', sans-serif;
    margin-bottom: 1rem;
}

Практические советы по селекторам

  • Используйте классы для переиспользуемых стилей
  • Избегайте глубокой вложенности (более 2-3 уровней) — это увеличивает специфичность и усложняет поддержку
  • Именуйте классы осмысленно: .button-primary лучше, чем .btn1
  • Не используйте ID для стилизации — только для уникальных элементов и JavaScript
  • Используйте семантические селекторы: article h2 лучше, чем .article-title в некоторых случаях

Практика

Подключите внешний CSS-файл к вашей HTML-странице и создайте стили для:

  • Заголовков разных уровней (h1-h3) с разными размерами и цветами
  • Класса .card с рамкой, скруглением и тенью
  • Ссылок с эффектом при наведении (hover)
  • Списков с кастомными маркерами

Экспериментируйте с разными селекторами и посмотрите, как они работают.

Каскадность, наследование и специфичность

Понимание каскадности, наследования и специфичности — это основа работы с CSS. Эти концепции определяют, какие стили будут применены к элементу, когда несколько правил конфликтуют друг с другом.

Каскадность (Cascade)

CSS называется "каскадным" потому, что стили применяются в определённом порядке, как водопад. Когда несколько правил могут применяться к одному элементу, браузер использует каскад для определения приоритета.

Порядок применения стилей (от низкого к высокому приоритету):

  1. Стили браузера (user agent stylesheet) — базовые стили, которые браузер применяет по умолчанию
  2. Пользовательские стили — стили, установленные пользователем в браузере
  3. Авторские стили — ваши CSS-файлы
  4. Стили с !important — имеют наивысший приоритет (избегайте их использования)

В рамках одного источника: если два правила имеют одинаковую специфичность, применяется то, которое идёт ниже в коде (позже в файле).

/* Первое правило */
h1 { color: black; }

/* Второе правило — оно применится, так как идёт ниже */
h1 { color: blue; }
/* Результат: h1 будет синим */

Наследование (Inheritance)

Некоторые CSS-свойства наследуются дочерними элементами от родительских. Это означает, что если вы задали цвет текста для <body>, все элементы внутри унаследуют этот цвет, если не переопределить его явно.

Свойства, которые наследуются:

  • color — цвет текста
  • font-family, font-size, font-weight — свойства шрифта
  • line-height — межстрочный интервал
  • text-align — выравнивание текста
  • list-style — стиль списков

Свойства, которые НЕ наследуются:

  • width, height — размеры
  • margin, padding — отступы
  • border — рамки
  • background — фон
  • display — тип отображения
/* Задаём базовые стили для body */
body {
    color: #1e293b;           /* наследуется всеми элементами */
    font-family: 'Arial', sans-serif;  /* наследуется */
    line-height: 1.6;         /* наследуется */
    margin: 0;                /* НЕ наследуется */
    padding: 0;               /* НЕ наследуется */
}

/* Все параграфы унаследуют color, font-family, line-height */
/* Но margin и padding нужно задавать отдельно */

Принудительное наследование: можно заставить свойство наследоваться, используя значение inherit:

.card {
    border: 1px solid #e5e7eb;
}

.card a {
    border: inherit;  /* наследует border от .card */
}

Специфичность (Specificity) — вес селектора

Специфичность определяет, какое правило применится, когда несколько правил могут стилизовать один элемент. Браузер вычисляет "вес" каждого селектора и применяет правило с наибольшим весом.

Как вычисляется специфичность

Специфичность вычисляется по формуле: (a, b, c, d)

  • a — inline стили (style="...") = 1000
  • b — количество ID в селекторе = 100 за каждый
  • c — количество классов, атрибутов, псевдоклассов = 10 за каждый
  • d — количество тегов и псевдоэлементов = 1 за каждый
/* Примеры специфичности */

/* (0, 0, 0, 1) = 1 */
p { color: black; }

/* (0, 0, 1, 0) = 10 */
.card { color: blue; }

/* (0, 1, 0, 0) = 100 */
#mainTitle { color: green; }

/* (0, 0, 2, 1) = 21 */
.card .title { color: red; }

/* (1, 0, 0, 0) = 1000 */
/* style="color: purple;" в HTML */

Правило: чем больше число, тем выше специфичность. При конфликте применяется правило с большей специфичностью.

/* Конфликт стилей */
h1 { color: black; }          /* специфичность: 1 */
.title { color: blue; }        /* специфичность: 10 */
#mainTitle { color: green; }   /* специфичность: 100 */
/* Победит зелёный (id имеет большую специфичность) */

Важно понимать:

  • Специфичность не складывается линейно: (0, 0, 11, 0) = 110, что больше, чем (0, 1, 0, 0) = 100
  • !important переопределяет всё, но его использование — плохая практика
  • Старайтесь поддерживать низкую специфичность — это упрощает поддержку кода
  • Избегайте селекторов по ID для стилизации — они создают высокую специфичность

Единицы измерения в CSS

CSS предоставляет множество единиц измерения. Правильный выбор единиц критически важен для адаптивности и поддержки.

Абсолютные единицы

  • px (пиксели) — самая распространённая единица. 1px = 1 пиксель экрана. Используйте для мелких деталей (рамки, тени), но не для размеров шрифтов и отступов в адаптивных макетах.
  • pt (пункты) — используется в печати, 1pt = 1/72 дюйма
  • cm, mm, in — сантиметры, миллиметры, дюймы. Используются редко, в основном для печати

Относительные единицы (рекомендуются)

1. rem (root em) — относительно размера шрифта корневого элемента (<html>):

html { font-size: 16px; }  /* базовый размер */
h1 { font-size: 2rem; }   /* = 32px (2 × 16px) */
p { font-size: 1rem; }     /* = 16px (1 × 16px) */
.card { padding: 1.5rem; } /* = 24px (1.5 × 16px) */

Преимущества: предсказуемость, легко масштабировать весь сайт, изменяя размер шрифта у html.

Когда использовать: для размеров шрифтов, отступов, размеров элементов. Рекомендуется как основная единица.

2. em — относительно размера шрифта родительского элемента:

.card { font-size: 18px; }
.card .title { font-size: 1.5em; }  /* = 27px (1.5 × 18px) */
.card .small { font-size: 0.875em; } /* = 15.75px (0.875 × 18px) */

Особенность: может создавать каскадный эффект, когда вложенные элементы умножают размеры. Используйте осторожно.

Когда использовать: когда нужно, чтобы размер зависел от родителя (например, отступы относительно размера шрифта элемента).

3. % (проценты) — относительно размера родительского элемента:

.container { width: 1200px; }
.box { width: 50%; }  /* = 600px (50% от 1200px) */

Когда использовать: для ширины, высоты, отступов относительно родителя. Отлично подходит для адаптивных макетов.

4. vw, vh (viewport units) — относительно размера окна браузера:

.hero { 
    height: 60vh;  /* 60% высоты окна браузера */
    width: 100vw;  /* 100% ширины окна */
}
.sidebar { width: 25vw; }  /* 25% ширины окна */

Когда использовать: для полноэкранных секций, адаптивных размеров относительно экрана.

Осторожно: на мобильных устройствах 100vw может создать горизонтальную прокрутку из-за полосы прокрутки. Используйте 100% вместо 100vw для ширины.

5. vmin, vmax — минимальный/максимальный размер viewport:

.square { 
    width: 50vmin;   /* 50% от меньшей стороны (ширина или высота) */
    height: 50vmin;  /* всегда квадрат */
}

Современные единицы

  • ch — ширина символа "0" в текущем шрифте. Полезно для ограничения ширины текста
  • lh — высота строки (line-height) текущего элемента
  • cqw, cqh — единицы контейнерных запросов (container queries)

Практические рекомендации

  • Для шрифтов: используйте rem — предсказуемо и масштабируемо
  • Для отступов: используйте rem для вертикальных отступов, % или rem для горизонтальных
  • Для ширины контейнеров: используйте %, max-width с px или rem
  • Для высоты: используйте vh для полноэкранных секций, auto или rem для остального
  • Избегайте: смешивания единиц без необходимости, использования px для всего в адаптивных макетах
/* Хороший пример использования единиц */
:root {
    font-size: 16px;  /* базовый размер */
}

.container {
    max-width: 1200px;  /* фиксированная максимальная ширина */
    width: 100%;        /* адаптивная ширина */
    padding: 1.5rem;    /* адаптивные отступы */
}

h1 {
    font-size: 2.5rem;  /* = 40px */
    margin-bottom: 1rem; /* = 16px */
}

.card {
    width: 100%;        /* адаптивная ширина */
    padding: 1.25rem;   /* адаптивные внутренние отступы */
    border: 1px solid;  /* 1px всегда 1px */
}

Практика

Создайте страницу и поэкспериментируйте с единицами:

  • Используйте rem для размеров шрифтов и отступов
  • Создайте контейнер с max-width: 1200px и width: 100%
  • Используйте vh для создания полноэкранной секции
  • Сравните результат при изменении размера шрифта в браузере (Ctrl + колесо мыши)

Работа с текстом и шрифтами

Базовые свойства

body { font-family: 'Montserrat', system-ui, sans-serif; line-height: 1.7; }
h1 { font-size: 2rem; font-weight: 700; text-align: center; }
a { text-decoration: none; }
a:hover { text-decoration: underline; }

Подключение Google Fonts

<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;600;700&display=swap" rel="stylesheet">

Практика

Задайте базовую типографику для портфолио: шрифты, размеры и межстрочные интервалы для заголовков/текста.

Модель коробки (Box Model)

Каждый элемент — прямоугольник: content + padding + border + margin.

.card {
  width: 300px; /* ширина content */
  padding: 16px; /* внутренние отступы */
  border: 1px solid #e5e7eb; /* рамка */
  margin: 12px auto; /* внешние отступы */
  box-sizing: border-box; /* включает padding и border в width */
}

Практика

Сверстайте 3 карточки проекта: выровняйте по сетке, примените отступы, рамки и скругления.

Позиционирование элементов

.parent { position: relative; }
.child { position: absolute; top: 8px; right: 8px; }
.fixed-banner { position: fixed; bottom: 16px; right: 16px; }
.sticky-header { position: sticky; top: 0; }

Практика

Сделайте липкую шапку и значок (badge) в правом верхнем углу карточки через absolute.

Flexbox

.row {
  display: flex;
  gap: 16px;
  justify-content: space-between; /* выравнивание по главной оси */
  align-items: center;            /* выравнивание по поперечной оси */
}
.card { flex: 1 1 300px; }

Практика

Сверстайте горизонтальное меню и сетку карточек на Flexbox с переносом строк.

Grid Layout

.gallery {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}
.item:nth-child(1) { grid-column: span 2; }

Практика

Сделайте фотогалерею 3×N, одну из карточек растяните на 2 колонки.

Адаптивная верстка и медиазапросы

Mobile‑First: сначала стили для мобильных, затем усложняем для больших экранов.

.container { padding: 16px; }
@media (min-width: 768px) {
  .container { max-width: 720px; margin: 0 auto; }
}
@media (min-width: 1024px) {
  .container { max-width: 960px; }
}

Практика

Сделайте главную портфолио адаптивной: навигация, сетки карточек, отступы.

Трансформации, переходы и анимации

.btn { transition: transform .2s ease, box-shadow .2s ease; }
.btn:hover { transform: translateY(-2px); box-shadow: 0 8px 16px rgba(0,0,0,.1); }
@keyframes pulse { from { transform: scale(1); } to { transform: scale(1.05); } }
.card:hover { animation: pulse .8s ease-in-out alternate; }

Практика

Добавьте hover‑эффекты кнопкам и карточкам, анимируйте появление элементов.

Flexbox — углублённо

Разбираемся с алгоритмом распределения пространства, переносом строк и выравниванием многострочных рядов.

.row { display: flex; flex-wrap: wrap; gap: clamp(12px, 2vw, 24px); }
.card { flex: 1 1 clamp(220px, 30%, 360px); min-width: 220px; }
.row { align-content: start; /* выравнивание нескольких рядов */ }
.card { align-self: stretch; }

Известные ловушки

  • Сжатие контента: используйте min-width и min-height.
  • Неожиданное выравнивание — различайте align-items и align-content.

Grid — углублённо

Шаблоны областей, автоматическое размещение, функции minmax(), fit-content(), subgrid.

.layout {
  display: grid;
  grid-template-columns: [full-start] 1fr [content-start] minmax(0, 1200px) [content-end] 1fr [full-end];
}
.layout > * { grid-column: content; }
.gallery { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 16px; }
.article { display: grid; grid-template-columns: 1fr 320px; grid-template-rows: auto 1fr; grid-template-areas:
  'title aside' 'content aside'; }
.article__title { grid-area: title; }
.article__content { grid-area: content; }
.article__aside { grid-area: aside; }

Subgrid: позволяет наследовать линии родителя для вложенных сеток (поддержка в современных браузерах).

Архитектуры CSS: БЭМ, ITCSS, Utility‑first

БЭМ

Именование: block__element--modifier. Пример: card, card__title, card--featured.

.card { /* блок */ }
.card__title { /* элемент */ }
.card--featured { /* модификатор */ }

ITCSS

Слои: Settings → Tools → Generic → Elements → Objects → Components → Utilities. От абстрактного к конкретному, уменьшает специфичность.

Правила поддержки

  • Минимизируйте специфичность: избегайте селекторов по id, вложенности > 2 уровней.
  • Компонентный подход: каждый блок изолирован, стили живут рядом.
  • Используйте design tokens через :root и CSS Custom Properties.
:root { --space-1: 8px; --space-2: 12px; --brand: #4f46e5; }
.button { padding: var(--space-1) var(--space-2); background: var(--brand); }

Адаптив: контейнерные запросы, ретина, медиа

Container Queries

.card-grid { container-type: inline-size; }
.card { display: grid; grid-template-columns: 1fr; }
@container (min-width: 480px) {
  .card { grid-template-columns: 1fr 1fr; }
}

Ретина и качество

  • image-set() для фоновых изображений; srcset для <img>.
  • Используйте aspect-ratio, указывайте width/height у медиа для предотвращения CLS.

Производительность CSS

  • Критический CSS: инлайните ключевые стили в <head>, остальное отложенно.
  • Избегайте тяжёлых теней и анимаций layout/paint; анимируйте transform и opacity.

Итоговый проект модуля 2

Полностью стилизуйте главную портфолио‑страницу: сетки (Flex/Grid), адаптивность, типографика, интерактивные hover‑эффекты.

  • Навигация (desktop/mobile), секции «Проекты» (карточки), «Контакты» (форма)
  • Светлая/тёмная темы — по желанию
  • Анимации появления элементов при наведении/прокрутке

Настройки

Цветовая схема

Тема