Just a quick tip today! I was asked by a client to create an old-school ticker that was fixed to the bottom of the screen, with latest alerts and information for visiting users. I knew immediately I wanted a CSS only implementation, which I managed with the following code:
<aside class="ticker">
<div class="ticker__inner">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam a ipsum at lorem varius tincidunt quis sed nunc.</p>
</div>
</aside>
.ticker {
--ticker-duration: 45s;
position: fixed;
bottom: 0;
left: 0;
width: 100%;
z-index: 10;
background: #000;
color: #fff;
overflow: hidden;
padding: 0.5rem;
}
.ticker__inner {
display: flex;
align-items: center;
justify-content: center;
flex-wrap: nowrap;
white-space: nowrap;
animation-iteration-count: infinite;
animation-timing-function: linear;
animation-name: ticker;
animation-duration: var(--ticker-duration);
text-align: center;
padding-left: 100%;
width: max-content;
}
.ticker__inner p {
margin: 0 2rem;
}
@keyframes ticker {
0% {
transform: translate3d(0%, 0, 0);
}
100% {
transform: translate3d(-100%, 0, 0);
}
}
Improving our Component
We can do a few things to improve our component, starting with the following reset. This will stop animation for users who prefer to not see animations and transitions (such a handy reset, thanks Andy Bell!):
/** Reset for users who would prefer no animations **/
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
Of course, if the animation isn't running then some of the content will be hidden by our overflow: hidden
. So to combat this, let's format it nicely for users:
@media (prefers-reduced-motion: reduce) {
.ticker__inner {
flex-wrap: wrap;
white-space: inherit;
padding-left: 0;
width: auto;
}
}
And that's a wrap! You can view the final code on Codepen.