Reputation: 249
I'm trying to animate a span that moves back and forth enclosed within a div using CSS3 keyframes. Ideally, I'd like the keyframes to look something like this:
@-webkit-keyframes backandforth {
0% {text-align:left;} 50%{text-align:right;} 100%{text-align:left;}
}
But since it's not possible to animate text-align, I've been searching for an alternative property that can be animated to reach the desired positioning. That's where I'm stuck at.
I tried setting the left property to 100% midway through the animation, but that ended up pushing the span off the div. I also tried animating the float property, but that didn't work.
Then I saw this question on moving text from left to right and tried the JSFiddle from the top answer. While it looks like the solution, it unfortunately did not work for me since I want my animation to move continuously at ease, and for the last few seconds of that animation, the span stalls.
Upvotes: 7
Views: 16399
Reputation: 130065
To infinitely animate a node back-and-forth use the alternate infinite
values for the animate
property which points to a @keyframes
rule with only 1
keyframe, which represent the end-state (in the below case moving a div
to the right-side).
Note that in the below example I intentionally did not use position
but used the "new" (as of writing) container
property which opens up the usage for container size units translateX(calc(100cqw - 100%))
The first div
(top-most) is relative to the body
element, and the second div
is relative to the fieldset
(its wrapper), because both the body
and the fieldset
has the container
property applied.
body {
container-type: size;
}
div {
display: inline-block;
outline: 1px solid red;
animation: move 1s ease-in-out alternate infinite;
}
/* or inside a container */
fieldset {
width: 50%;
border: 2px dashed green;
margin: 1em 0;
padding: 0;
container-type: inline-size;
}
@keyframes move {
to { transform: translateX(calc(100cqw - 100%)) }
}
<div>I'm moving!</div>
<fieldset>
<legend>Inside a container</legend>
<div>I'm moving!</div>
</fieldset>
Upvotes: 0
Reputation: 5849
you can play around the left position when the animation is at 50% like so :
because when you put it left: 100%
it depend on the left corner of the span this is why it will go out the container div
@-webkit-keyframes backandforth {0%{left:0;} 50%{left:58%;} 100%{left:0;}}
I hope this fits your needs
var thisis = document.getElementById("wrapper");
var tyty = document.getElementById("move");
var witth = tyty.offsetWidth;
thisis.style.paddingRight = witth +"px";
with this JS whatever you change the text it will still in the container div
Upvotes: 6
Reputation: 1594
There is also a pure-CSS way to do it if you combine absolute positioning left
with simultaneous transform: translate
.
https://jsfiddle.net/cd7kjwy6/
* {
box-sizing: border-box;
}
html {
font-size: 16px;
}
.mt-2 {
margin-top: 0.5rem;
}
/* ---------------- relevant CSS ---------------- */
.animated {
position: relative;
background-color: pink;
max-width: 200px;
overflow: hidden;
line-height: 3rem;
height: 3rem;
}
.animated__text {
position: absolute;
animation: 3s bounce ease-in-out infinite paused;
white-space: nowrap;
top: 0;
padding: 0 0.5rem;
}
.animated:not(.animated--on-hover) .animated__text,
.animated.animated--on-hover:hover .animated__text {
animation-play-state: running;
}
@keyframes bounce {
0%, 5%, 95%, 100% {
left: 0%;
transform: translate(0, 0);
}
45%, 55% {
left: 100%;
transform: translate(-100%, 0);
}
}
<div class="animated">
<span class="animated__text">animate me!</span>
</div>
<div class="animated mt-2">
<span class="animated__text">Longcat is looooooooooooooooooong!</span>
</div>
<div class="animated mt-2">
<span class="animated__text">~</span>
</div>
<div class="animated animated--on-hover mt-2">
<span class="animated__text">only on hover</span>
</div>
If you wanted to snap the "hover" variant back to the original position, you could use something like this (or JavaScript for a proper reset):
.animated.animated--on-hover:not(:hover) .animated__text {
left: 0 !important;
transform: translate(0, 0) !important;
}
Upvotes: 2