😄

[CSS]: CSSで本のページをめくる動き(ページのたわみ)を再現してみた

に公開

CSSで本のページをめくる動き(ページのたわみ)を再現してみた

ちょっと前にCSSでページをめくったときのたわみを再現してみたく遊んでみた結果できたので、あまり役には立ちませんが備忘録として残します。

動作環境

  • react v19
  • css

コード

結論としてはこんな感じのコードです。

"use client"

import { useRef } from "react"

const Test = () => {
  const ref = useRef<HTMLDivElement | null>(null)

  const onClick = () => {
    ref.current?.classList.add("flip")
  }

  return (
    <div 
      className="page"
      ref={ref} 
      onClick={() => onClick()}
      >
      <div className="w-[50px] h-[500px] absolute !right-0" />                       
      <div>
        <div>
          <div>
            <div>
              <div>
                <div>
                  <div>
                    <div>
                      <div>
                        <div>
                          <div>
                            <div>
                              <div>
                                <div>
                                  <div>
                                    <div>
                                      <div>
                                        <div>
                                          <div>
                                            <div>
                                              <div>
                                                <div>
                                                  <div>
                                                    <div>
                                                      <div></div>
                                                    </div>
                                                  </div>
                                                </div>
                                              </div>
                                            </div>
                                          </div>
                                        </div>
                                      </div>
                                    </div>
                                  </div>
                                </div>
                              </div>
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  )
}

export default Test;
body {
  padding: 8rem;
}

.page {
  height: 500px;
  visibility: visible;
  transform-style: preserve-3d;
  transition-duration: 2s;
  transform-origin: right;
  position: absolute;
  right: 50%;
}

.page div {
  width: 15px;
  height: 500px;
  position: absolute;
  right: 15px;
  transform-style: preserve-3d;
  transform-origin: 100% 100%;
  background-color: rgb(221, 223, 209);
}

.flip {
  transform: perspective(1500px) rotatey(180deg);
}

.flip div > div {
  animation: flip 4s ease;
  transform-origin: right;
}

@keyframes flip {
  25% {
    transform: rotateY(-6deg);
  }
  100% {
    transform: rotateY(0deg);
  }
}

コード

動作はこんな感じです
動作

ここから確認できます

  1. classNameがpageのdiv要素に対して180度回転させることでページをめくる動作を再現
  2. 入れ子になっているそれぞれのdiv要素に対して右側を支点にして回転アニメーションを設定することでたわみが再現できます。

デメリット

  • 画像を表示するとき、それぞれの入れ子に対してposition-xを設定してずらしながら表示しなければいけない
  • 複数ページ実装すると処理が重くなり、かくついてくる

力業で小説っぽいUIも実装できます

※ zIndexの対策を行っていないので、クリック直後に次のページが表示されます

小説

最後に

もっといい方法などあれば、コメントに書いていただけると幸いです。
よろしくお願いいたします。

GitHubで編集を提案

Discussion