CSSだけで数珠つなぎに無限ループするニュースティッカーを作ってみる
お知らせ等の短い文章をテロップのように横スクロールして表示するCSSサンプルです。
普通(?)のニュースティッカーサンプル
表示例
- ニュースティッカーのテスト1
- ニュースティッカーのテスト2
- ニュースティッカーのテスト3
- ニュースティッカーのテスト4
- ニュースティッカーのテスト5
HTMLとCSS
<div class="news_ticker1">
<ul>
<li>ニュースティッカーのテスト1</li>
<li>ニュースティッカーのテスト2</li>
<li>ニュースティッカーのテスト3</li>
<li>ニュースティッカーのテスト4</li>
<li>ニュースティッカーのテスト5</li>
</ul>
</div>
<style>
.news_ticker1 {
width:300px;
overflow:hidden;
white-space:nowrap;
border:1px solid red;
}
@keyframes hscroll {
0% { transform:translateX(300px); }
100% { transform:translateX(-100%); }
}
.news_ticker1 ul {
display:inline-block;
margin:0;
padding:0;
animation:hscroll 8s linear infinite;
}
.news_ticker1 li {
display:inline-block;
}
</style>
解説
やってることはけっこう単純で、
- ニュースティッカーを表示する枠をdivタグ300pxで作成しwhite-space:nowrap;で折り返しを禁止し、overflow:hidden;ではみ出したテキストは隠すように設定する。
- ul/liをdisplay属性でinline-block化して横並び表示する。
- CSSアニメーションの設定でX座標+300pxの位置(要するに右側の欄外)から、-100%の位置(左側の欄外)まで移動させる。
というだけの動作です。
ただ、サンプルだと枠が300pxなのでそれほど気にならないかもですが、もっと横長になってくると空白の時間が長くなり、ちょっともったいないなぁ~って気になったんですよね。
数珠つなぎなニュースティッカーサンプル
というわけで、その空白期間を無くした数珠つなぎに表示されるニュースティッカーのサンプルです。
表示例
- ニュースティッカーのテスト1
- ニュースティッカーのテスト2
- ニュースティッカーのテスト3
- ニュースティッカーのテスト4
- ニュースティッカーのテスト5
- ニュースティッカーのテスト1
- ニュースティッカーのテスト2
- ニュースティッカーのテスト3
- ニュースティッカーのテスト4
- ニュースティッカーのテスト5
「ニュースティッカーのテスト1~5」まで表示された後、すぐに「ニュースティッカーのテスト1」が繋がって表示されていますよね?
HTMLとCSS
<div class="news_ticker2">
<ul>
<li>ニュースティッカーのテスト1</li>
<li>ニュースティッカーのテスト2</li>
<li>ニュースティッカーのテスト3</li>
<li>ニュースティッカーのテスト4</li>
<li>ニュースティッカーのテスト5</li>
</ul>
<ul>
<li>ニュースティッカーのテスト1</li>
<li>ニュースティッカーのテスト2</li>
<li>ニュースティッカーのテスト3</li>
<li>ニュースティッカーのテスト4</li>
<li>ニュースティッカーのテスト5</li>
</ul>
</div>
<style>
.news_ticker2 {
width:300px;
overflow:hidden;
white-space:nowrap;
border:1px solid red;
}
@keyframes hscroll2 {
0% { transform:translateX(4px); }
100% { transform:translateX(-100%); }
}
.news_ticker2 ul {
display:inline-block;
margin:0;
padding:0;
animation:hscroll2 5s linear infinite;
}
.news_ticker2 li {
display:inline-block;
}
</style>
解説
HTMLタグを見た瞬間にあーなるほどと思われるかもですが、2個並べてるだけです。
どうせこういうニュースティッカーを使う場合はCMSを使ったり、データベースと連動するPHPスクリプト等のサーバーサイドスクリプトを使っているだろうから、同じニュースを2個並べるくらい問題ないかなと思ってこんな実装にしてみました。
そもそも最後の「テスト5」が表示されている最中に「テスト1」をつなげるなんて、HTMLの要素を切って繋げないといけないのでJavaScript使うならともかくCSSだけじゃちょっと無理ですよねー。
JavaScript使うにしても欄外に移動したliタグを切り取って、最後尾につなげ直す…とかちょっと面倒かなぁ…と。ん?そうでもないか…。そのうちやってみようw
まぁそれはともかく、今回はCSSのみで作るのがコンセプトなのでこのまま進めます。
前回からの変更点は
- ulタグのグループを2つにした
- @keyframes hscroll2 を-300pxからのスタートではなく、4pxからスタートにした
だけです。
1個目のULタグのアニメーションが終了した瞬間に、2個目のULタグが最初の位置(4px)に登場すればループがずっと繋がっているように見えるんじゃないかな、と思って試してみたら出来ちゃった感じ。
なんで0pxじゃなくて4pxと中途半端なのかというとliタグとliタグの間に4pxほどの空白が出来るからです。
そのため、 0% { transform:translateX(0px); } みたいな書き方をするとループをつなげる際に一瞬カクッとした感じになります。
見たほうがわかりやすいか。
実際0pxにすると↓こんな感じ。
- ニュースティッカーのテスト1
- ニュースティッカーのテスト2
- ニュースティッカーのテスト3
- ニュースティッカーのテスト4
- ニュースティッカーのテスト5
- ニュースティッカーのテスト1
- ニュースティッカーのテスト2
- ニュースティッカーのテスト3
- ニュースティッカーのテスト4
- ニュースティッカーのテスト5
どうでしょ。テスト5までスクロールした後、一瞬カクついてませんか? もしかしたらブラウザによって微妙に違うかもだけど。
これはinline-blockの特性で、改行があると要素同士の間に空白が入り、アニメーション終了時に空白1個分(4px)のズレが生じるためです。
(inline-block化した)liタグの間に改行を入れなければこんな空白は入らないので、0% { transform:translateX(0px); }という指定で構いません。
まとめ
- CSSだけでmarqueeタグ(HTML5では廃止)みたいなニュースティッカーを作ってみた。
- 単純に欄外から欄外へ横スクロールさせると空白期間が気になった。
- 空白なしでニュースティッカーを数珠つなぎで無限ループさせるよう、ulグループを2つにして繋げてみた。
といったところでしょうか。
単純な仕組みですが、PCとスマホの両対応が求められる昨今、狭い横幅でも情報を詰め込みたい!なんてケースで使えるのではないでしょうか。