Эффект печатной машинки в CSS: шаги() и мигающий курсор

Cascading Style Sheets (CSS) за годы эволюции приобрели мощный набор функций, позволяющих создавать визуальные эффекты, которые раньше требовали JavaScript. Одной из таких возможностей является создание эффекта печатной машинки (typewriter) чисто через CSS: управляемая последовательная отрисовка текста и мигающий курсор.
Что такое эффект печатной машинки
Эффект печатной машинки — это анимация текста, имитирующая по-символное появление строки, как если бы её печатал человек на машинке или вводил в терминал. Такие анимации добавляют драматичность, управляют вниманием пользователя и используются в заголовках, баннерах, интерактивных учебных материалах.
Краткое определение: steps() — это дискретная функция времени, которая разбивает анимацию на указанные шаги и идеально подходит для симуляции побуквенного ввода.
Как работает функция steps()
Функция timing-function steps(n, direction) разбивает интервал анимации на n шагов. Параметры:
- n — число шагов (целое).
- direction — start или end (по умолчанию end). “start” завершает первый шаг сразу, “end” завершает шаг в конце.
Пример синтаксиса:
animation-timing-function: steps(10, end);Применение: если вы анимируете ширину контейнера от 0% до 100% и используете steps(40), текст будет “появляться” дискретно в 40 шагах.
Простой пример: движение блока по экрану (choppy / плавно)
HTML-разметка (фрагмент):
CSS: плавное перемещение (по умолчанию):
.container {
background-color: blue;
}
div:not(.container) {
background-color: red;
width: 88px;
height: 88px;
animation: movebox 4s infinite;
}
@keyframes movebox {
100% {
transform: translateX(100vw);
}
}Если вместо плавной анимации хочется прерывистого перемещения, добавьте timing-function:
div:not(.container) {
/* ... */
animation: movebox 4s infinite;
animation-timing-function: steps(10, end);
}Чем больше шагов — тем плавнее выглядит движение; меньше шагов даёт более «рваный» эффект.
Важно: если direction не указан, браузер использует end по умолчанию.
Создание эффекта печатной машинки: структура файлов
- Создайте папку проекта.
- index.htm — для разметки.
- style.css — для стилей и анимаций.
Пример базовой разметки index.htm:
Typewriter CSS
Lorem ipsum dolor sit amet consectetur
adipisicing elit. Reiciendis, tempore!
Анимация текста: разбиваем ширину на шаги
Чтобы текст появлялся посимвольно, мы будем анимировать ширину блока от 0% до 100%, скрывая переполнение и задавая моноширинный шрифт.
CSS — настройка контейнера:
.container{
width: fit-content;
}@keyframes для постепенного открытия (type-text):
@keyframes type-text {
0% {
width: 0%;
}
100% {
width: 100%;
}
}Класс .text с шаговой функцией и курсором:
.text {
overflow: hidden; /* спрятать невидимую часть текста */
white-space: nowrap; /* не переносить на новую строку */
font-family: "Courier New", Courier, monospace;
border-right: solid 2px green; /* визуальный курсор */
font-size: 23px;
animation: type-text forwards 4s;
animation-timing-function: steps(40);
}Пояснения:
- steps(40) разбивает анимацию на 40 шагов — это примерно соответствует числу символов + пробелов в строке; подгоняйте n под длину текста.
- forwards гарантирует, что после анимации ширина останется 100%.
Мигающий курсор: оживляем правую границу
Определим анимацию смены цвета границы для эффекта мигания:
@keyframes cursor-blink {
0% {
border-color: transparent;
}
100% {
border-color: green;
}
}
.text{
/* другие правила */
animation: type-text forwards 4s, cursor-blink .6s infinite;
}Такая связка даст нам побуквенное появление текста и постоянно мигающий курсор.
Полный пример в одном месте
index.htm и style.css приведены выше; объединённый CSS-фрагмент для копирования:
.container{ width: fit-content; }
@keyframes type-text {
0% { width: 0%; }
100% { width: 100%; }
}
@keyframes cursor-blink {
0% { border-color: transparent; }
100% { border-color: green; }
}
.text {
overflow: hidden;
white-space: nowrap;
font-family: "Courier New", Courier, monospace;
border-right: solid 2px green;
font-size: 23px;
animation: type-text forwards 4s, cursor-blink .6s infinite;
animation-timing-function: steps(40);
}Советы: увеличьте duration (4s) для более медленной печати; увеличьте количество шагов для плавности или уменьшите для более «скоростной» печати.
Доступность и предпочтения пользователя
Важно учитывать пользователей с ограничениями восприятия движения:
- Обрабатывать prefers-reduced-motion:
@media (prefers-reduced-motion: reduce) {
.text {
animation: none;
border-right: none; /* или оставьте статичный курсор */
}
}- Предоставьте альтернативный статичный контент или кнопку для включения/выключения анимации.
- Для читателей скринридеров убедитесь, что текст доступен в DOM целиком (анимируйте ширину, а не содержимое через aria-hidden).
Кросс-браузерная совместимость и падения назад
Функция steps() и @keyframes поддерживаются в современных браузерах. Тем не менее:
- Старые версии Internet Explorer/Edge Legacy могут вести себя нестабильно.
- Для критичного UX рассмотрите Progressive Enhancement: показывайте весь текст без анимации, если поддержки нет.
Пример простого падения назад:
.text { /* базовый стиль — видимый текст */ }
@supports (animation-timing-function: steps(1)) {
/* анимация только в поддерживающих средах */
}Альтернативные подходы
- JavaScript-симуляция: полный контроль по символам, задержка на символ, случайные паузы, динамическая подстройка скорости.
- CSS типографика с mask-size / clip-path: можно маскировать текст по ширине.
- SVG: анимировать текстовый элемент по длине маски.
Когда выбрать JavaScript: если требуется динамическая печать, паузы, удаление символов (backspace) или управление скоростью по событиям.
Когда CSS-решение не подходит (контрпримеры)
- Многострочный ввод со сложной версткой (разные inline-элементы) — анимировать ширину может ломать переносы.
- Нужна анимация удаления символов с высокой детерминированностью — проще управлять через JS.
- Динамическое изменение текста на основе ввода пользователя — JS удобнее.
Mini-методология: как подойти к задаче
- Оцените: статичный текст или динамический?
- Выберите технику: CSS-steps для простых статичных строк, JS для интерактивности.
- Прототип: создайте локальный пример и подберите число шагов равным длине строки.
- Тестирование: устройства, screen readers, prefers-reduced-motion.
- Оптимизация: уменьшите количество анимаций, чтобы снизить нагрузку на GPU/CPU.
Чеклист по ролям
Дизайнер:
- Убедиться, что моноширинный шрифт соответствует дизайн-гайду.
- Выбрать цвет и ширину “курcора” для контраста.
Фронтенд-разработчик:
- Реализовать анимацию с steps(n) и forwards.
- Добавить prefers-reduced-motion.
- Обработать fallback для старых браузеров.
QA:
- Проверить на десктопе/мобильных/таблете.
- Тестировать с включённым и выключенным prefers-reduced-motion.
- Проверить поведение при изменении размера шрифта и длины строки.
Критерии приёмки
- Текст появляется побуквенно за заданное время.
- Курсор мигает с равномерной частотой и видим на контрастном фоне.
- При prefers-reduced-motion анимация не мешает и отключается.
- Скринридер читает весь текст независимо от анимации.
Тест-кейсы и приёмочные сценарии
- Default: страница загружена — текст печатается полностью за 4s; курсор мигает.
- prefers-reduced-motion: анимация отсутствует, текст полностью видим.
- Длинная строка: анимация адаптируется к длине (проверить число шагов).
- Мобильные браузеры: плавность и отсутствие мерцаний.
Сниппет-штопка (cheat sheet)
- Подсчитать n для steps: примерно равно количеству символов в строке.
- animation-timing-function: steps(n, start) — первый шаг срабатывает сразу.
- forwards сохраняет итоговое состояние после окончания.
Полезные фрагменты:
/* Отключить анимацию при reduced motion */
@media (prefers-reduced-motion: reduce) {
.text { animation: none; }
}
/* Динамическое задание шагов через CSS-переменную */
:root { --steps: 40; }
.text { animation-timing-function: steps(var(--steps)); }Decision flow: когда использовать CSS или JS
flowchart TD
A[Нужно побуквенное появление?] --> B{Только статичный текст?}
B -- Да --> C[Используйте CSS steps'' и @keyframes]
B -- Нет --> D{Нужны паузы/удаление/интерактив?}
D -- Да --> E[Используйте JavaScript-реализацию]
D -- Нет --> C
C --> F[Добавьте prefers-reduced-motion и fallback]
E --> FСоветы по производительности
- Ограничьте число одновременно анимируемых элементов.
- Анимации ширины — относительно дешёвые, но постоянное изменение layout может вызвать reflow; для длинных страниц избегайте анимировать свойства, вызывающие переобёртку множества элементов.
- Рассмотрите использование transform + clip-path для более «GPU-дружелюбных» анимаций, если требуется высокая частота кадров.
Частые ошибки и отладка
- Проблема: курсор исчезает после анимации — проверьте порядок анимаций и значение forwards.
- Проблема: текст внезапно переносится — убедитесь, что white-space: nowrap.
- Проблема: фиксированная ширина ломает адаптивность — используйте fit-content или inline-block и подбирайте шаги по длине.
Краткое резюме
Эффект печатной машинки с CSS — лёгкая и эффективная техника для статичных строк. Она выполняется за счёт анимации ширины и функции steps(), а мигающий курсор достигается отдельной анимацией границы. Для интерактивных сценариев и сложных кейсов JavaScript предоставляет гибкость. Всегда учитывайте доступность и потребности пользователей, задавая fallback и реагируя на prefers-reduced-motion.
Важно: начинайте с простого и улучшайте по необходимости — часто CSS-решение достаточно для декоративных и маркетинговых элементов.
Примечания
- Подберите число шагов примерно равным количеству отображаемых символов.
- Для многострочных блоков используйте альтернативы (mask, clip-path или JS).
- Тестируйте на реальных устройствах и с выключенными анимациями.
Похожие материалы
Полная настройка пульта Logitech Harmony
Ссылки в macOS: алиасы, символьные и жесткие
Установить Windows 8 в VHD без переразметки
Dream Address в Animal Crossing: как пользоваться
Как продавать электронные книги — пошагово