slick でフェードスライダーを作成する

[slick](http://kenwheeler.github.io/slick/) を使用した、フェードで切り替わるスライダーのコードを紹介します。
アニメーションは全て CSS で制御しているため、[slick](http://kenwheeler.github.io/slick/) 以外のスライダーライブラリにも流用可能です。

# 完成形

<p class="codepen" data-height="400" data-default-tab="result" data-slug-hash="LYQYVPE" data-user="RikuOta" style="height: 400px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/RikuOta/pen/LYQYVPE">
  Untitled</a> by Riku Ota (<a href="https://codepen.io/RikuOta">@RikuOta</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

# HTML

<details>
<summary>コード</summary>

```html
<div class="slider js-slider">
  <!-- 1つ目のスライド -->
  <div class="slideItem">
    <div class="slideItem__inner">
      <p class="slideItem__image">
        <img src="https://picsum.photos/300/200" alt="サンプル画像">
      </p>
      <div>
        <p class="slideItem__title">
          <span>1つ目のスライドです</span>
        </p>
        <div class="slideItem__text1">
          <p>1つ目のスライドです。</p>
          <p>1つ目のスライドです。</p>
        </div>
        <div class="slideItem__text2">
          <p>1つ目のスライドです。</p>
          <p>1つ目のスライドです。</p>
        </div>
      </div>
    </div>
  </div>
  <!-- 1つ目のスライド -->

  <!-- 2つ目のスライド -->
  <div class="slideItem">
    <div class="slideItem__inner">
      <p class="slideItem__image">
        <img src="https://picsum.photos/300/210" alt="サンプル画像">
      </p>
      <div>
        <p class="slideItem__title">
          <span>2つ目のスライドです</span>
        </p>
        <div class="slideItem__text1">
          <p>2つ目のスライドです。</p>
          <p>2つ目のスライドです。</p>
        </div>
        <div class="slideItem__text2">
          <p>2つ目のスライドです。</p>
          <p>2つ目のスライドです。</p>
        </div>
      </div>
    </div>
  </div>
  <!-- 2つ目のスライド -->

  <!-- 3つ目のスライド -->
  <div class="slideItem">
    <div class="slideItem__inner">
      <p class="slideItem__image">
        <img src="https://picsum.photos/300/220" alt="サンプル画像">
      </p>
      <div>
        <p class="slideItem__title">
          <span>3つ目のスライドです</span>
        </p>
        <div class="slideItem__text1">
          <p>3つ目のスライドです。</p>
          <p>3つ目のスライドです。</p>
        </div>
        <div class="slideItem__text2">
          <p>3つ目のスライドです。</p>
          <p>3つ目のスライドです。</p>
        </div>
      </div>
    </div>
  </div>
  <!-- 3つ目のスライド -->
</div>
```
</details>

# JavaScript

```javascript
$(".js-slider").slick({
  fade: true,
  speed: 0,
  touchThreshold: 100
});
```

# CSS (SCSS)

```scss
body {
  color: #444;
  font-family: -apple-system, BlinkMacSystemFont, 'Hiragino Kaku Gothic ProN', 'ヒラギノ角ゴ ProN W3', Arial, YuGothic, 'Yu Gothic', Osaka, Meiryo, メイリオ, sans-serif;
}

// slick の「←」と「→」ボタン
.slick-arrow {
  // 色
  &::before {
    color: #222;
  }
}

// slick は オプションで `fade: true` とした場合、
// CSS の opacity プロパティを切り替えることでスライドの表示・非表示を制御している
// しかし、今回はスライド内の各要素 (画像やタイトルなど) に異なるアニメーションをつけたいため、
// スライド自身は常に `opacity: 1` を指定して表示しておく
.slick-slide {
  opacity: 1 !important;
}

// レイアウト用
.slider {
  max-width: 600px;
  margin: 0 auto;
  padding-top: 40px;
}

.slideItem {
  // レイアウト用
  &__inner {
    display: flex;
    justify-content: center;
  }

  &__image {
    margin-bottom: 32px;
    margin-right: 40px;

    // アニメーション (非アクティブになったとき)
    opacity: 0;
    transition: 0.3s;

    // アニメーション (アクティブになったとき)
    @at-root .slick-active & {
      opacity: 1;
      transition: 0.5s 0.3s;
    }
  }

  &__title {
    padding: 4px;
    margin: -4px;
    font-size: 1.2em;
    font-weight: bold;
    margin-bottom: 24px;
    position: relative;

    &::before {
      background-color: currentColor;
      position: absolute;
      top: 0;
      left: 0;
      height: 100%;
      content: "";

      // アニメーション (アクティブになったとき)
      @at-root .slick-active & {
        animation: stretch-left-to-right 0.6s both;
        @keyframes stretch-left-to-right {
          0% {
            left: 0;
            width: 0;
          }
          50% {
            left: 0;
            width: 100%;
          }
          51% {
            left: auto;
            right: 0;
            width: 100%;
          }
          100% {
            left: auto;
            right: 0;
            width: 0;
          }
        }
      }
    }

    > span {
      // アニメーション (非アクティブになったとき)
      opacity: 0;
      transition: 0s 0.3s;

      // アニメーション (アクティブになったとき)
      @at-root .slick-active & {
        opacity: 1;
      }
    }
  }

  &__text1 {
    line-height: 1.5;

    // アニメーション (非アクティブになったとき)
    opacity: 0;
    transition: 0.3s;
    transform: translateY(1em);

    // アニメーション (アクティブになったとき)
    @at-root .slick-active & {
      opacity: 1;
      transition: 0.3s 0.3s;
      transform: translateY(0);
    }
  }

  &__text2 {
    font-size: 14px;
    margin: 16px 0;
    padding: 1em;
    line-height: 1.75;
    position: relative;
    background-color: #f4f4f4;

    // アニメーション (非アクティブになったとき)
    opacity: 0;
    transition: 0.3s;
    transform: translateY(1em);

    // アニメーション (アクティブになったとき)
    @at-root .slick-active & {
      opacity: 1;
      transition: 0.3s 0.37s;
      transform: translateY(0);
    }
  }
}
```