I want to create a simple line through animation and so far I’m here:
.strikethrough { display: inline-block; position: relative; line-height: 1.5em; } .strikethrough:after { content: ''; position: absolute; display: block; width: 100%; height: 1px; box-shadow: 0 1px rgba(252, 3, 3,0.7); margin-top: -0.7em; background: rgba(252, 3, 3,0.8); transform-origin: center left; animation: strikethrough 1s 0.5s cubic-bezier(.55, 0, .1, 1) 1; } @keyframes strikethrough { from { transform: scaleX(0); } to { transform: scaleX(1); } }
<span class="strikethrough">Favor packaging over toy</span>
As you see everything works fine except two things:
Now we can see the line at first then it hides and starts the animation, I want to see only the animated line.
I want to initiate the animation using javascript… but with this pseudo-element (after) it seems complicated!
Advertisement
Answer
You can fix your animation using animation-fill-mode
:
animation-fill-mode: backwards;
To trigger your animation, just add the strikethrough class. The thing where I think this won’t work is when you have a multiline text, as your ::after
won’t cover that.
document.querySelector( '.strikethrough' ).addEventListener( 'click', event => { event.target.classList.toggle( 'strikethrough' ); });
.strikethrough { display: inline-block; position: relative; line-height: 1.5em; } .strikethrough:after { content: ''; position: absolute; display: block; width: 100%; height: 1px; box-shadow: 0 1px rgba(252, 3, 3,0.7); margin-top: -0.7em; background: rgba(252, 3, 3,0.8); transform-origin: center left; animation: strikethrough 1s 0.5s cubic-bezier(.55, 0, .1, 1) 1; animation-fill-mode: backwards; } @keyframes strikethrough { from { transform: scaleX(0); } to { transform: scaleX(1); } }
<span class="strikethrough">Favor packaging over toy</span>
Personally, I would take this simpler tack to reduce the amount of actual objects on screen, and the amount of code, by using a background image to scale. If cleverly set up, you could even multi-line this (by making the background the line height and having a middle pixel in it – and with SVGs you could ensure it was only 1px regardless of the stretching etc…).
document.querySelector( 'p' ).addEventListener( 'click', event => { event.target.classList.toggle( 'strikethrough' ); })
@keyframes stretch { to { background-size: 100% var(--line-height); } } :root { --line-height: 1.2em; } p { line-height: var(--line-height); } .strikethrough { line-height: 1.2em; background: url('data:image/svg+xml;charset=utf8,<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none"><line x1="0" y1="50%" x2="100%" y2="50%" stroke="black" stroke-width="1px" /></svg>') repeat-y 0 0 / 0 var(--line-height); animation: stretch 4s; animation-fill-mode: forwards; }
<p>Hello World!<br />Another line, does it work?</p>