cssのみで表現するパララックス
TL;DR
- 今回は掲題の通り、パララックスを css だけで表現するよ。
- とはいえ開発ツールとして docker とか prettier とか sass とか使うよ
- 今回は Mac Chrome ブラウザで動作確認したけどそれ以外は確認していないからクロスブラウザでちゃんと動くかは保証しないから苦情は受け付けないよ。
position: sticky
に正常に対応しているブラウザなら大丈夫なはずだけどね。 - 前提の説明が長すぎるので結論から見たい人は 本題 だけ見るといいと思うよ。
- あくまで方法の一つとして紹介がてら css で遊んでただけだから随所で適当な箇所があるよ。
- リポジトリは公開しているから適当に見てね
parallax-sample - 実際のページは こちら
利用ツール
- docker for Mac
- sass
- eslint
- prettier
- stylelint
- nodejs 18.x
ファイル構成
├── LICENSE
├── README.md
├── docker-compose.yml
├── docs
│ ├── css
│ │ └── index.css
│ ├── favicon.ico
│ └── index.html
├── package.json
├── src
│ └── scss
│ └── index.scss
└── yarn.lock
各ファイルについて
テキスト形式ファイル
下記は見ての通り
LICENSE
README.md
docker について
localhost で http アクセスするために docker を利用するよ。
README にある通りだけど一応解説しておくと docker-compose.yml
にhttpd(apache)
を使って http 越しにアクセスするよ。
今回は js 使ってないから関係ないけど js を動かす場合 file://
プロトコル で 直接 local の html を表示した場合、セキュリティの関係でブラウザが js をブロックするからその対策だと思ってくれて構わないよ。
というわけで
$ docker-compose up -d
# 使い終わったら落とす
# $ docker-compose down
上記を叩いて http サーバを立ち上げるんだ。
そうすることでdocker-compose.yml
に記載したとおり
# imageの指定だよ
image: httpd:2.4
volumes:
# ローカルのdocsディレクトリをdockerコンテナ内の/usr/local/apache2/htdocs/ ディレクトリと同期するよ
- ./docs:/usr/local/apache2/htdocs/
ports:
# ローカルの8080番ポートをコンテナ内の80番ポートに転送するよ
- '8080:80'
こうすることで http://localhost:8080/
にアクセスすることで docs 配下のファイルにアクセスできるよ。
これでブラウザからアクセスする準備は完了だ。
npm モジュールについて
今回 npm モジュールをいくつか使っているけどこれらは docs 配下に直接 html と css を記載するだけなら本当は必要ないんだ。
ちなみに npm run コマンド
と yarn コマンド
はほぼ同義だ。
各モジュールについて解説しよう。
-
eslint*
これらは js を整形、指定した規則に従わせるツールだ(今回は js 使ってないから無視してくれて構わない) -
npm-run-all
これは npm run をワイルドカードで起動できる便利ツールだ。後で少しだけ解説するよ。 -
sass
css を scss で記述するために使うよ -
prettier
対象のファイルを整形するツールだよ。 -
stylelint*
css の整形ツールだよ。
ぶっちゃけ sass 以外は整形するためのツールだからなくとも構わない。
npm-run-all
は package.json
の scripts に記述したコマンドを一括で実行するためのツールだ。
{
"scripts": {
"fix:scss": "stylelint --fix src/**/*.{css,scss,sass} --config-basedir .",
"fix:eslint": "eslint --fix .",
"fix:prettier": "prettier --write .",
"fix": "run-s fix:*",
"build:sass": "yarn sass --no-source-map src/scss/:./docs/css/ && rm -rf docs/css/index.css.map",
"watch:sass": "yarn sass --watch src/scss/:./docs/css/"
}
}
今回 scripts には上記の様に記載してある。
これらはnpm run fix:scss
と打つと
$ npm run stylelint --fix src/**/*.{css,scss,sass} --config-basedir .
と打つのと同じ意味になる。つまりはショートカットを定義しているんだ。
そして npm-run-all
によってこれらのショートカットをまとめて叩くことが可能になるんだ。
例えば npm run fix
とうつと
# run-s はシリアル、つまり順次実行するという意味でfix:*にマッチするスクリプトを実行する
# run-p とした場合はパラレル、つまり非同期に実行するよ。
# 個々のファイルを同時にいじるとまずいから今回は-sでシリアルに実行する
$ run-s fix:*
となる。
次に sass のコンパイルのお話だ。
$ npm run build:sass
を実行することで
$ yarn sass --no-source-map src/scss/:./docs/css/ && rm -rf docs/css/index.css.map
# yarn sass --no-source-map src/scss/:./docs/css/
# 上記でsrc/scssの中身をdocs/css/にコンパイルしている
# その上でもしソースマップが存在していた場合、
# rm -rf docs/css/index.css.map
# で削除する
$ yarn sass --watch src/scss/:./docs/css/
# これはscssをコンパイルするのは変わらないけどwatchなので変更を検知してリアルタイムで変換する
# そしてこのコマンドを実行することによってソースマップも作られる
# 開発中は watch でリアルタイム反映してリリースする時にbuildする感じの使い方をするよ。
となる。 [1]
本題
長くなったけどここからが本題
まず html だけどこんな感じ
html
<div>
<section>
<img src="https://picsum.photos/1280/720?random=1" alt="image-1" />
<div class="description">image 1</div>
</section>
<section>
<img src="https://picsum.photos/1280/720?random=2" alt="image-2" />
<div class="description">image 2</div>
</section>
<section>
<img src="https://picsum.photos/1280/720?random=3" alt="image-3" />
<div class="description">image 3</div>
</section>
<section>
<img src="https://picsum.photos/1280/720?random=4" alt="image-4" />
<div class="description">image 4</div>
</section>
<section>
<img src="https://picsum.photos/1280/720?random=5" alt="image-5" />
<div class="description">image 5</div>
</section>
<footer>
<p class="leading-loose">Images from <a class="no-underline" href="https://unsplash.com">Unsplash</a></p>
</footer>
</div>
可能な限りシンプルな構成にしてみたよ。
footer
は画像利用のライセンス表記だからあまり気にしないで欲しい。
scss
まず @use
でインポートしているのはいわゆる reset css だね。
各ブラウザ間の差異を打ち消す css なので必ずしも必要というわけではない。
@use '../../node_modules/destyle.css/destyle.css';
body {
font-size: 16px;
color: #fff;
> div {
position: relative;
}
}
section {
position: sticky;
top: 0;
display: block;
width: 100vw;
height: 100vh;
}
img {
position: absolute;
object-fit: cover;
object-position: center center;
width: 100%;
height: 100%;
}
footer {
position: sticky;
bottom: 0;
display: block;
padding: 15px;
background: rgb(255 255 255 / 30%);
p {
color: #000;
a {
color: #fff;
}
&.leading-loose {
text-align: right;
}
}
}
.description {
position: absolute;
top: 50%;
left: 50%;
width: 100%;
font-size: 5rem;
text-align: center;
text-shadow: 1px 1px 15px rgb(0 0 0);
transform: translate(-50%, -50%);
}
要所を解説すると section
に関する指定が今回の本懐。
position: sticky;
にすることでスクロール時に要素が隠れるまで固定表示にしている。
ただしそのままだと中の要素のサイズによってサイズが変動してしまうので 1 セクションを 1 ページとするためにwidth
を100vw
[2] height
を100vh
[3] とする。
これにより section
が画面サイズを気にせずにページサイズになる。
中のコンテンツは <img src="https://picsum.photos/1280/720?random=n" alt="image-n" />
で背景画像を表示している。
https://picsum.photos/1280/720
が毎回指定したサイズでランダムで画像を返してくれるので今回のサンプルで利用させてもらってるよ。
そしてこの画像自体もサイズは section
と同じサイズまで調整して background-size: cover
と指定したのと同様にしている。
あとは div で中に文字を表示しているだけでこの辺は css の基本がわかっていれば特に難しい話でもないので割愛するよ。
まとめ
どうだろうか。
こんな感じでサクッと開発環境を構築して適当に css 書いてパララックスを実装してみた。
今回は見た目でわかりやすいよう画像を背景に無理やり指定しているけど section に背景色を指定するだけで画像も使わずもっと簡単にパララックスを実装できる。
なにかの参考になると幸いだ。
Discussion