В веб-разработке иногда возникает потребность визуально повторить содержимое элемента в другом месте страницы. Это похоже на создание «проекции», но не дублируя при этом сам HTML-код.
Сделать это можно на одном CSS без использования JavaScript. CSS отлично справляется со вставкой текста при помощи кастомных data-* в тандеме с псевдоэлементами. Таким образом можно не только дублировать текст, но и создавать всплывающие подсказки (toolkit), украшать заголовки, добавлять любой текст, который не будет влиять на SEO — в том числе отображать перевод на другой язык.
Оглавление
Принцип работы
Ключ к этому методу:
- Псевдоэлементы (
::beforeили::after) позволяют вставить контент до или после содержимого выбранного элемента, не меняя при этом HTML-структуру. - Свойство
content: Это свойство позволяет задать содержимое для псевдоэлемента. Самое интересное, что оно может принимать не только строковые значения, но и функциюattr(), которая считывает значение любого атрибута родительского HTML-элемента.
Вы скажете, что CSS-свойство content и так позволяет вставлять строковый текст напрямую (например, content: "Новинка";). Но для кириллических символов это может приводить к проблемам с кодировкой (появлению «кракозябр») в зависимости от настроек сервера, кодировки файла стилей (.css) и его подключения.
Чтобы гарантировать, что ваш текст всегда отображается корректно лучше хранить весь динамический и кириллический текст в пользовательских атрибутах HTML (например, data-copy или data-text), а затем вызывать его через функцию attr():
/* ❌ Ненадежно для кириллицы: */
/* content: "Скидка 50%"; */
/* ✅ Надежно: */
content: attr(data-copy);
Пример: Создание текстовой «проекции»
Предположим, у нас есть заголовок, и мы хотим создать его полупрозрачную, сдвинутую копию.
Шаг 1: HTML-структура
Для «голограммы» нам понадобится место хранения текста, который хотим дублировать. Используем пользовательский атрибут data-copy.
<h1 class="hologram-title" data-copy="CSS-голограмма">
CSS-голограмма
</h1>
Шаг 2: базовый CSS и позиционирование
Чтобы переместить псевдоэлемент в нужную точку страницы, нам нужно задать для родительского элемента position: relative, а для самого псевдоэлемента — position: absolute.
.hologram-title {
font-size: clamp(28px, 6vw, 72px);
font-family: sans-serif;
color: #007bff;
position: relative;
display: inline-block;
margin: 50px;
z-index: 10;
}
Шаг 3: создание и стилизация «голограммы»
Теперь используем ::after для создания проекции.
.hologram-title::after {
/* Копируем текст из атрибута */
content: attr(data-copy);
position: absolute;
top: 5px;
left: 10px;
color: rgba(0, 123, 255, 0.2);
z-index: 5; /* Отправляем под оригинал */
pointer-events: none; /* Важно: делаем проекцию некликабельной */
}
Результат

Вот ещё эксперимент: тут я добавила тени для текста (text-shadow), псевдоэлемент ::before и отключила у ::after позиционирование.

Пример: Текст-призрак
Этот пример показывает, как можно использовать сразу два пользовательских атрибута для создания сложного, динамичного, многострочного заголовка с подзаголовками, которые не влияют на SEO, т.к. их нет в DOM, при этом сам HTML-элемент (<h1>) остается однострочным.
Шаг 1: подготовка HTML с двумя атрибутами
В заголовок добавляем два разных атрибута с разным содержимым.
<body class="mode-visible">
<h1 class="hologram-title" data-copy="без JavaScript ⭐⭐⭐⭐⭐⭐⭐" data-twocopy="Псевдоэлементы">
Текст-призрак
</h1>
</body>
Шаг 2: создание многослойного эффекта
Визуально это разбивается на 4 строки:
::before(текст с эмодзи изdata-copy)<h1>(основной текст)::after(текст изdata-twocopy)- В этом примере получается три основных текстовых элемента, но благодаря большим
line-heightв::beforeи смещениям, эмодзи занимает место четвёртой строки.
А. Основные стили
Настраиваем фон и основной заголовок. Использование position: relative для правильного позиционирования псевдоэлементов, указываем цвет основного заголовка.
body {
background: radial-gradient(circle at center, #2a2340, #1a142b);
padding: 20px;
}
.hologram-title {
font-size: 72px;
font-family: "Arial Black", sans-serif;
font-style: italic;
position: relative;
display: inline-block;
padding: 20px 30px;
margin: 80px 0 30px 80px;
text-transform: uppercase;
letter-spacing: -4px;
color: #e0d4ff; /* Основной цвет текста */
}
B. Верхняя строка с эмодзи
Псевдоэлемент ::before располагается выше, добавила туда эмодзи звёздочки, увеличу line-height, чтобы они оказались в самом низу.
.hologram-title::before {
content: attr(data-copy);
position: absolute;
top: -82px;
left: -20px;
color: #ff00c8;
opacity: 0.5;
filter: blur(2px);
font-style: normal; /* Сброс курсива, чтобы отличаться от <h1> */
pointer-events: none;
line-height: 2.5; /* Занимает много вертикального пространства */
animation: pulse 2.5s infinite ease-in-out;
z-index: -1;
}
C. Нижняя строка с искажением
Псевдоэлемент ::after располагается ниже и имеет совершенно другой шрифт, цвет и небольшой наклон.
.hologram-title::after {
content: attr(data-twocopy);
position: absolute;
top: 80px; /* Смещение вниз */
left: -20px;
color: #00ff16;
opacity: 0.25;
font-size: 60px;
transform: skew(-10deg) rotate(-2deg);
pointer-events: none;
font-family: "Papyrus", fantasy; /* Другой шрифт */
letter-spacing: 6px;
animation: floaty 4s infinite ease-in-out;
z-index: -1;
}
Шаг 3: Динамические анимации
Добавляем лёгкие анимации, чтобы оживить эффект и придать ему небольшой киберпанковский вид:
/* --- АНИМАЦИИ --- */
/* Мерцание верхней проекции */
@keyframes pulse {
0%, 100% { opacity: 0.5; transform: scale(1); }
50% { opacity: 0.8; transform: scale(1.01); }
}
/* "Плавающее" искажение нижней проекции */
@keyframes floaty {
0%, 100% { transform: skew(-10deg) rotate(-2deg) translateY(0); }
50% { transform: skew(-10deg) rotate(-2deg) translateY(-5px); }
}
Результат

Пример: Призрачный перевод и всплывающая подсказка
В этом примере используется пользовательский атрибут data-translate, чтобы создать строки с переводом и всплывающую подсказку.
Алгоритм действий остаётся таким же, как и в предыдущих примерах. Здесь атрибуты добавлены к заголовку и окну приветствия. В параграфах (<p>) используется тот же принцип: псевдоэлементы (::after) отображают полный перевод всего абзаца, прикрепляя его к концу блока — без абсолютного позиционирования. Это удобно для учебных материалов: оригинал виден всегда, а перевод напоминает подстрочник. При желании можно настроить отображение перевода по наведению.
Результат

Как сделать всплывающую подсказку для слов
Для отдельных слов, используется HTML-тег с классом .tooltip. Всплывающий текст хранится в его атрибуте:
<span class="tooltip" data-translate="Striking example">яркий пример</span>
Вариант на одном CSS
Подсказка всплывает по наведению (hover):
.tooltip {
position: relative;
cursor: pointer;
color: #007bff;
text-decoration: underline dotted;
}
.tooltip::after {
content: attr(data-copy);
position: absolute;
bottom: 120%;
left: 0;
background: #007bff;
color: #fff;
padding: 6px 10px;
border-radius: 8px;
white-space: nowrap;
opacity: 0;
transform: translateY(10px);
transition: opacity 0.3s ease, transform 0.3s ease;
pointer-events: none;
z-index: 10;
box-shadow:0 0 10px #6f42c1
}
.tooltip:hover::after {
opacity: 1;
transform: translateY(0);
}
Вариант с JavaScript
После клика по слову над ним появится всплывающая подсказка.
.tooltip {
cursor: pointer;
color: #007bff;
text-decoration: underline dotted;
}
.tooltip-popup {
position: absolute;
background: #007bff;
color: #fff;
padding: 6px 10px;
border-radius: 8px;
white-space: nowrap;
z-index: 10;
box-shadow: 0 0 10px #6f42c1;
}
document.addEventListener('click', (e) => {
const target = e.target;
if (target.classList.contains('tooltip')) {
const existing = document.querySelector('.tooltip-popup');
if (existing) existing.remove();
const popup = document.createElement('div');
popup.className = 'tooltip-popup';
popup.textContent = target.dataset.translate;
document.body.appendChild(popup);
const rect = target.getBoundingClientRect();
popup.style.top = `${rect.top + window.scrollY - 35}px`;
popup.style.left = `${rect.left + window.scrollX}px`;
setTimeout(() => popup.remove(), 3000);
}
});
Где ещё можно использовать
Этот метод подходит для создания только декоративных, неинтерактивных эффектов, без влияния на SEO.
- Например, можно отобразить в углу или поверх блока текст: «Beta», «Demo», «Preview».
- На карточке товара:
data-status=«Новинка», «Скидка», «Распродажа». - Как ambient-слой в дизайне.
- В админке или предпросмотре: «Только для модератора», «Черновик».
| Характеристика | Описание |
| Только текст | Нельзя скопировать сложную структуру (теги <img>, <a>, <span> и т.д.). Псевдоэлемент может отобразить только текст или изображение через URL. |
| Не интерактивно | Проекция, созданная ::before или ::after, некликабельна. Она не является частью DOM. Рекомендуется использовать pointer-events: none;. |
| Дублирование данных | Чтобы скопировать текст, его приходится дублировать (в атрибуте data-copy). |
Текст внутри тега и текст в data-* — это два разных места. И если вы хотите, чтобы они всегда были одинаковыми, придётся вручную следить за синхронизацией.
Например, в WordPress можно автоматизировать это через PHP:
<h1 class="hologram-title" data-copy="<?php echo $title; ?>">
<?php echo $title; ?>
</h1>
