自分で忘年会コンテンツを実装する話

## 僕について

リブセンスの @highwide です。
マッハバイトでPHPやRubyのコードを書いたり、マネジメントをやったりしています。
CSSに苦手意識があります。

## CSSへの苦手意識

どういうときにどんなプロパティを使うのかとかはある程度わかっても、ひとつの画面を組み上げようとしたときに要素ごとの関係性というのが見えず「なんでこのdivがここにあるんじゃああああ」となりがちです。

先日、運営に携わっている、社内のLT大会「0x64物語reboot」で使う投票アプリを実装したのですが、bootstrapを使っていてさえもCSSへの苦手意識によってこんなデザインの有様となっています。

<img width="1333" alt="スクリーンショット 2017-12-12 21.45.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/51449/2a66eb01-938d-f7ef-3402-b1c1e1f2de08.png">


※なお「0x64物語reboot」については、今年、夏のデブサミで発表の機会をいただき、こちらのスライドに詳細な説明などが書いてあります

=> [「さびれた勉強会を復活させる"文化のリファクタリング"」](https://speakerdeck.com/livesense/wen-hua-falserihuakutaringu)

## そんな私のHTML+CSSの学び方

さて、そんな私なのですが、一方では「昨今耳にするようなモダンフロントエンドの各技術に飛びつく前に、ある程度まともにHTML+CSSを組めるようになるようになるべきなのでは」という思いもあり、チームのフロントエンドエンジニアにオススメの教材などを聞きました。

オススメしてもらったのがこちらの本です。

[HTML5/CSS3モダンコーディング フロントエンドエンジニアが教える3つの本格レイアウト](https://www.shoeisha.co.jp/book/detail/9784798141572)

今も読み進めているところなのですが、以下のようなCSSのリファレンスだけではたどり着けないような現場のテクニックをわかりやすく知ることができ、とてもいい感じです。

```css
*, *::before, *::after {
  box-sizing: border-box;
}
```

```css

.clearfix::after {
  content: '';
  display: block;
  clear: both;
}
```

## ところで

ところで話は変わるのですが、新任のマネージャーとして、各職種のマネージャー諸先輩方とのミーティングに参加していると、思わぬ ~~タスク~~ 成長の機会を与えていただけることがあります。

...今回の場合は事業部の忘年会の幹事でした。

※ なお、リブセンスでは本人の志向性や適性を鑑みた上でのアサインを行おうという文化が強く、エンジニアが、その専門性がないがしろにされるようなタスクを無理に押し付けられるということはありません。今回の場合はなんだかんだ言って、(**「今回限りは」の前提のもと**)僕も乗り気だった...と考えていただければと思います。

## 作ったもの

そこで、僕は忘年会のコンテンツとして、最近学習しているHTML+CSSを使ったちょっとした何かを作ろうと考えました。
特に、先の本の内容とはズレてしまうのですが、最近チームメイトがこんな感じ↓に利用したCSS animationを使ってみたい！という気持ちがあり、利用してみることにしました。

![css_animation.gif](https://qiita-image-store.s3.amazonaws.com/0/51449/031adc7f-9472-644e-37c4-df36ef37ea33.gif)

また、当日は来期の新組織体制が発表されるということもあり、それに関連したコンテンツにできれば、皆の関心に応えることができるのではないか、とも考えました。

結果として実装したものがこちらです。

![slot_animation.mov.gif](https://qiita-image-store.s3.amazonaws.com/0/51449/d3a488ba-b1e4-4eef-5dbf-749247938f99.gif)

「 **全然HTML + CSSで複雑なデザインを実現しようとしていない！！！** 」という自分ツッコミはありつつ、外部ライブラリを使わずにスロットマシーンの機構を作ることができました。
スロット部分はCSSアニメーションを実装し、各ボタンの停止/再生はJavaScriptで実装しています。

忘年会に参加してくれている皆さんの前で停止ボタンを押すことで

* 「◯◯グループの」
* 「最年少が」
* 「リブセンスの入社理由」

...というように、誰かが質問に対する回答を語ってもらえるというコンテンツにしました。
これによって新しい組織にどんな人がいるのか、みんなに知ってもらいたいという狙いです。

## どうやってCSSアニメーションでスロット機構を作るの？

JavaScript抜きでスロットの回転を無限に繰り返すのは、どのように実装すべきか軽く悩みました。
これについては、以下サイトを大いに参考させていただきました。

[css3のanimationで作る永久ループのスライドショー - パソコン倶楽部りんご](http://clubringo.com/css3%E3%81%AEanimation%E3%81%A7%E4%BD%9C%E3%82%8B%E6%B0%B8%E4%B9%85%E3%83%AB%E3%83%BC%E3%83%97%E3%81%AE%E3%82%B9%E3%83%A9%E3%82%A4%E3%83%89%E3%82%B7%E3%83%A7%E3%83%BC/)

このサイトに書かれている通り、ユーザーに見えないところでDOM要素を一周させるとやりたいことが実現できると気がつきました。

![css_animation_desc.mov.gif](https://qiita-image-store.s3.amazonaws.com/0/51449/3cb6faac-b180-6207-4f49-9dd117d8a03a.gif)

実装はこんな感じです

```css
.slot-lane ul li {
  animation: slide 1.35s 0s infinite;
  animation-play-state: running;
}
.slot-lane ul li:nth-of-type(1) {
  animation-delay:0s;
}
.slot-lane ul li:nth-of-type(2) {
  animation-delay:0.15s;
}
/* 要素分 animation-delay が続くので省略 */
/* 本当はもうちょっと要素数に応じて動的な定義ができるようにしたかった */
@keyframes slide {
  0% {top:-50px;left:0%;}
  42.85% {top:400px;left:0%;}
  50% {top:400px;left:100%;}
  92.85% {top:-50px;left:100%;}
}
```

また、停止と再生のボタンは、要素の `style.animationPlayState` を書き換えるこのような実装をしました。

```javascript
var slotToggle = function(elem) {
  if(elem.style.animationPlayState === 'paused') {
    elem.style.animationPlayState = 'running'
  } else {
    elem.style.animationPlayState = 'paused'
  }
}
document.getElementById("left-button").onclick = function() {
  var texts = document.getElementById('left-lane').getElementsByTagName('li');   
  Array.prototype.forEach.call(texts, slotToggle);
};
```

※ 返ってきた `HTMLCollection` に対して `forEach` を回すにはどうすればいいんやという点について軽くハマりました。
このへんはとりあえず忘年会に間に合わせるよう、最低限動くように進めてしまったので、ご指摘などあればぜひお願いします...m(_ _)m

## で、どうだったの？

ついさきほど、忘年会が終わりました！
(幹事を務める忘年会と、アドベントカレンダーの担当が同日に重なるのは大変なのでオススメしません)

とりあえず、手前味噌ながら、職種を問わずそれなりに盛り上がったのではないかと思います！
(というのは、質問に答えてくれる人に助けられた部分は多分にあるのですが)

忘年会の幹事を任されてしまったとき、**自**分でコンテンツを実装することでエンジニアとしてやりたいことをやりつつ、みんなの要望に応えることができるのだなぁと感じた1日でした。

以上、「Livesense - 自 Advent Calendar 2017」の12日目の記事でした！