Имитация ввода текста

Имитация ввода текста

как сделать плавную анимацию на CSSПроблема

Иногда перед нами встает задача создать эффект текста, появляющегося на экране символ за символом, словно кто-то его вводит. Этот прием в сочетании с моноширинными шрифтами особенно часто используется на технических веб-сайтах для имитации командной строки терминала.

При правильном использовании он способен прекрасно вписаться и значительно улучшить общий дизайн страницы. Обычно для реализации такого эффекта разработчикам приходится прибегать к помощи длинного, грязного и сложного JS-кода. И несмотря на то что это всего лишь представление, использование CSS для подобного эффекта кажется недостижимой мечтой. Или все же это возможно?

имитация ввода текста на css

 

Решение

Основная идея заключается в том, чтобы анимировать ширину элемента, содержащего наш текст, с нуля и до полного значения, увеличивая размер видимой области на один символ за раз. Вероятно, вы уже догадались, какое ограничение накладывает данный подход: для многострочного текста он не работает. К счастью, чаще всего подобная стилизация требуется для однострочного текста, такого как заголовки.

Еще одна вещь, о которой не следует забывать, — каждая анимация по мере увеличения длительности порождает все больший снижающий эффект: короткая анимация делает интерфейс более стильным и в некоторых случаях даже способна повысить удобство использования.

Но чем длиннее анимация, тем скорее она начинает раздражать пользователя. Следовательно, даже если эту технику можно было бы применить к длинному многострочному тексту, в большинстве случаев это было бы очень плохой идеей.

Приступим к кодированию! Предположим, что мы хотим применить этот эффект к заголовку верхнего уровня ( <h1> ), для которого мы уже определили стиль, включающий моноширинный шрифт, и который выглядит так:

HTML
<h1>CSS is awesome!</h1>

Теоретически мы могли бы использовать это решение и с многострочным текстом, но для этого потребовалось бы обернуть каждую строку в собственный элемент и обеспечить необходимую задержку старта анимации (то есть решение в итоге получится хуже изначальной проблемы).

Читайте также  Как создать куб на CSS3


Мы можем с легкостью добавить анимацию, меняющую ширину нашего заголовка от 0 до конечного значения, как показано далее:

@keyframes typing {
from { width: 0 }
}
h1 {
width: 7.7em; /* Ширина текста */
animation: typing 8s;
}

Все правильно, ведь так? Однако, как вы видите на рисунке выше, у этого безобразия нет ничего общего с эффектом, которого мы хотели добиться. Наверное, вы уже догадались, в чем проблема. Во первых, мы забыли применить  white-space: nowrap; для предотвращения переноса текста на новую строку, поэтому по мере увеличения ширины элемента количество строк меняется.

Во-вторых, мы забыли применить  overflow: hidden; поэтому обрезания не происходит. Исправив эти недочеты, мы начинаем видеть реальные проблемы нашей анимации, а именно:
очевидно, что анимация получается плавной, вместо того чтобы отображать текст символ за символом; менее очевидная проблема заключается в том,что до сих пор мы указывали ширину в единицах измерения  em, что, конечно, лучше, чем делать это в пикселах, но тоже не идеально. Откуда взялось значение 7,7?  Как его вычислить?

Первую проблему можно решить с помощью функции расчета времени  steps(), как это описано в уроке  «Как сделать покадровую анимацию» и «Как сделать мерцающую анимацию». К сожалению, требуемое количество шагов равно количеству символов в нашей строке, а значит, такой код будет сложно поддерживать, а в случае динамического текста — попросту невозможно создать. Однако, как мы увидим чуть далее, вычисление этого значения можно автоматизировать, используя крошечный фрагмент кода JavaScript.

Обойти вторую проблему нам помогут единицы измерения  ch .  ch — это одна из новых единиц измерения, которая была добавлена в спецификации CSS и представляет ширину глифа 0.

 

Это одна из наименее известных новых единиц измерения, так как в большинстве случаев нас мало волнует возможность определять размеры элементов относительно ширины глифа 0. Однако моноширинные шрифты — особый случай. В моноширинных шрифтах ширина глифа 0 совпадает с шириной любого другого глифа. Следовательно, для того чтобы задать ширину в единицах измерения  ch, нужно указать количество символов. В нашем примере их  15 . Соберем все вместе:

Читайте также  Плавная анимация состояния

@keyframes typing {
from { width: 0; }
}
h1 {
width: 15ch; /* Ширина текста */
overflow: hidden;
white-space: nowrap;
animation: typing 6s steps(15);
}

Как подтверждают кадры, показанные на рисунке, теперь наконец-то мы получили желаемый результат: наш текст отображается символ за символом. Однако он все еще не выглядит достаточно реалистичным.

 

Догадаетесь, чего не хватает?

Последняя деталь, которая сделала бы наше решение намного реалистичнее, — это мигающий курсор. Мы уже научились создавать мерцающую анимацию в уроке «Как создать мерцающую анимацию». В данном случае курсор можно добавить посредством псевдоэлемента, используя свойство  opacity для реализации мерцания.

С другой стороны, мы могли бы сэкономить псевдоэлемент, которых у нас и так не очень много, на случай, если он понадобится для другого эффекта, и сделать мигающий курсор из правой рамки:

@keyframes typing {
from { width: 0 }
}
@keyframes caret {
50% { border-color: transparent; }
}
h1 {
width: 15ch; /* Ширина текста */

overflow: hidden;
white-space: nowrap;
border-right: .05em solid;
animation: typing 6s steps(15),
caret 1s steps(1) infinite;
}

Обратите внимание, что, в отличие от анимационного эффекта для отображения текста, курсор должен мерцать бесконечно (даже после того, как мы показали весь текст), отсюда и ключевое слово infinite. Помимо этого, мы не указываем цвет рамки, так как он должен определяться автоматически и совпадать с цветом текста. Несколько кадров из результирующей анимации показаны на рисунке.


Наша анимация работает просто великолепно, но проблему сопровождения этого кода мы пока не решили: для каждого заголовка необходимо определять собственный стиль, зависящий от количества символов, и обновлять значения каждый раз, когда мы меняем что-то в содержимом. Это как раз та задача, с которой превосходно способен справиться JS:
JS
$$(‘h1’).forEach(function(h1) {
var len = h1.textContent.length, s = h1.style;
s.width = len + ‘ch’;
s.animationTimingFunction = «steps(«+len+»),steps(1)»;
});

Эти несколько строк кода JS позволяют нам успешно догнать и схватить обоих зайцев: наша анимация не только реалистично выглядит, но и проста в сопровождении! Все это прекрасно, но что произойдет, если окажется, что браузер не поддерживает анимацию CSS? По сути, такой браузер пропустит весь код, как-либо связанный с анимацией, и прочитает только следующее:
h1 {
width: 15ch; /* Ширина текста */
overflow: hidden;
white-space: nowrap;
border-right: .05em solid;
}
В зависимости от того, поддерживает ли такой браузер единицы измерения ch, пользователь увидит один из запасных вариантов, показанных на рисунке ниже.

Читайте также  Как сделать покадровую анимацию

 

Для того чтобы избежать второго случая, можно добавить резервное решение с единицами измерения  em. Если же вы не хотите видеть немерцающий курсор в резервном решении, то измените анимацию курсора, добавив в ключевые кадры рамку, для того чтобы в случае отсутствия анимации отображалась только невидимая прозрачная рамка, вот так:

@keyframes caret {
50% { border-color: currentColor; }
}
h1 {
/* … */
border-right: .05em solid transparent;
animation: typing 6s steps(15),
caret 1s steps(1) infinite;
}

Это достаточно хорошее резервное решение: в старых браузерах анимации нет, но ничего не ломается и текст остается доступным, в то же время не теряя в стилизации.

ПОПРОБУЙТЕ САМИ!

http://play.csssecrets.io/typing

 

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Плюсануть
Поделиться

Об авторе

admin administrator

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: