よくある機能の実装です。やりたいことはこちら。
- スマホ画面でちょっとスクロールダウンしたら右下にボタンが表示される
- ボタンを押すと、画面の一番上まで戻れる
Gatsby は React なので、useState
とuseEffect
をメインで使って、あと CSS で実装していきます。
このブログの Scroll to Top でもデザイン以外は全く同じものが使われていますので、スマホの人は動きが見れていると思います。
CSS でボタンを作る
今回 layout.js 配下にスクロールアップボタンコンポーネントを配置して全画面で使えるようにします。
なので、CSS は layout.js で読んでいるところに追加してください。
/* base.css */
#scrollBtn {
display: none; /* Hidden by default */
}
@media only screen and (max-width: 580px) {
#scrollBtn {
display: block;
position: fixed;
bottom: 20px;
right: 30px;
z-index: 99;
border: none;
outline: none;
background-color: blue;
color: white;
cursor: pointer;
padding: 15px;
border-radius: 10px;
font-size: 18px;
animation: fadeIn 1.5s ease 0s 1 normal;
}
#scrollBtn:hover {
background-color: #555;
}
}
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@-webkit-keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
スマホのみに表示させたいので、PC 画面ではhidden
にしています。
重要なところはz-index
とposition: fixed
、それから位置を決めるbottom
とright
くらいでしょうか。
ボタンのデザインは適宜変更してください。
また、animation
を使ってフェードインするようにしています。
コンポーネント追加
今回は、Scroll
コンポーネントという名前で作ってみたいと思います。
// components/scroll.js
import React, { useState, useEffect } from 'react'
const Scroll = ({ showBelow }) => {
const [show, setShow] = useState(showBelow ? false : true)
const handleScroll = () => {
if (window.pageYOffset > showBelow) {
if (!show) setShow(true)
} else {
if (show) setShow(false)
}
}
const handleClick = () => {
window[`scrollTo`]({ top: 0, behavior: `smooth` })
}
useEffect(() => {
if (showBelow) {
window.addEventListener(`scroll`, handleScroll)
return () => window.removeEventListener(`scroll`, handleScroll)
}
})
return (
<div>
{show && (
<button onClick={handleClick} id="scrollBtn" aria-label="to top">
Top
</button>
)}
</div>
)
}
export default Scroll
useEffect
でスクロール位置を監視して、引数で渡したshowBelow
の値よりも下に行ったら表示されるようになっています。
layout.js に組み込む
layout.js
の適当な場所にScroll
コンポーネントを配置します。
// layout.js
// 他のインポートは省略
import Scroll from './scroll'
const DefaultLayout = ({ children }) => (
<StaticQuery
query={graphql`
query SiteTitleQuery {
site {
siteMetadata {
title
author
description
}
}
}
`}
render={data => (
<div className="">
<Header siteMetadata={data.site.siteMetadata} />
<div>{children}</div>
<Footer />
<Scroll showBelow={250} /> // この部分を追加
</div>
)}
/>
)
DefaultLayout.propTypes = {
children: PropTypes.node.isRequired,
}
export default DefaultLayout
引数は適宜変えて使ってください。
完成!
これでバッチリ動いているでしょうか。
ボタンの中身をアイコンに変えたり、CSS 変えたりカスタマイズ色々出来ると思います。
誰かの参考になれば幸いです。
参考にさせていただいたサイトはこちら。Scroll to Top - React & Gatsby