← HTML & CSS/Селекторы CSS#17 из 383← ПредыдущийСледующий →+10 XP
Полезно по теме:Гайд: старт в frontendПрактика: DOM и событияТермин: DOMМаршрут: старт с нуля

Селекторы CSS

Селектор — это способ сказать браузеру: «применяй эти стили вот к этим элементам». Без селекторов CSS не знал бы, к чему применять оформление. Это как адрес на конверте: письмо (стиль) должно знать, кому доставить.

Тег-селектор

Применяет стили ко всем элементам с данным тегом.

p { color: #333; }       /* Все параграфы */
button { cursor: pointer; }  /* Все кнопки */
h1 { font-size: 32px; }  /* Все заголовки h1 */

Удобно для базовых стилей, но слишком грубо для сложных интерфейсов.

Классовый селектор (.class)

Самый используемый в реальных проектах. Точка перед именем — признак класса.

.card { border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
.btn-primary { background: #7b2ff7; color: white; }
.active { border: 2px solid blue; }

Один элемент может иметь несколько классов: <div class="card active featured">

ID-селектор (#id)

Применяется к единственному элементу с данным id. Решётка перед именем.

#header { position: fixed; top: 0; width: 100%; }
#cart-count { background: red; color: white; border-radius: 50%; }

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

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

Потомок (пробел) — элемент внутри другого на любой глубине

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

Дочерний (>) — только прямые дети

.menu > li { display: inline-block; }  /* Только li, прямые дети .menu */

Несколько селекторов (запятая) — одни стили для разных элементов

h1, h2, h3 { font-family: 'Georgia', serif; }
.btn-primary, .btn-secondary { padding: 10px 20px; border-radius: 6px; }

Соседний (+) и общий (~) сиблинги

h2 + p { margin-top: 0; }    /* p сразу после h2 */
h2 ~ p { color: #444; }      /* все p после h2 в том же родителе */

Атрибутные селекторы

input[type="text"] { border: 1px solid #ccc; }
input[type="checkbox"] { width: 16px; }
a[href^="https"] { color: green; }   /* ссылки, начинающиеся с https */
a[href$=".pdf"] { color: red; }      /* ссылки, заканчивающиеся на .pdf */
[data-theme="dark"] { background: #1a1a1a; } /* по data-атрибуту */

Универсальный селектор (*)

* { box-sizing: border-box; margin: 0; padding: 0; }

Часто используется для глобального сброса стилей в начале CSS-файла.

Типичные ошибки

Ошибка 1: Пробел между тегом и классом

div .card { }   /* Ищет .card ВНУТРИ div — не то же самое! */
div.card { }    /* Div с классом card — правильно */

Ошибка 2: Слишком длинные цепочки

/* Плохо — хрупко и трудно читать */
.page .section .container .row .col .card .card-body p { }

/* Хорошо — короткие, конкретные */
.card-body p { }

Ошибка 3: Злоупотребление ID

#submit-button { }  /* Плохо — невозможно переиспользовать */
.btn-submit { }     /* Хорошо — класс можно применить к нескольким кнопкам */

В реальных проектах

В React-проектах с CSS Modules имена классов автоматически генерируются уникальными: .card__title превращается в .Card_title__x7k2f. В Tailwind CSS ты вообще не пишешь селекторы — используешь готовые классы-утилиты. Но под капотом всё равно работают те же механизмы выбора элементов.

BEM-методология называет классы по схеме блок__элемент--модификатор: .card__title--large. Это самое популярное соглашение об именах в больших CSS-проектах.

Примеры

Работа с классами и селекторами через JavaScript DOM API

// Создаём структуру: карточка с заголовком и описанием
const styleTag = document.createElement('style')
styleTag.textContent = `
  .card { border: 1px solid #ddd; border-radius: 12px; padding: 16px; margin: 8px; }
  .card.featured { border-color: #7b2ff7; box-shadow: 0 2px 12px rgba(123,47,247,0.2); }
  .card__title { font-size: 18px; font-weight: bold; color: #111; }
  .card__title--sale { color: #e53e3e; }
  .card p { color: #666; font-size: 14px; }
`
document.head.appendChild(styleTag)

// Обычная карточка
const card1 = document.createElement('div')
card1.className = 'card'

const title1 = document.createElement('h3')
title1.className = 'card__title'
title1.textContent = 'Кроссовки Nike'

const desc1 = document.createElement('p')
desc1.textContent = 'Размер 42, белые'

card1.appendChild(title1)
card1.appendChild(desc1)
document.body.appendChild(card1)

// Карточка со скидкой (featured + sale)
const card2 = document.createElement('div')
card2.className = 'card featured'  // несколько классов

const title2 = document.createElement('h3')
title2.className = 'card__title card__title--sale'  // BEM модификатор
title2.textContent = 'Кроссовки Adidas -30%'

card2.appendChild(title2)
document.body.appendChild(card2)

// Проверяем классы через classList API
console.log('card1 классы:', card1.className)
console.log('card2 классы:', card2.className)
console.log('card2 — featured?', card2.classList.contains('featured'))  // true
console.log('card1 — featured?', card1.classList.contains('featured'))  // false

// Динамически добавляем/удаляем класс
card1.classList.add('featured')
console.log('После добавления featured:', card1.classList.contains('featured'))  // true

card1.classList.remove('featured')
card1.classList.toggle('featured')  // добавит, если нет
console.log('После toggle:', card1.classList.contains('featured'))  // true

// querySelector использует те же селекторы что и CSS
const allCards = document.querySelectorAll('.card')
console.log('Количество карточек:', allCards.length)  // 2

const featuredCard = document.querySelector('.card.featured')
console.log('Есть featured карточка:', featuredCard !== null)  // true

Селекторы CSS

Селектор — это способ сказать браузеру: «применяй эти стили вот к этим элементам». Без селекторов CSS не знал бы, к чему применять оформление. Это как адрес на конверте: письмо (стиль) должно знать, кому доставить.

Тег-селектор

Применяет стили ко всем элементам с данным тегом.

p { color: #333; }       /* Все параграфы */
button { cursor: pointer; }  /* Все кнопки */
h1 { font-size: 32px; }  /* Все заголовки h1 */

Удобно для базовых стилей, но слишком грубо для сложных интерфейсов.

Классовый селектор (.class)

Самый используемый в реальных проектах. Точка перед именем — признак класса.

.card { border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
.btn-primary { background: #7b2ff7; color: white; }
.active { border: 2px solid blue; }

Один элемент может иметь несколько классов: <div class="card active featured">

ID-селектор (#id)

Применяется к единственному элементу с данным id. Решётка перед именем.

#header { position: fixed; top: 0; width: 100%; }
#cart-count { background: red; color: white; border-radius: 50%; }

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

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

Потомок (пробел) — элемент внутри другого на любой глубине

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

Дочерний (>) — только прямые дети

.menu > li { display: inline-block; }  /* Только li, прямые дети .menu */

Несколько селекторов (запятая) — одни стили для разных элементов

h1, h2, h3 { font-family: 'Georgia', serif; }
.btn-primary, .btn-secondary { padding: 10px 20px; border-radius: 6px; }

Соседний (+) и общий (~) сиблинги

h2 + p { margin-top: 0; }    /* p сразу после h2 */
h2 ~ p { color: #444; }      /* все p после h2 в том же родителе */

Атрибутные селекторы

input[type="text"] { border: 1px solid #ccc; }
input[type="checkbox"] { width: 16px; }
a[href^="https"] { color: green; }   /* ссылки, начинающиеся с https */
a[href$=".pdf"] { color: red; }      /* ссылки, заканчивающиеся на .pdf */
[data-theme="dark"] { background: #1a1a1a; } /* по data-атрибуту */

Универсальный селектор (*)

* { box-sizing: border-box; margin: 0; padding: 0; }

Часто используется для глобального сброса стилей в начале CSS-файла.

Типичные ошибки

Ошибка 1: Пробел между тегом и классом

div .card { }   /* Ищет .card ВНУТРИ div — не то же самое! */
div.card { }    /* Div с классом card — правильно */

Ошибка 2: Слишком длинные цепочки

/* Плохо — хрупко и трудно читать */
.page .section .container .row .col .card .card-body p { }

/* Хорошо — короткие, конкретные */
.card-body p { }

Ошибка 3: Злоупотребление ID

#submit-button { }  /* Плохо — невозможно переиспользовать */
.btn-submit { }     /* Хорошо — класс можно применить к нескольким кнопкам */

В реальных проектах

В React-проектах с CSS Modules имена классов автоматически генерируются уникальными: .card__title превращается в .Card_title__x7k2f. В Tailwind CSS ты вообще не пишешь селекторы — используешь готовые классы-утилиты. Но под капотом всё равно работают те же механизмы выбора элементов.

BEM-методология называет классы по схеме блок__элемент--модификатор: .card__title--large. Это самое популярное соглашение об именах в больших CSS-проектах.

Примеры

Работа с классами и селекторами через JavaScript DOM API

// Создаём структуру: карточка с заголовком и описанием
const styleTag = document.createElement('style')
styleTag.textContent = `
  .card { border: 1px solid #ddd; border-radius: 12px; padding: 16px; margin: 8px; }
  .card.featured { border-color: #7b2ff7; box-shadow: 0 2px 12px rgba(123,47,247,0.2); }
  .card__title { font-size: 18px; font-weight: bold; color: #111; }
  .card__title--sale { color: #e53e3e; }
  .card p { color: #666; font-size: 14px; }
`
document.head.appendChild(styleTag)

// Обычная карточка
const card1 = document.createElement('div')
card1.className = 'card'

const title1 = document.createElement('h3')
title1.className = 'card__title'
title1.textContent = 'Кроссовки Nike'

const desc1 = document.createElement('p')
desc1.textContent = 'Размер 42, белые'

card1.appendChild(title1)
card1.appendChild(desc1)
document.body.appendChild(card1)

// Карточка со скидкой (featured + sale)
const card2 = document.createElement('div')
card2.className = 'card featured'  // несколько классов

const title2 = document.createElement('h3')
title2.className = 'card__title card__title--sale'  // BEM модификатор
title2.textContent = 'Кроссовки Adidas -30%'

card2.appendChild(title2)
document.body.appendChild(card2)

// Проверяем классы через classList API
console.log('card1 классы:', card1.className)
console.log('card2 классы:', card2.className)
console.log('card2 — featured?', card2.classList.contains('featured'))  // true
console.log('card1 — featured?', card1.classList.contains('featured'))  // false

// Динамически добавляем/удаляем класс
card1.classList.add('featured')
console.log('После добавления featured:', card1.classList.contains('featured'))  // true

card1.classList.remove('featured')
card1.classList.toggle('featured')  // добавит, если нет
console.log('После toggle:', card1.classList.contains('featured'))  // true

// querySelector использует те же селекторы что и CSS
const allCards = document.querySelectorAll('.card')
console.log('Количество карточек:', allCards.length)  // 2

const featuredCard = document.querySelector('.card.featured')
console.log('Есть featured карточка:', featuredCard !== null)  // true

Задание

Напиши HTML-страницу с тремя div-элементами. Первый — только класс item, второй — классы item и active (зелёный фон), третий — классы item и disabled (полупрозрачный). Используй разные типы CSS-селекторов: тег div, класс .item, комбинацию .item.active.

Подсказка

.item.active (без пробела) — оба класса на одном элементе. class="item active" — задаёт два класса. opacity: 0.5 делает элемент полупрозрачным. background: green или #38a169 для зелёного фона.

Загружаем среду выполнения...
Загружаем AI-помощника...