Skip to content

Instantly share code, notes, and snippets.

@ralphilius
Created February 21, 2018 07:06
Show Gist options
  • Save ralphilius/7994dd28692c5eba1a8521d2f986104e to your computer and use it in GitHub Desktop.
Save ralphilius/7994dd28692c5eba1a8521d2f986104e to your computer and use it in GitHub Desktop.
Pure CSS Ticker (Horizontal) by Lewis Carey https://codepen.io/lewismcarey/pen/GJZVoG
* {
box-sizing: border-box;
}
@-webkit-keyframes ticker {
0% {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
visibility: visible;
}
100% {
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
}
}
@keyframes ticker {
0% {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
visibility: visible;
}
100% {
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
}
}
.ticker-wrap {
position: fixed;
bottom: 0;
width: 100%;
overflow: hidden;
height: 1.2rem;
background-color: rgba(0, 0, 0, 0.9);
padding-left: 100%;
box-sizing: content-box;
}
.ticker-wrap .ticker {
display: inline-block;
height: 1rem;
line-height: 1rem;
white-space: nowrap;
padding-right: 100%;
box-sizing: content-box;
-webkit-animation-iteration-count: infinite;
animation-iteration-count: infinite;
-webkit-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-name: ticker;
animation-name: ticker;
-webkit-animation-duration: 30s;
animation-duration: 30s;
}
.ticker-wrap .ticker__item {
display: inline-block;
padding: 0 1rem;
font-size: 0.7rem;
color: white;
}
body {
padding-bottom: 5rem;
}
h1, h2, p {
padding: 0 5%;
}
* { box-sizing: border-box; }
$duration: 30s;
@-webkit-keyframes ticker {
0% {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
visibility: visible;
}
100% {
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
}
}
@keyframes ticker {
0% {
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
visibility: visible;
}
100% {
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
}
}
.ticker-wrap {
position: fixed;
bottom: 0;
width: 100%;
overflow: hidden;
height: 1.2rem;
background-color: rgba(#000, 0.9);
padding-left: 100%;
box-sizing: content-box;
.ticker {
display: inline-block;
height: 1rem;
line-height: 1rem;
white-space: nowrap;
padding-right: 100%;
box-sizing: content-box;
-webkit-animation-iteration-count: infinite;
animation-iteration-count: infinite;
-webkit-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-name: ticker;
animation-name: ticker;
-webkit-animation-duration: $duration;
animation-duration: $duration;
&__item {
display: inline-block;
padding: 0 1rem;
font-size: 0.7rem;
color: white;
}
}
}
body { padding-bottom: 5rem; }
h1,h2,p {padding: 0 5%;}
<h1>Pure CSS Ticker (No-JS)</h1>
<h2>A smooth horizontal news like ticker using CSS transform on infinite loop</h2>
<div class="ticker-wrap">
<div class="ticker">
<div class="ticker__item">Letterpress chambray brunch.</div>
<div class="ticker__item">Vice mlkshk crucifix </div>
<div class="ticker__item">Ugh PBR&B kale </div>
<div class="ticker__item">Gluten-free mumblecore </div>
<div class="ticker__item">Authentic bitters </div>
<div class="ticker__item">Letterpress chambray brunch.</div>
<div class="ticker__item">Vice mlkshk </div>
<div class="ticker__item">Ugh PBR&B kale chips Echo Park.</div>
<div class="ticker__item">Gluten-free </div>
<div class="ticker__item">Authentic bitters </div>
</div>
</div>
<p>So, annoyingly, most JS solutions don't do horizontal tickers on an infinite loop, nor do they render all that smoothly.</p>
<p>The difficulty with CSS was getting the animation to transform the entire items 100% yet include an offset that was only the width of the browser (and not the items full width).</p>
<p>Setting the start of the animation to anything less than zero (e.g. -100%) is unreliable as it is based on the items width, and may not offset the full width of the browser or creates too large an offset</p>
<p>Padding left on the wrapper allows us the correct initial offset, but you still get a 'jump' as it then loops too soon. (The full text does not travel off-screen)</p>
<p>This is where adding display:inline-block to the item parent, where the natural behaviour of the element exists as inline, gives an opportunity to add padding-right 100% here. The padding is taken from the parent (as its treated as inline) which usefully is the wrapper width.</p>
<p><b>Magically*</b> we now have perfect 100% offset, a true 100% translate (width of items) and enough padding in the element to ensure all items leave the screen before it repeats! (width of browser)</p>
<p>*Why this works: The inside of an inline-block is formatted as a block box, and the element itself is formatted as an atomic inline-level box. <br>Uses `box-sizing: content-box`<br>
Padding is calculated on the width of the containing box.<br>
So as both the ticker and the items are formatted as nested inline, the padding must be calculated by the ticker wrap.</p>
<p>Ticker content c/o <a href="http://hipsum.co/">Hipsum.co</a></p>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment