ニュースティッカーをCodePenを利用して実装している画面

直近の案件でニュースティッカーを実装する機会があったので、実装の過程を備忘録がてらメモします。

ざっくり言うと、HTMLは普通にマークアップして、javascriptで状態を変更し、CSSで状態に応じたスタイルとアニメーションを付与する、というネタに困ったから記事にしたのがバレるような、何も変わったところのない感じです。あ、状態にはWAI-ARIAを使用しました。

実装例
See the Pen Simple news ticker by Soichi Masuda (@masuP9) on CodePen.

HTML

普通です。

<ul class="news-ticker">
  <li class="news-ticker--item">大発見!!すごい場所からすごいアレがみつかる</li>
  <li class="news-ticker--item">すごすぎるアレのすごい10個の秘密</li>
  <li class="news-ticker--item">すごいアレが本当にすごすぎると話題に</li>
</ul>

javascript

ニュースティッカーの要素のなかで、javascriptでコントロールする状態は itemの表示/非表示です。今回はWAI-ARIAを使って、表示するitemにはaria-hidden="false"を、非表示のものにはaria-hidden="true"を付与します。表示状態を一定時間で切り替えて、ティッカー的な表現にします。

最初に、ニュースティッカー全体にrole="marquee"を付与します。

var ticker = document.querySelector('.news-ticker');
ticker.setAttribute('role', 'marquee');

role="marquee"を与えることで、これはmarqueeみたいに動いたり、もしくは消えたり出たりするやーつだという役割を持つようになります。role="marquee"は暗黙的に情報が更新される領域であることを示すaria-live属性を持ちますが、それほど重要でないことから、その値は支援技術ユーザーに対して更新が通知されないoffに固定されています。

次に、最初のitemを表示、それ以外を非表示にします。

var items = ticker.querySelectorAll('.news-ticker--item');

Array.prototype.forEach.call(items, function(item, index) {
  if (index === 0) {
    item.setAttribute('aria-hidden','false');
  } else {
    item.setAttribute('aria-hidden','true');
  }
});

これを一定時間ごとに切り替えます。

var loopTicker;

function startTicker() {
  clearInterval(loopTicker);

  loopTicker = setInterval(function() {
    var currentTicker = ticker.querySelector('[aria-hidden="false"]'),
        nextTicker = currentTicker.nextElementSibling;

    currentTicker.setAttribute('aria-hidden', 'true');

    if (nextTicker) {
      nextTicker.setAttribute('aria-hidden', 'false');
    } else {
      items[0].setAttribute('aria-hidden', 'false');
    }
  }, 7000);
}

あとはテキストを選択したいとか、リンクならクリックしようとしてる時に表示が消えちゃうとカチンと来るので、マウスカーソルが乗っているときは切り替えを止めます。リンクの時はフォーカスにも同じイベントを設定すると良いですね。

function stopTicker() {
  clearInterval(loopTicker);
}

ticker.addEventListener('mouseover', function() {
  stopTicker();
});

ticker.addEventListener('mouseout', function() {
  startTicker();
});

CSS

CSSでは javascript で与えられた状態に対するスタイリングを行いますので、セレクタもaria-hidden属性の値を参照します。今回は、アニメーションも付与しますのでaria-hidden="true"の場合は、画面から吹っ飛ばして、表示の場合は戻します。

.news-ticker {
  position: relative;
}

.news-ticker--item[aria-hidden="true"] {
  position: absolute;
  left: 200%;
}

.news-ticker--item[aria-hidden="false"] {
  position: relative;
  left: auto;
}

次に、状態が切り替わった時のアニメーションを定義します。表示されるときは左からスライドインさせ、非表示になるときは、右へスライドアウトさせます。

@keyframes slidein {
  from { right: 100%;}
  to   { right: 0%; }
}

@keyframes slideout {
  from { left: 0%; }
  to   { left: 100%;}
}

.news-ticker--item[aria-hidden="true"] {
  animation-duration: 0.5s;
  animation-name: slideout;
}

.news-ticker--item[aria-hidden="false"] {
  animation-duration: 0.5s;
  animation-name: slidin;
}

これらのコードを組み合わせると、冒頭のニュースティッカーになります。ティッカー自体は、jQueryのプラグインなどでも多く作成されていますが、イチから実装してみると色々と気を配れるのでこれぐらいのものをサッと実装できる実装力を高めていきたいですね。