【CSS】画像のbefore・afterをスライドさせて、比較できるようなUIを作ってみた。

## 概要

みなさんは、このようなUIは見たことがあるでしょうか？

この記事では、↓このようなUIをCSSだけで作成する方法と`Image Compare Viewer`を使う方法を紹介します。

![スクリーンショット 2022-08-26 0.46.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390720/3d41cced-26a1-e058-3d93-a5efa3209d4c.png)


## CSSだけで実装する場合
:::note warn
CSSで実装する場合は、CSS プロパティの`resize`を使うため、
before と afterを切り替えるためのドラックするUIが少し扱いづらいですがご了承ください。
:::

### 基本的な書き方
以下のようなHTMLに対してスタイルを当てる前提で進めます。

```HTML
<div class="container">
    <div class="before">
        <img src="**/**/before.jpeg" class="image"/>
    </div>
    <img src="**/**/after.jpeg" class="image"/>
</div>
```
　
基本方針は、

> `beforeクラス`のdivを`position: absolute;`で`after画像`の上に持ってきて、
cssプロパティのresize要素で`beforeクラス`のdivを可変させる

このようにスタイルを当てていきます。


### スタイルを当てる

#### STEP. 1 before・afterの画像を重ねる
まずは、`beforeクラス`のdivを`after画像`の上に持ってきます。
`.container`に`position: relative;`、`.before`に`position: absolute;`を指定すると、
before・afterの画像を重ねることができます。

```css
.container {
  position: relative;
  width: fit-content; 
}

.before {
  position: absolute;
}

.image {
  display: block;
}
```

<p class="codepen" data-height="300" data-slug-hash="qBoGrxB" data-editable="true" data-user="sp_degu" style="height: 300px; 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/sp_degu/pen/qBoGrxB">
  resize - 1</a> by でぐぅー | Qiita (<a href="https://codepen.io/sp_degu">@sp_degu</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

#### STEP. 2 リサイズできるようにする
div要素をリサイズできるようにするために、
`resize: horizontal;`と`overflow: auto;`を指定することで、
水平方向へのリサイズができるようになります。

このようにすると、水平方向へ画面がある限りリサイズできるので、
`max-width`を決めて、最大サイズを決めます。

```css
.container {
  position: relative;
  width: fit-content; 
}

.before {
  position: absolute;
  resize: horizontal; /* 追加 */
  overflow: auto; /* 追加 */
  max-width: 100%; /* 追加 */
}

.image {
  display: block;
}
```

<p class="codepen" data-height="300" data-slug-hash="poLmexx" data-editable="true" data-user="sp_degu" style="height: 300px; 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/sp_degu/pen/poLmexx">
  resize - 1</a> by でぐぅー | Qiita (<a href="https://codepen.io/sp_degu">@sp_degu</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

*※ 画像の右下のアイコンから、リサイズできます。*


#### STEP. 3 デザインを調整する
以下のスタイルを調整します。

+ before・afterで半分ずつ表示させたいので、`beforeクラス`のdivにwidthを指定します。
+ 画像の境界がわかりやすいようにborderを追加します。

変更したスタイルはこんな感じです。

```css
.container {
  position: relative;
  width: fit-content;
  border: 1px solid rgba(0,0,0,.12); /* 追加 */
}

.before {
  position: absolute;
  resize: horizontal;
  overflow: auto;
  max-width: 100%;
  width: 50%; /* 追加 */
  border-right: 1px solid red; /* 追加 */
}

.image {
  display: block;
}
```

<p class="codepen" data-height="300" data-slug-hash="mdxgzrx" data-editable="true" data-user="sp_degu" style="height: 300px; 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/sp_degu/pen/mdxgzrx">
  resize - complete</a> by でぐぅー | Qiita (<a href="https://codepen.io/sp_degu">@sp_degu</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>




## `Image Compare Viewer`で実装する場合
CSSだけで、画像のbefore・afterを比較できるようなUIを作ると
ドラッグする部分がわかりにくいので、ユーザビリティがあまり良くありません。

そういう時は、`Image Compare Viewer`を使うと便利です。


### 使い方
#### STEP. 1 外部ファイルをインポートする。 
スクリプトとスタイルシートを外部ファイルとして記述します。

```HTML
<head>
  <script src="https://unpkg.com/image-compare-viewer/dist/image-compare-viewer.min.js"></script>
  <link type="text/css" href="https://unpkg.com/image-compare-viewer/dist/image-compare-viewer.min.css">
</head>
```

npnを使う時は、こちらのコマンドで利用します。
```
npm install image-compare-viewer
```

#### STEP. 2 HTMLを記述する
beforeとafterの画像を記述して、親要素にidを指定します。
```HTML
<div id="image-compare">
  <img src="**/**/before.jpeg" alt=""/>
  <img src="**/**/after.jpeg" alt=""/>
</div>
```

#### STEP. 3 JavaScriptを記述する
スクリプトを初期化して、親のidを指定して実行します。

```javascript
import imageCompareViewer from "https://cdn.skypack.dev/image-compare-viewer@1.5.0";
const element = document.getElementById("image-compare");
const viewer = new imageCompareViewer(element).mount();
```

### 完成したのがこちら
<p class="codepen" data-height="300" data-slug-hash="OJvYmLQ" data-editable="true" data-user="sp_degu" style="height: 300px; 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/sp_degu/pen/OJvYmLQ">
  Untitled</a> by でぐぅー | Qiita (<a href="https://codepen.io/sp_degu">@sp_degu</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

### カスタマイズする
オプションをつけると、UIをカスタマイズすることができます。

property|値|解説
--|--|--
controlColor|Color|コントローラーの枠線、図の色
controlShadow|Bool|コントローラーに影をつけるか
addCircle|Bool|コントローラーの周りにサークルをつけるか
addCircleBlur|Bool|コントローラーの周りのサークルにブラーをつけるか
showLabels|Bool|画像にラベルをつけるか
**labelOptions**|--|ラベルのオプション
　┗ before|String|ラベルの文字
　┗ after|String|ラベルの文字
　┗ onHover|Bool|ホバーした時にラベルを表示させるか
smoothing|Bool|タッチでアニメーションさせるか
smoothingAmount|Number|スムージングの時間
hoverStart|Bool|ホバーしたら枠がついていくようするか
verticalMode|Bool|縦に分けるか
startingPoint|Number|スタートの位置
fluidMode|bool|コンテナの高さと幅を互いに独立したフルードにするか


## まとめ
この記事では、画像のbefore・afterをスライドさせて、比較できるようなUIについて、

CSSだけで実装する方法と `Image Compare Viewer`で実装する方法を紹介しました。

エンジニア夏休み企画をやっているので、普段業務では使わないけど、
やってみたかったことをしてみました。

CSSだけで、画像のbefore・afterをスライドさせて、比較できるようなUIは、結構無理がありそうです。
紹介した内容が限界でした。

https://qiita.com/official-events/6d31965c499a69377c0b

---

最後まで読んでくださってありがとうございます！

普段はデザインやフロントエンドを中心にQiitaに記事を投稿しているので、ぜひQiitaのフォローとX(Twitter)のフォローをお願いします。

https://twitter.com/degudegu2510