CSS-псевдоэлементы в JavaScript: управление ::before и ::after
Для кого эта статья:
- Фронтенд-разработчики и веб-дизайнеры
- Студенты и специалисты, желающие улучшить навыки в CSS и JavaScript
Профессионалы, заинтересованные в оптимизации веб-интерфейсов и производительности сайтов
CSS-псевдоэлементы — невидимые герои современного веб-дизайна, позволяющие творить магию без захламления HTML-разметки. Но что делать, когда нужно манипулировать ими динамически через JavaScript? Эта область — болевая точка для многих разработчиков: прямое управление
::beforeи::afterчерез DOM невозможно. Но существуют элегантные обходные пути, которые превращают кажущиеся ограничения в новые возможности для создания по-настоящему отзывчивых и интерактивных интерфейсов. 🚀
Задумываетесь о профессиональном развитии в веб-разработке? Манипуляция псевдоэлементами — лишь малая часть навыков, которые должен освоить современный фронтенд-разработчик. В рамках курса Обучение веб-разработке от Skypro вы не просто изучите теоретические основы, но погрузитесь в практические задачи, включая продвинутые техники работы с DOM, CSS и JavaScript. Ваши интерфейсы станут динамичнее, а портфолио — привлекательнее для потенциальных работодателей.
Сущность псевдоэлементов CSS и их роль в веб-разработке
Псевдоэлементы — особые конструкции CSS, позволяющие стилизовать определённые части элемента без необходимости добавления дополнительных тегов в HTML. Наиболее часто используемые псевдоэлементы — ::before и ::after, но существуют и другие, например, ::first-letter, ::first-line, ::selection.
Псевдоэлементы ::before и ::after вставляют контент до или после содержимого элемента. Они представляют собой дочерние элементы выбранного элемента, что делает их мощным инструментом для декоративных эффектов.
Виктор Самойлов, технический директор
Мой первый серьезный проект включал создание интерфейса для финансовой панели управления. Клиент требовал минималистичный дизайн с интуитивно понятными индикаторами статуса. Вместо добавления избыточных спанов для отображения статусов транзакций, я использовал псевдоэлементы
::beforeс разными цветами и формами.Когда пришло время добавить анимацию при наведении, стало ясно, что
::beforeи::after— незаменимые инструменты. Мы сократили HTML-разметку на 30%, увеличили скорость загрузки и удовлетворили требования заказчика к чистоте кода. С тех пор я всегда предпочитаю использовать псевдоэлементы вместо дополнительных контейнеров, когда это возможно.
Основные характеристики псевдоэлементов:
- Не являются частью DOM — невидимы для JavaScript напрямую
- Создаются и управляются исключительно через CSS
- Требуют обязательное свойство content (хотя бы пустое
content: "") - Могут быть позиционированы абсолютно относительно родителя
- Наследуют стили от родительского элемента
| Псевдоэлемент | Назначение | Пример использования |
|---|---|---|
::before | Создаёт элемент перед содержимым целевого элемента | Декоративные иконки, маркеры, кавычки |
::after | Создаёт элемент после содержимого целевого элемента | Очистка флоатов, индикаторы, примечания |
::first-letter | Стилизует первую букву текстового элемента | Буквицы, декоративные капители |
::selection | Стилизует выделенный пользователем текст | Кастомные цвета выделения текста |
Использование псевдоэлементов позволяет достичь нескольких важных целей:
- Семантическая чистота HTML — декоративные элементы остаются в CSS
- Производительность — меньше DOM-узлов, быстрее рендеринг
- Разделение контента и презентации — соответствие принципам современной веб-разработки
- Создание сложных визуальных эффектов — наслоение, градиенты, анимации без дополнительной разметки

Ограничения прямого доступа к ::before и ::after через JavaScript
Работая с псевдоэлементами, разработчики сталкиваются с фундаментальным ограничением: поскольку ::before и ::after не являются реальными DOM-узлами, прямой доступ к ним через привычные методы JavaScript невозможен. 🔒
Попытки получить доступ к псевдоэлементам стандартными методами приводят к разочарованию:
// Не работает!
document.querySelector('.myElement::before');
// Возвращает null
// Тоже не работает
document.querySelector('.myElement').querySelector('::before');
// Ошибка: Invalid selector
// И это не сработает
const element = document.querySelector('.myElement');
element.style.setProperty('::before', 'color: red');
// Не производит ожидаемого эффекта
Основные ограничения работы с псевдоэлементами:
- Невозможность прямого выбора через DOM-селекторы
- Отсутствие прямого доступа к их стилям через element.style
- Невозможность назначить обработчики событий напрямую
- Нельзя динамически создавать/удалять псевдоэлементы через DOM API
Эти ограничения не случайны — они являются следствием архитектурного решения отделить представление (CSS) от структуры (HTML). Псевдоэлементы — это часть CSS, а не DOM.
| Подход | Применимость к псевдоэлементам | Причина ограничений |
|---|---|---|
| Direct DOM access | ❌ Невозможен | Псевдоэлементы не являются частью DOM-дерева |
| element.style | ❌ Не работает | Стиль доступен только для самого элемента, не для его псевдоэлементов |
| setAttribute() | ❌ Не применим | Атрибуты могут устанавливаться только для настоящих DOM-узлов |
| addEventListener() | ❌ Невозможен | События могут прослушиваться только на реальных элементах DOM |
| getComputedStyle() | ✅ Частично работает | Позволяет получить стили псевдоэлемента, но не изменить их напрямую |
Однако эти ограничения породили креативные решения. Вместо того чтобы рассматривать невозможность прямого доступа как проблему, опытные разработчики используют альтернативные подходы, превращающие ограничения в новые возможности.
Манипуляция псевдоэлементами с помощью getComputedStyle()
Хотя прямое изменение псевдоэлементов через DOM невозможно, метод getComputedStyle() открывает нам путь для работы с ними. Этот инструмент позволяет получить вычисленные стили псевдоэлементов, что критически важно для динамического взаимодействия с ними. 🧰
Анна Соколова, фронтенд-архитектор
На проекте для крупного e-commerce мне потребовалось создать динамические бейджи на товарах, которые менялись в зависимости от статуса: "новинка", "распродажа", "последний экземпляр". Первоначально я реализовала их как обычные дочерние элементы, но это усложнило разметку и создало проблемы с производительностью при отрисовке сотен товаров.
Решение пришло в виде псевдоэлементов. Я использовала
::beforeдля отображения бейджа иgetComputedStyle()для проверки его текущего состояния перед изменением. Через CSS-переменные и data-атрибуты мы полностью перенесли логику отображения в CSS, а JavaScript только менял классы и атрибуты родительских элементов.Результат превзошёл ожидания: мы добились 40% ускорения рендеринга каталога и значительно упростили поддержку кода. Теперь эта техника — стандарт для всех наших проектов.
Для получения стилей псевдоэлементов используется расширенная форма getComputedStyle():
// Получение вычисленных стилей для ::before
const beforeStyles = window.getComputedStyle(element, '::before');
// Получение вычисленных стилей для ::after
const afterStyles = window.getComputedStyle(element, '::after');
// Пример чтения конкретного свойства
const content = beforeStyles.getPropertyValue('content');
const color = beforeStyles.getPropertyValue('color');
console.log(content, color);
Обратите внимание, что getComputedStyle() позволяет только получить значения, но не изменить их напрямую. Для изменения стилей псевдоэлементов используются косвенные методы:
- Изменение классов родительского элемента — самый простой способ
- Использование data-атрибутов в сочетании с CSS-селекторами атрибутов
- Динамическое создание/изменение правил CSS через StyleSheet API
- Работа с CSS-переменными — наиболее гибкий подход
Пример практического использования getComputedStyle() для проверки состояния и последующей манипуляции:
function togglePseudoElementVisibility(element) {
// Проверяем текущее состояние псевдоэлемента
const beforeStyles = window.getComputedStyle(element, '::before');
const isVisible = beforeStyles.getPropertyValue('display') !== 'none';
// Изменяем класс на основе проверки
if (isVisible) {
element.classList.add('hide-pseudo');
} else {
element.classList.remove('hide-pseudo');
}
}
// CSS правило
// .hide-pseudo::before { display: none; }
Обратите внимание на особенности работы с getComputedStyle() для псевдоэлементов:
- Свойство
contentвозвращается в форме с кавычками (например, "text") - Цвета всегда возвращаются в формате rgb()/rgba(), независимо от исходного формата в CSS
- Размеры преобразуются в пиксели, даже если были заданы в em, rem или процентах
- Если псевдоэлемент не существует (нет свойства content), многие браузеры всё равно возвращают объект CSSStyleDeclaration, но с пустыми значениями
Динамическое изменение псевдоэлементов через CSS-переменные
CSS-переменные (Custom Properties) — изящный мост между JavaScript и псевдоэлементами. Этот подход не просто обходит ограничения, но создаёт элегантную архитектуру для динамического взаимодействия с псевдоэлементами. 🎯
Ключевое преимущество CSS-переменных в том, что они поддерживают наследование и могут быть изменены через JavaScript в рантайме. Псевдоэлемент наследует переменные от своего родителя, что позволяет косвенно воздействовать на него.
Базовая схема работы с переменными для управления псевдоэлементами:
/* CSS */
:root {
--badge-content: "New";
--badge-color: #ff5722;
--badge-display: block;
}
.product::before {
content: var(--badge-content);
color: var(--badge-color);
display: var(--badge-display);
position: absolute;
top: 10px;
right: 10px;
padding: 5px 10px;
border-radius: 3px;
}
/* JavaScript */
function updateBadge(element, status) {
switch (status) {
case 'new':
element.style.setProperty('--badge-content', '"New"');
element.style.setProperty('--badge-color', '#ff5722');
element.style.setProperty('--badge-display', 'block');
break;
case 'sale':
element.style.setProperty('--badge-content', '"Sale"');
element.style.setProperty('--badge-color', '#4caf50');
element.style.setProperty('--badge-display', 'block');
break;
case 'none':
element.style.setProperty('--badge-display', 'none');
break;
}
}
// Использование
updateBadge(document.querySelector('.product'), 'sale');
CSS-переменные можно также задавать на уровне элементов через атрибут style, делая код еще более декларативным:
// Более компактная запись
element.style = '--badge-content: "Last chance"; --badge-color: #ff9800';
Преимущества использования CSS-переменных для управления псевдоэлементами:
- Чистое разделение ответственности — структура и базовый стиль в CSS, динамические данные в JavaScript
- Производительность — не требуется манипуляция DOM или постоянное изменение классов
- Гибкость — можно управлять любыми свойствами псевдоэлемента
- Масштабируемость — легко расширять набор контролируемых свойств
Более сложный пример с анимацией и динамическим контентом:
/* CSS */
.notification {
position: relative;
--notification-count: "0";
--notification-visibility: hidden;
}
.notification::after {
content: var(--notification-count);
visibility: var(--notification-visibility);
position: absolute;
top: -8px;
right: -8px;
background: red;
color: white;
border-radius: 50%;
min-width: 20px;
height: 20px;
text-align: center;
line-height: 20px;
font-size: 12px;
transition: transform 0.3s;
transform: scale(var(--notification-scale, 1));
}
/* JavaScript */
function updateNotification(element, count) {
if (count > 0) {
element.style.setProperty('--notification-count', `"${count}"`);
element.style.setProperty('--notification-visibility', 'visible');
// Добавляем анимацию через временную переменную
element.style.setProperty('--notification-scale', '1.2');
setTimeout(() => {
element.style.setProperty('--notification-scale', '1');
}, 300);
} else {
element.style.setProperty('--notification-visibility', 'hidden');
}
}
Для более сложных сценариев можно комбинировать CSS-переменные с другими техниками:
| Техника | Применение | Пример сценария |
|---|---|---|
| CSS-переменные + data-атрибуты | Для выбора между несколькими вариантами содержимого | Изменение иконок статуса на основе data-status |
| CSS-переменные + классы | Для крупных визуальных изменений и предопределенных состояний | Переключение между темной/светлой темой с анимациями |
| CSS-переменные + CSS-анимации | Для сложных визуальных эффектов с переходами | Интерактивные подсказки, появляющиеся с анимацией |
| CSS-переменные + медиа-запросы | Для адаптивного поведения псевдоэлементов | Изменение размера и положения бейджей на мобильных устройствах |
Продвинутые техники управления ::before и ::after в jQuery
Несмотря на рост популярности современных JavaScript-фреймворков, jQuery по-прежнему используется во многих проектах. Для работы с псевдоэлементами в jQuery существуют специализированные подходы, расширяющие стандартный функционал библиотеки. ⚙️
jQuery не имеет встроенных методов для прямого управления псевдоэлементами, но предоставляет элегантный API для работы с CSS, DOM и атрибутами, который можно адаптировать для наших целей.
Базовые операции с псевдоэлементами в jQuery:
// Чтение стилей псевдоэлемента
function getPseudoStyle(element, pseudo, prop) {
return window.getComputedStyle(
$(element)[0],
pseudo
).getPropertyValue(prop);
}
// Использование
const content = getPseudoStyle('.my-element', ':before', 'content');
console.log(content);
// Управление через CSS-переменные
$('.my-element').css('--pseudo-color', 'red');
Для более удобной работы с псевдоэлементами в jQuery часто создают плагины или расширения. Вот пример создания простого jQuery-расширения:
// Плагин для работы с псевдоэлементами
$.fn.pseudoStyle = function(element, prop, value) {
const selector = `#${element}-pseudo-selector`;
let styleEl = $(selector);
if (!styleEl.length) {
styleEl = $('<style></style>').attr('id', `${element}-pseudo-selector`);
$('head').append(styleEl);
}
styleEl.html(`.${element}:${this.selector.substring(1)}:${prop}{${value}}`);
return this;
};
// Использование
$('.button').pseudoStyle('before', 'content', '"Click me!"');
Более изящный способ — использование CSS-переменных с jQuery:
// Создаём функцию-обертку для удобства
$.fn.setPseudoContent = function(pseudoEl, content) {
return this.css(`--${pseudoEl}-content`, `"${content}"`);
};
$.fn.setPseudoColor = function(pseudoEl, color) {
return this.css(`--${pseudoEl}-color`, color);
};
// CSS
.element::before {
content: var(--before-content, '');
color: var(--before-color, inherit);
}
// Использование
$('.element')
.setPseudoContent('before', 'New notification')
.setPseudoColor('before', '#ff5722');
Для сложных случаев можно использовать jQuery для динамического создания и манипуляции правилами таблицы стилей:
// Функция для создания/изменения CSS-правил
$.createPseudoRule = function(selector, pseudoEl, cssObj) {
const id = `dynamic-pseudo-${selector.replace(/[^a-zA-Z0-9]/g, '')}`;
let style = $(`#${id}`);
if (!style.length) {
style = $('<style></style>').attr('id', id);
$('head').append(style);
}
let cssText = `${selector}::${pseudoEl} {`;
for (const prop in cssObj) {
if (cssObj.hasOwnProperty(prop)) {
cssText += `${prop}: ${cssObj[prop]}; `;
}
}
cssText += '}';
style.html(cssText);
return style;
};
// Пример использования
$.createPseudoRule('.notification', 'after', {
'content': '"5"',
'background-color': 'red',
'color': 'white',
'border-radius': '50%',
'padding': '2px 6px'
});
Главные преимущества использования jQuery для работы с псевдоэлементами:
- Кроссбраузерность — jQuery обрабатывает различия реализаций в разных браузерах
- Краткость синтаксиса — цепочка методов позволяет писать компактный и читаемый код
- Совместимость — идеально подходит для проектов, уже использующих jQuery
- Расширяемость — легко создавать собственные плагины и хелперы для конкретных задач
При использовании jQuery для работы с псевдоэлементами учитывайте следующие рекомендации:
- Предпочитайте CSS-переменные динамическому созданию правил CSS для лучшей производительности
- Используйте делегирование событий, если псевдоэлементы должны реагировать на взаимодействия
- Кэшируйте jQuery-объекты для оптимизации производительности при частых манипуляциях
- Рассмотрите возможность использования data-атрибутов для хранения данных, влияющих на псевдоэлементы
Работа с псевдоэлементами в JavaScript — это тот случай, когда кажущиеся ограничения открывают двери к более глубокому пониманию взаимодействия CSS и JavaScript. Вместо того чтобы бороться с невозможностью прямого доступа, профессиональные разработчики используют эти особенности для создания более чистой архитектуры с чётким разделением ответственности. Помните: псевдоэлементы — это инструменты презентационного слоя, и взаимодействие с ними через CSS-переменные, классы или атрибуты не только обходит ограничения, но и соответствует лучшим практикам фронтенд-разработки.