CSS animated typing - html

I'm trying make an animation as if I was typing. To achieve this I'm using CSS animation 'steps'.
The animation itself works just fine. However, if I want to animate multiple lines of text, they all start playing at the same time. Which isn't giving me the desired effect. (Tried using <br> in a single <h1>, which cut off the text, but again started the animations simultaneously.)
To counter this, I put the next line of text in an <h2> and set an animation-delay for every line of text. Which works, but the text is visible before the animation starts.
I want the text to be hidden until the animation starts playing, to really get that 'live typing' effect.
Anyone got any ideas on how I can achieve this?
HTML
<div class="content">
<h1>Hi there! My name is Jeff.</h1>
<h2>And I create cool stuff.</h2>
</div>
CSS
.content h1 {
background:white;
opacity:0.7;
white-space:nowrap;
overflow:hidden;
border-right: 3px solid black;
-webkit-animation: typing 2s steps(26, end),
blink-caret 1s step-end 2s;
}
.content h2 {
background:white;
opacity:0.7;
white-space:nowrap;
overflow:hidden;
border-right: 3px solid black;
-webkit-animation: typing 2s steps(26, end),
blink-caret 1s step-end infinite;
-webkit-animation-delay:3s;
}
#-webkit-keyframes typing {
from { width: 0; }
to { width:400px; }
}
#-webkit-keyframes blink-caret {
from, to { border-color: transparent }
50% { border-color: black }
}
jsFiddle

The simplest solution is to add:
animation-fill-mode:both;
to your h2 (with the necessary prefixes). That way, you aren't setting it to a zero width outside of your animation, so browsers that don't support this CSS will display the heading (which I guess is what you're after). See this fiddle.
The animation-fill-mode:
specifies how a CSS animation should apply styles to its target before
and after it is executing
Setting it to both in this instance means that your h2 will have a width of 0 before it starts executing, and a width of 400px after.

As the comments already include a solution, perhaps this might be another way of doing it - by using timeouts and setting visibility: hidden at the beginning (For simplification I just used jQuery to set the visiblitiy).
Include the following CSS rule:
.content {
visibility: hidden;
}
As JavaScript you would have:
window.setTimeout(function() {
$('#contentdiv h1').css('visibility', 'visible');
}, 100);
window.setTimeout(function() {
$('#contentdiv h2').css('visibility', 'visible');
}, 3100);
See the jsFiddle

p
{
font:500 22px consolas;
width:20ch;
white-space:nowrap;
overflow:hidden;
animation:type 5s steps(20) infinite;
}
#keyframes type
{
0%{ width:0; }
}
<p>Text Type Animation</p>

Not quite the OP's question, but in case someone else finds this useful:
I wanted to be able to typing-animate a pararaph of text, a single <p> tag which might contain text that would wrap, and produce an unknown number of actual lines. Applying a simple linear animation to the p tag itself wouldn't work, so instead, I took the approach of having several "hider" elements that would cover the paragraph of text, each one line high, and then I would animate each of those so they would shrink away, reveal characters from the line of text beneath them.
The HTML looks like this:
<div class="container">
<!-- container div is required to set absolute positions within it, so that .typing and .hiders exactly overlap -->
<p class="typing">
This paragraph of text will be animated
with a "typewriter" style effect, and it
will continue to work even if it splits across
multiple lines. Well, in this case, up to a
maximum of 5 lines, but you get the picture.
</p>
<div class="hiders">
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
</div>
</div>
You need a container, and position the .typing element and the .hiders using absolute so that they're on top of each other:
.container {
position: relative;
font-family: Consolas, monospace;
}
.typing {
position: absolute;
top: 0;
margin: 0;
z-index: -1;
}
.hiders {
margin: 0;
position: absolute;
top: 0;
width: 100%;
}
And the animation gets applied to each p inside the .hiders:
.hiders p {
position: relative;
clear: both;
margin: 0;
float: right; /* makes animation go left-to-right */
width:0; /* graceful degradation: if animation doesn't work, these are invisible by default */
background: white; /* same as page background */
animation: typing 2s steps(30, end);
animation-fill-mode: both; /* load first keyframe on page load, leave on last frame at end */
}
.hiders p:nth-child(2) {
animation-delay: 2s;
}
.hiders p:nth-child(3) {
animation-delay: 4s;
/* etc */
Here's the final fiddle:
https://jsfiddle.net/hjwp/514cLzxn/
Original credit for inspiration: Lea Verou

Related

Trying to animate a paragraph on html using css but it wont wrap around the container

I'm trying to animate a paragraph (like a typewriter) but the code ends when the container ends. I've tried changing both the duration of the animation and including pre-wrap for "white space:" and "break-word" for word-wrap but the animation then continues to animate multiple lines at the same time. Is there a way to make it so the animation goes one line at a time and continues to the next line when the container (the container is just margin-left & margin-right) ends?
I used
.typewriter {
overflow: hidden;
border-right: .15em solid orange;
white-space: pre-wrap;
margin: 0 auto;
letter-spacing: .15em;
word-wrap: break-word;
animation:
typing 4s steps(100, end),
blink-caret .75s step-end infinite;
}
#keyframes typing {
from { width: 0 }
to { width: 100% }
}
#keyframes blink-caret {
from, to { border-color: transparent }
50% { border-color: orange; }
}
I was expecting the animation to write the paragraph line by line and break it into the next line but it animates multiple lines at a time and then cascades to 15 lines.

Div Appearing over Heading

I'm very new to css and html. I'm setting up a text version of the oregon trail, and on my main menu screen one of my divs is appearing over some text that I have fading in and out. I've searched quite a bit and couldn't get any of the solutions I found to solve it.
CSS and HTML
body {
background-color: black;
}
#title {
color: white;
text-align: center;
}
div.menu {
position: relative;
vertical-align: middle;
}
p {
position: relative;
color: burlywood;
text-align: center;
}
#keyframes fadeIn {
from {
opacity: 0;
}
}
h7 {
position: relative;
top: 100px;
animation: fadeIn 2s linear infinite alternate;
}
<div id="title">
<h1>The Oregon Trail</h1>
<h2>Main Menu</h2>
<h7>Press Key to Select Option</h7>
</div>
<div class="menu">
<p>1. Travel the Trail</p>
<p>2. Learn about the Trail</p>
<p>3. See the Oregon Top Ten</p>
<p>4. Turn Sound Off</p>
</div>
Any tips as to why this is occurring?
You need to change your <h7> styling in the CSS from position: relative;to position: initial;. That should fix the problems of it being overlapped!
This here is your issue:
h7 {
position: relative;
top: 100px;
animation: fadeIn 2s linear infinite alternate;
}
top will move the element, but elements around it will treat it as if it was not moved. You'll probably want to use margin-top or padding-top to move it into the position you want instead of top.
Here is a link to an MDN page that explains it:
https://developer.mozilla.org/en-US/docs/Web/CSS/position
Relative
The element is positioned according to the normal flow of the document, and then offset relative to itself based on the values of top, right, bottom, and left. The offset does not affect the position of any other elements;

Is it possible to animate a CSS line-through text-decoration?

I am trying to animate with CSS the a line through on a bit of text, but it's not actually animating, just going from hidden to displayed. Can anyone advise if what I'm trying is actually possible? If not, is there another way to achieve this?
HTML:
<div>
The text in the span <span class="strike">is what I want to strike out</span>.
</div>
CSS:
#keyframes strike{
from{text-decoration: none;}
to{text-decoration: line-through;}
}
.strike{
-webkit-animation-name: strike; /* Chrome, Safari, Opera */
-webkit-animation-duration: 4s; /* Chrome, Safari, Opera */
animation-name: strike;
animation-duration: 4s;
animation-timing-function: linear;
animation-iteration-count: 1;
animation-fill-mode: forwards;
}
You can use a pseudo like this
Note (thanks to Phlame), this left-to-right animation won't work if the line to strike breaks in to a second line. For that one need to use yet another pseudo element and some script to position the two properly. Or use some other animation effect, e.g. like the one suggested in Oriol's answer.
#keyframes strike{
0% { width : 0; }
100% { width: 100%; }
}
.strike {
position: relative;
}
.strike::after {
content: ' ';
position: absolute;
top: 50%;
left: 0;
width: 100%;
height: 1px;
background: black;
animation-name: strike;
animation-duration: 4s;
animation-timing-function: linear;
animation-iteration-count: 1;
animation-fill-mode: forwards;
}
<div>
The text in the span <span class="strike">is what I want to strike out</span>.
</div>
It depends on how you want to animate it.
Since text-decoration-color is animatable, you can animate it from transparent to auto.
But this property is not widely supported yet.
#keyframes strike {
from { text-decoration-color: transparent; }
to { text-decoration-color: auto; }
}
.strike {
text-decoration: line-through;
animation: strike 4s linear;
}
<div>
The text in the span <span class="strike">is what I want to strike out</span>.
</div>
Here's a variation on the accepted answer, using an image to provide an animated "scribble" strike-through.
html {
font-family: Helvetica;
font-size: 24px;
}
.strike { position:relative; }
.strike::after {
content:' ';
position:absolute;
top:50%; left:-3%;
width:0; height:10px;
opacity:80%;
transform:translateY(-50%);
background:repeat-x url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB0AAAAKAQMAAAByjsdvAAAABlBMVEUAAADdMzNrjRuKAAAAAXRSTlMAQObYZgAAADdJREFUCNdj+MMABP8ZGCQY/h9g+MHw/AHzDwbGD+w/GBhq6h8wMNj/b2BgkP8HVMMPUsn+gQEAsTkQNRVnI4cAAAAASUVORK5CYII=);
animation: strike 2s linear .3s 1 forwards;
}
#keyframes strike { to { width: 106%; } }
This thing and <span class="strike">this thing and</span> this thing.
It's very elegant, IMO, to use linear-gradient as background, and paint line which is the same color as the text (currentColor).
This solution is very flexible, opens up the door to many interesting effects and is also much less code than a pseudo-element solution.
PS: It also supports multi-line texts
From my CodePen:
span {
--thickness: .1em;
--strike: 0;
background: linear-gradient(90deg, transparent, currentColor 0) no-repeat
right center / calc(var(--strike) * 100%) var(--thickness);
transition: background-size .4s ease;
font: 25px Arial;
padding: 0 .2em;
}
span:hover {
--strike: 1; /* "1" means "true" (show the strike line) */
background-position-x: left;
}
<span contenteditable spellcheck='false'>
Strike-through animation (hover)
</span>
According to W3Schools, the text-decoration property is not animatable.
However, if you use jQuery, you can. (See here)

How can I 'grow' text in only one direction if the text is centered?

I'm trying to create an overlay that says: 'Waiting...', but I want the ellipses to be animated. So the text would actually go from:-
'Waiting' -> 'Waiting.' -> 'Waiting..' -> 'Waiting...' -> 'Waiting' ->
However, when the ellipses count changes it's pushing the 'Waiting' to the left since the content is centered in its container.
HTML:
<div style='text-align: center'>
<span>Waiting</span>
<span id='ellipses'></span>
</div>
Javascript:
var ellipses = 0;
setInterval(function () {
$('#ellipses').text('.'.repeat(ellipses))
ellipses = (ellipses + 1) % 4;
}, 400)
Any good way to handle this ?, Easy to do with some magic numbers or manual calculation of what 'center' is + a fixed position, but I'd like to have a clean css solution if possible..
Using pure CSS, try this Fiddle,
.ellipses1 {
-webkit-animation: elipses 1.3s infinite;
-webkit-animation-delay: 0.0s;
}
.ellipses2 {
-webkit-animation: elipses 1.3s infinite;
-webkit-animation-delay: 0.2s;
}
.ellipses3 {
-webkit-animation: elipses 1.3s infinite;
-webkit-animation-delay: 0.3s;
}
#-webkit-keyframes elipses {
0% { opacity: 0; }
50% { opacity: 0; }
100% { opacity: 1; }
}
Try adding the following to your style:
#ellipses{
position:absolute;
}
Place the ellipsis inside an after pseudo element and declare its position as absolute. I created a fiddler to demonstrate the behavior. The ellipsis depends on your mouse pointer hovering over the second (middle) line for demonstration purpose: http://jsfiddle.net/f9eutj40/
HTML:
<div>
<span>
The first line
</span>
</br>
<span class="ellipsis">
The second line
</span>
</br>
<span>
The third line
</span>
</div>
CSS:
div {
text-align: center;
background-color: green;
}
span {
color: cyan;
}
span.ellipsis:hover:after {
color: cyan;
content: ".....";
position: absolute;
}
This way you don't even have to make a modification to the text itself (and clean it up afterwards again...). You just modify the styling of the text. This is done in a static manner in the demo above using the content: rule, but nothing speaks against doing that dynamic.

Why doesn't the marquee stop on hover?

To stop the marquee for mouse-hover I did this:
CSS:
<style type="text/css">
.wm {
border: solid 2px;
border-color:#0aa2e3;
border-radius: 10px;
font-family:Georgia, "Times New Roman", Times, serif;
font-size:13px;
}
marquee:hover {
animation-play-state:paused;
}
</style>
HTML :
<p class="wm"> <marquee> ... </marquee> </p>
But nothing happens as I point my mouse over the moving paragraph. Why is that ?
That's because marquee isn't a CSS3 animation and that's about all you can pause via animation-play-state:paused;
But more importantly: You should no longer be using marquee at all
If you need something similar, like a moving link list that can be clicked and stops on hovering, you should be looking for alternatives, I could bet there are some jQuery news ticker plug-ins out there.
Edit: Since you're looking for a pauseable CSS3 Animation according to your comments, you'll require the following markup:
<p class="marquee"> <!-- the wrapping container -->
<span> ... </span> <!-- the tray moving around -->
</p>
The content in your span will be the one moving around your wrapping container with the marquee class.
/* define the animation */
#keyframes marquee {
0% { transform: translate(0, 0); }
100% { transform: translate(-100%, 0); }
}
/* define your limiting container */
.marquee {
width: 450px;
margin: 0 auto;
white-space: nowrap;
overflow: hidden;
box-sizing: border-box;
}
/* this is the tray moving around your container */
.marquee span {
display: inline-block;
padding-left: 100%;
text-indent: 0;
animation: marquee 15s linear infinite; /* here you select the animation */
}
/* pause the animation on mouse over */
.marquee span:hover {
animation-play-state: paused
}
Also as an jsfiddle: http://jsfiddle.net/MaY5A/209/
Additional note:
Since CSS3 animations are still experimental in some browsers, you might have to add vendor prefixes. Which can be weird especially for the animation definition itself:
#-webkit-keyframes marquee {
...
}
#-moz-keyframes marquee {
...
}
But transform, translate, animation and animation-play-state might require vendor prefixes, depending on how far back you want to support browsers.