Кнопка, которая меняет цвет при наведении. Первый абзац с увеличенной буквой. Красная рамка у поля с ошибкой. Полоска под активным пунктом меню. Всё это делается без JavaScript — только с помощью псевдоклассов и псевдоэлементов CSS.
Псевдоклассы начинаются с одного двоеточия :. Они описывают состояние или позицию элемента.
/* :hover — при наведении мыши */
.btn:hover { background-color: #6b21d4; }
a:hover { text-decoration: underline; }
/* :focus — при фокусе (Tab или клик) */
input:focus { border-color: #7b2ff7; outline: 2px solid rgba(123,47,247,0.3); }
button:focus { outline: 3px solid #7b2ff7; }
/* :active — в момент нажатия */
.btn:active { transform: scale(0.97); }
/* :visited — посещённые ссылки */
a:visited { color: #6b21d4; }input:disabled { opacity: 0.5; cursor: not-allowed; }
input:checked { accent-color: #7b2ff7; }
input:invalid { border-color: #e53e3e; }
input:valid { border-color: #38a169; }
input:placeholder-shown { border-color: #e2e8f0; }
input:required { border-left: 3px solid #e53e3e; }/* Первый и последний дочерний элемент */
li:first-child { border-top: none; }
li:last-child { border-bottom: none; }
/* nth-child(n) — каждый n-й элемент */
tr:nth-child(even) { background: #f7fafc; } /* Чётные строки таблицы */
tr:nth-child(odd) { background: white; } /* Нечётные строки */
li:nth-child(3) { font-weight: bold; } /* Только третий */
li:nth-child(3n) { color: red; } /* Каждый третий */
/* Единственный ребёнок */
p:only-child { margin: 0; }
/* :not() — исключение */
.btn:not(.btn-disabled) { cursor: pointer; }
li:not(:last-child) { border-bottom: 1px solid #eee; }Псевдоэлементы начинаются с двух двоеточий ::. Они создают виртуальные дочерние элементы, которые не существуют в HTML.
Вставляют виртуальный элемент до/после содержимого. Требуют свойство content.
/* Значок перед ссылкой */
.external-link::after {
content: ' ↗';
font-size: 0.8em;
opacity: 0.7;
}
/* Декоративная линия под заголовком */
.section-title::after {
content: ''; /* Пустой контент — только для декора */
display: block;
width: 40px;
height: 3px;
background: #7b2ff7;
margin-top: 8px;
}
/* Счётчик */
.price::before {
content: '₽ ';
}
/* Кавычки для цитат */
blockquote::before { content: '«'; }
blockquote::after { content: '»'; }/* ::placeholder — стиль для placeholder текста */
input::placeholder {
color: #a0aec0;
font-style: italic;
}
/* ::selection — стиль выделения текста */
::selection {
background: #7b2ff7;
color: white;
}
/* ::first-line — первая строка текста */
p::first-line {
font-weight: bold;
font-size: 1.1em;
}.btn {
background: #7b2ff7;
transition: background 0.2s, transform 0.1s;
}
.btn:hover { background: #6b21d4; }
.btn:active { transform: scale(0.97); }
.btn:focus { outline: 3px solid rgba(123,47,247,0.4); outline-offset: 2px; }.nav-link { position: relative; }
.nav-link::after {
content: '';
position: absolute;
bottom: -2px;
left: 0;
width: 0;
height: 2px;
background: #7b2ff7;
transition: width 0.3s;
}
.nav-link:hover::after { width: 100%; }Ошибка 1: Забыть content у ::before/::after
.el::before { display: block; width: 10px; } /* Не отображается — нет content! */
.el::before { content: ''; display: block; width: 10px; } /* Работает */Ошибка 2: Одно двоеточие у псевдоэлементов
p:before { } /* Старый синтаксис, работает, но не стандарт */
p::before { } /* Правильно для CSS3+ */Ошибка 3: :nth-child считает от родителя, а не от типа
/* <div> <p> <span> <p> </div> */
p:nth-child(2) { } /* Выбирает <span>, потому что span — второй ребёнок div! */
p:nth-of-type(2) { } /* Выбирает второй <p> — правильно */Псевдоклассы — основа интерактивности без JavaScript. Hover-эффекты, состояния форм, полоска активной вкладки — всё это CSS. ::before и ::after часто заменяют лишние HTML-теги: декоративные линии, иконки, перекрытия (overlay).
Псевдоклассы через JavaScript: состояния, nth-child и псевдоэлементы
// CSS с псевдоклассами и псевдоэлементами
const style = document.createElement('style')
style.textContent = `
* { box-sizing: border-box; }
body { font-family: Arial, sans-serif; padding: 16px; }
/* Кнопка с состояниями */
.btn {
background: #7b2ff7;
color: white;
border: none;
padding: 10px 20px;
border-radius: 8px;
cursor: pointer;
font-size: 14px;
transition: background 0.2s, transform 0.1s;
margin: 4px;
}
.btn:hover { background: #6b21d4; }
.btn:active { transform: scale(0.97); }
.btn:focus { outline: 3px solid rgba(123,47,247,0.4); outline-offset: 2px; }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
/* Input с состояниями */
.input {
border: 2px solid #e2e8f0;
border-radius: 6px;
padding: 8px 12px;
font-size: 14px;
width: 200px;
display: block;
margin: 8px 0;
transition: border-color 0.2s;
}
.input:focus { border-color: #7b2ff7; outline: none; }
.input::placeholder { color: #a0aec0; font-style: italic; }
/* Список с nth-child */
.list { list-style: none; padding: 0; margin: 16px 0; }
.list li {
padding: 8px 12px;
border-bottom: 1px solid #e2e8f0;
}
.list li:nth-child(odd) { background: #f7fafc; }
.list li:first-child { border-radius: 8px 8px 0 0; font-weight: bold; }
.list li:last-child { border-bottom: none; border-radius: 0 0 8px 8px; }
.list li:not(:first-child):hover { background: #ebf4ff; cursor: pointer; }
/* Псевдоэлемент ::before для иконки */
.price::before { content: '₽ '; color: #718096; }
/* Декоративная линия через ::after */
.section-title {
display: inline-block;
font-weight: 700;
margin-bottom: 12px;
}
.section-title::after {
content: '';
display: block;
width: 100%;
height: 3px;
background: #7b2ff7;
margin-top: 4px;
border-radius: 2px;
}
`
document.head.appendChild(style)
// Создаём компоненты
const title = document.createElement('h3')
title.className = 'section-title'
title.textContent = 'Интерактивные кнопки'
document.body.appendChild(title)
const btn1 = document.createElement('button')
btn1.className = 'btn'
btn1.textContent = 'Активная'
const btn2 = document.createElement('button')
btn2.className = 'btn'
btn2.textContent = 'Неактивная'
btn2.disabled = true
document.body.appendChild(btn1)
document.body.appendChild(btn2)
// Инпут
const input = document.createElement('input')
input.className = 'input'
input.placeholder = 'Введите имя...'
input.type = 'text'
document.body.appendChild(input)
// Список с nth-child
const ul = document.createElement('ul')
ul.className = 'list'
;['Заголовок', 'Первый', 'Второй', 'Третий', 'Четвёртый'].forEach(text => {
const li = document.createElement('li')
li.textContent = text
ul.appendChild(li)
})
document.body.appendChild(ul)
// Цена с ::before
const price = document.createElement('div')
price.className = 'price'
price.style.fontSize = '20px'
price.style.fontWeight = '700'
price.textContent = '1 490'
document.body.appendChild(price)
// Логирование
console.log('btn1.disabled:', btn1.disabled) // false
console.log('btn2.disabled:', btn2.disabled) // true
console.log('Кол-во li:', ul.children.length) // 5
// Проверяем :nth-child через querySelectorAll
const oddItems = ul.querySelectorAll('li:nth-child(odd)')
console.log('Нечётных li:', oddItems.length) // 3 (1-й, 3-й, 5-й)Кнопка, которая меняет цвет при наведении. Первый абзац с увеличенной буквой. Красная рамка у поля с ошибкой. Полоска под активным пунктом меню. Всё это делается без JavaScript — только с помощью псевдоклассов и псевдоэлементов CSS.
Псевдоклассы начинаются с одного двоеточия :. Они описывают состояние или позицию элемента.
/* :hover — при наведении мыши */
.btn:hover { background-color: #6b21d4; }
a:hover { text-decoration: underline; }
/* :focus — при фокусе (Tab или клик) */
input:focus { border-color: #7b2ff7; outline: 2px solid rgba(123,47,247,0.3); }
button:focus { outline: 3px solid #7b2ff7; }
/* :active — в момент нажатия */
.btn:active { transform: scale(0.97); }
/* :visited — посещённые ссылки */
a:visited { color: #6b21d4; }input:disabled { opacity: 0.5; cursor: not-allowed; }
input:checked { accent-color: #7b2ff7; }
input:invalid { border-color: #e53e3e; }
input:valid { border-color: #38a169; }
input:placeholder-shown { border-color: #e2e8f0; }
input:required { border-left: 3px solid #e53e3e; }/* Первый и последний дочерний элемент */
li:first-child { border-top: none; }
li:last-child { border-bottom: none; }
/* nth-child(n) — каждый n-й элемент */
tr:nth-child(even) { background: #f7fafc; } /* Чётные строки таблицы */
tr:nth-child(odd) { background: white; } /* Нечётные строки */
li:nth-child(3) { font-weight: bold; } /* Только третий */
li:nth-child(3n) { color: red; } /* Каждый третий */
/* Единственный ребёнок */
p:only-child { margin: 0; }
/* :not() — исключение */
.btn:not(.btn-disabled) { cursor: pointer; }
li:not(:last-child) { border-bottom: 1px solid #eee; }Псевдоэлементы начинаются с двух двоеточий ::. Они создают виртуальные дочерние элементы, которые не существуют в HTML.
Вставляют виртуальный элемент до/после содержимого. Требуют свойство content.
/* Значок перед ссылкой */
.external-link::after {
content: ' ↗';
font-size: 0.8em;
opacity: 0.7;
}
/* Декоративная линия под заголовком */
.section-title::after {
content: ''; /* Пустой контент — только для декора */
display: block;
width: 40px;
height: 3px;
background: #7b2ff7;
margin-top: 8px;
}
/* Счётчик */
.price::before {
content: '₽ ';
}
/* Кавычки для цитат */
blockquote::before { content: '«'; }
blockquote::after { content: '»'; }/* ::placeholder — стиль для placeholder текста */
input::placeholder {
color: #a0aec0;
font-style: italic;
}
/* ::selection — стиль выделения текста */
::selection {
background: #7b2ff7;
color: white;
}
/* ::first-line — первая строка текста */
p::first-line {
font-weight: bold;
font-size: 1.1em;
}.btn {
background: #7b2ff7;
transition: background 0.2s, transform 0.1s;
}
.btn:hover { background: #6b21d4; }
.btn:active { transform: scale(0.97); }
.btn:focus { outline: 3px solid rgba(123,47,247,0.4); outline-offset: 2px; }.nav-link { position: relative; }
.nav-link::after {
content: '';
position: absolute;
bottom: -2px;
left: 0;
width: 0;
height: 2px;
background: #7b2ff7;
transition: width 0.3s;
}
.nav-link:hover::after { width: 100%; }Ошибка 1: Забыть content у ::before/::after
.el::before { display: block; width: 10px; } /* Не отображается — нет content! */
.el::before { content: ''; display: block; width: 10px; } /* Работает */Ошибка 2: Одно двоеточие у псевдоэлементов
p:before { } /* Старый синтаксис, работает, но не стандарт */
p::before { } /* Правильно для CSS3+ */Ошибка 3: :nth-child считает от родителя, а не от типа
/* <div> <p> <span> <p> </div> */
p:nth-child(2) { } /* Выбирает <span>, потому что span — второй ребёнок div! */
p:nth-of-type(2) { } /* Выбирает второй <p> — правильно */Псевдоклассы — основа интерактивности без JavaScript. Hover-эффекты, состояния форм, полоска активной вкладки — всё это CSS. ::before и ::after часто заменяют лишние HTML-теги: декоративные линии, иконки, перекрытия (overlay).
Псевдоклассы через JavaScript: состояния, nth-child и псевдоэлементы
// CSS с псевдоклассами и псевдоэлементами
const style = document.createElement('style')
style.textContent = `
* { box-sizing: border-box; }
body { font-family: Arial, sans-serif; padding: 16px; }
/* Кнопка с состояниями */
.btn {
background: #7b2ff7;
color: white;
border: none;
padding: 10px 20px;
border-radius: 8px;
cursor: pointer;
font-size: 14px;
transition: background 0.2s, transform 0.1s;
margin: 4px;
}
.btn:hover { background: #6b21d4; }
.btn:active { transform: scale(0.97); }
.btn:focus { outline: 3px solid rgba(123,47,247,0.4); outline-offset: 2px; }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
/* Input с состояниями */
.input {
border: 2px solid #e2e8f0;
border-radius: 6px;
padding: 8px 12px;
font-size: 14px;
width: 200px;
display: block;
margin: 8px 0;
transition: border-color 0.2s;
}
.input:focus { border-color: #7b2ff7; outline: none; }
.input::placeholder { color: #a0aec0; font-style: italic; }
/* Список с nth-child */
.list { list-style: none; padding: 0; margin: 16px 0; }
.list li {
padding: 8px 12px;
border-bottom: 1px solid #e2e8f0;
}
.list li:nth-child(odd) { background: #f7fafc; }
.list li:first-child { border-radius: 8px 8px 0 0; font-weight: bold; }
.list li:last-child { border-bottom: none; border-radius: 0 0 8px 8px; }
.list li:not(:first-child):hover { background: #ebf4ff; cursor: pointer; }
/* Псевдоэлемент ::before для иконки */
.price::before { content: '₽ '; color: #718096; }
/* Декоративная линия через ::after */
.section-title {
display: inline-block;
font-weight: 700;
margin-bottom: 12px;
}
.section-title::after {
content: '';
display: block;
width: 100%;
height: 3px;
background: #7b2ff7;
margin-top: 4px;
border-radius: 2px;
}
`
document.head.appendChild(style)
// Создаём компоненты
const title = document.createElement('h3')
title.className = 'section-title'
title.textContent = 'Интерактивные кнопки'
document.body.appendChild(title)
const btn1 = document.createElement('button')
btn1.className = 'btn'
btn1.textContent = 'Активная'
const btn2 = document.createElement('button')
btn2.className = 'btn'
btn2.textContent = 'Неактивная'
btn2.disabled = true
document.body.appendChild(btn1)
document.body.appendChild(btn2)
// Инпут
const input = document.createElement('input')
input.className = 'input'
input.placeholder = 'Введите имя...'
input.type = 'text'
document.body.appendChild(input)
// Список с nth-child
const ul = document.createElement('ul')
ul.className = 'list'
;['Заголовок', 'Первый', 'Второй', 'Третий', 'Четвёртый'].forEach(text => {
const li = document.createElement('li')
li.textContent = text
ul.appendChild(li)
})
document.body.appendChild(ul)
// Цена с ::before
const price = document.createElement('div')
price.className = 'price'
price.style.fontSize = '20px'
price.style.fontWeight = '700'
price.textContent = '1 490'
document.body.appendChild(price)
// Логирование
console.log('btn1.disabled:', btn1.disabled) // false
console.log('btn2.disabled:', btn2.disabled) // true
console.log('Кол-во li:', ul.children.length) // 5
// Проверяем :nth-child через querySelectorAll
const oddItems = ul.querySelectorAll('li:nth-child(odd)')
console.log('Нечётных li:', oddItems.length) // 3 (1-й, 3-й, 5-й)Создай список из 5 пунктов и стилизуй его псевдоклассами: нечётные строки (`:nth-child(odd)`) — светло-синий фон, последний пункт (`:last-child`) — красный цвет текста, первый пункт (`:first-child`) — жирный шрифт. Добавь кнопке эффект наведения через `:hover` и нажатия через `:active`.
`:nth-child(odd)` выбирает нечётные элементы: 1-й, 3-й, 5-й. Для чётного фона используй `#ebf4ff`. `:last-child` — последний элемент, задай `color: #e53e3e`. `:hover` — потемни фон кнопки, `:active` — уменьши через `scale(0.97)`.