矢印を押すと横に移動する。
主にECサイトにて、商品販売を目的しているときに、
閲覧履歴から商品を紹介する、値段や性能の比較をするウェブデザインがあります。
横スクロールするデザインは、特にレスポンシブルデザインを主とする
スマホでタッチ操作をするため非常に相性が良いです。
しかし、PCは縦スクロールがメインで、横スクロールになじみがないユーザーもいます。
さらに、横スクロールは、マウスやトラックボールでは基本的に非対応な操作で、
トラックパッドが必要になります。
ノートパソコンではトラックパッドが標準搭載されている機器も多いですが、
トラックパッドがないPCを使っているユーザーも多いです。
本記事では、マウスやトラックボールでも横スライドをできるようにCSSで矢印(くの字)をデザインして、JavaScriptで駆動できるコードを紹介します。
CSSで矢印
矢印のボタンで横スクロールするには、CSSを使用します。
ウェブデザインで矢印を作成するメリットは以下の通りです。
矢印を押すことで、横にスライドできる機能は
閲覧しているユーザーにも簡単に示唆することができます。
何枚もの画像を配置する場合、横に配置すると画像が小さくなってしまいます。
一方で、縦に並べると長くなってしまい非常に見にくいデザインになります。
そこで、画面外に配置して矢印操作(横スライド)で画面を作成すると、
デザイン性が向上します。
HTML
<div class="Container">
<div class="Box-Container">
<div class="Box"></div>
<div class="Box"></div>
<div class="Box"></div>
<div class="Box"></div>
<div class="Box"></div>
<div class="Box"></div>
<!-- 必要な数の.Box要素を追加 -->
</div>
<div class="Arrow left"><</div>
<div class="Arrow right">></div>
</div>
解説
.Boxクラスは、.Box-Container内に配置されていて、横スライドに関与します。
また、左右の矢印は.Arrowというクラスが付けられており、
.Arrow leftと.Arrow rightでそれぞれ左矢印と右矢印を表しています。
CSS
.Container {
position: relative;
width: 100%;
overflow: hidden;
}
.Box-Container {
display: flex;
width: fit-content;
transition: transform 0.3s ease;
transform: translateX(0);
}
.Box {
flex-shrink: 0;
width: 300px;
height: 200px;
margin-right: 10px;
border-radius: 10px;
background-color: #ccc;
}
.Arrow {
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 30px;
height: 30px;
background-color: rgba(0, 0, 0, 0.3);
color: #fff;
font-size: 20px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.Arrow.left {
left: 0;
}
.Arrow.right {
right: 0;
}
.Hide {
display: none;
}
解説
class「.Container」は、スライドショー全体のコンテナを指定します。
「position」をrelativeにします。内部の要素に対して位置指定を行います。
「width」を100%にします。親要素に対して幅いっぱいに広がることを意味します。
「overflow」を hiddenにします。コンテンツがコンテナからはみ出さないように制御します。
class「.Box-Container」は、ボックス要素のコンテナを指定します。
「display」を flexにします。内部のボックス要素が横に並ぶようにします。
「width」を fit-contentにします。内部のボックス要素の合計幅に合わせてコンテナの幅を自動調整します。
「transition」をtransform 0.3s easeにします。スライド時のアニメーション効果を指定します。
「transform」をtranslateX(0)にします。初期状態でボックスがスライドされていないことを示します。
class「.Box」は、各ボックス要素のスタイルを指定します。
「flex-shrink」を0にします。ボックスが収縮しないように指定します。
「width」「height」をそれぞれ300px、200pxにします。各ボックス要素の固定サイズを指定します。
「margin-right」を10pxにします。ボックス要素の間隔を指定します。
「border-radius」を10pxにします。ボックス要素の角を丸くするための指定です。
「background-color」を#cccにします。ボックスの背景色を指定します。
class「.Arrow」は矢印要素のスタイルを指定します。
「position」 をabsoluteにします。親要素に対して位置指定を行います。
「top」を 50%、「transform」を translateY(-50%)にします。矢印要素を垂直方向に中央に配置するための指定です。
「width」を 30px、「height」を30pxにします。矢印要素のサイズを指定します。
「background-color」を rgba(0, 0, 0, 0.3)にします。矢印の背景色を指定します。
「color」を #fffにします。矢印のテキスト色を指定します。
「font-size」を20pxにします。矢印のフォントサイズを指定します。
「display」をflex、「align-items」をcenter、「justify-content」をcenterにします。矢印のテキストを中央に配置するための指定です。
「cursor」をpointerにします。矢印要素にカーソルが重なった時にポインター形状を表示する指定です。
class「.Arrow.left」と「.Arrow.right」は、左矢印と右矢印の位置を指定します。
.Arrow.leftは左側に配置され、.Arrow.rightは右側に配置されます。
class「.Hide」は、非表示にするためのクラスです。
「display」をnoneにして要素が非表示になります。
HTMLとCSSを実装した様子がこちらになります。
示したように、矢印を押しても横にスライドしません。
横のスライドには、JavaScriptの実装が必要です。
UdemyでWebデザインを学習
Udemyは、オンデマンド式の学習講座です。
趣味から実務まで使えるおすすめの講座を紹介します。
ビックセール開催中(12月19日まで)
対象のコースが1500円から(最大95%OFF)
- ちゃんと学ぶ、WordPress テーマ開発講座
WordPressの自作テーマを作成してWordPressの仕組み理解。
WordPressで高度なカスタマイズをしたい人におすすめ。
- 【世界で70万人が受講】Web Developer Bootcamp 2023(日本語版)
フロントエンド言語でフレームワークの扱い方、セキュリティーを学習。
Web開発を学びたい初心者から経験者までにおすすめ。
- 【PHP, MYSQL, Apache】ガチで学びたい人のためのWEB開発の基礎(バックエンド編)
Webシステムの仕組みと挙動、システム構築などを学習。
サーバーに関わる知識を付けたい人におすすめ。
- 【2023年最新】【JavaScript&CSS】ガチで学びたい人のためのWEB開発実践入門(フロントエンド編)
基礎レベルから実務レベルまで網羅していて、JSとCSSに焦点を当てた講座。
Webデザインをしたい人におすすめ。
JavaScript
const container = document.querySelector('.Container');
const boxContainer = document.querySelector('.Box-Container');
const leftArrow = document.querySelector('.Arrow.left');
const rightArrow = document.querySelector('.Arrow.right');
const scrollAmount = 200; // 3回で最大値まで行く程度の数値
leftArrow.addEventListener('click', () => {
const containerWidth = container.offsetWidth;
const maxScrollAmount = boxContainer.offsetWidth - containerWidth;
const currentScrollAmount = Math.abs(parseInt(boxContainer.style.transform.split('(')[1])) || 0;
const newScrollAmount = Math.max(currentScrollAmount - scrollAmount, 0);
boxContainer.style.transform = `translateX(-${newScrollAmount}px)`;
updateArrowVisibility(newScrollAmount, maxScrollAmount);
});
rightArrow.addEventListener('click', () => {
const containerWidth = container.offsetWidth;
const maxScrollAmount = boxContainer.offsetWidth - containerWidth;
const currentScrollAmount = Math.abs(parseInt(boxContainer.style.transform.split('(')[1])) || 0;
const newScrollAmount = Math.min(currentScrollAmount + scrollAmount, maxScrollAmount);
boxContainer.style.transform = `translateX(-${newScrollAmount}px)`;
updateArrowVisibility(newScrollAmount, maxScrollAmount);
});
function updateArrowVisibility(scrollAmount, maxScrollAmount) {
if (scrollAmount === 0) {
leftArrow.classList.add('Hide');
} else {
leftArrow.classList.remove('Hide');
}
if (scrollAmount === maxScrollAmount) {
rightArrow.classList.add('Hide');
} else {
rightArrow.classList.remove('Hide');
}
}
解説
初めに、変数を定義します。
変数「container」・「boxContainer」・「leftArrow」・「rightArrow」にそれぞれクラス要素を取得します。
取得には、「document.querySelector(‘要素’)」を使用します。
変数「scrollAmount」はスクロール量です。端から端まで何回で進むか各自で調整してください。
const container = document.querySelector('.Container');
const boxContainer = document.querySelector('.Box-Container');
const leftArrow = document.querySelector('.Arrow.left');
const rightArrow = document.querySelector('.Arrow.right');
const scrollAmount = 200; // 3回で最大値まで行く程度の数値
leftArrowのクリックイベントの処理を追加します。
ここでは、Arrow関数を使います。
変数containerWidthにcontainer要素の幅を代入します。
変数maxScrollAmountに、スクロール可能な要素であるboxContainerの幅から、表示領域であるcontainerの幅を引いた値を代入します。
変数currentScrollAmountboxは、Container要素の現在のスクロール量を取得します。
boxContainer.style.transformは、要素のスタイルプロパティtransformの値を表します。この場合、translateX()という文字列が設定されています。※()内は、pxで表現されます。
split(‘(‘)[1])を使用して、translateX()の()部分を取得し、parseIntで整数値に変換します。
Math.absを使用して、取得したスクロール量の絶対値を計算します。
また、スクロール量が取得できない場合は、0を代入します。
変数newScrollAmountは、現在のスクロール量から指定されたscrollAmountを引いた値と0のうち、大きい値を取得します。これにより、新しいスクロール量が0未満にならないように制限されます。
「boxContainer.style.transform」で、boxContainer要素のスタイルプロパティtransformを更新し、新しいスクロール量を反映させます。translateX関数を使用して、水平方向に指定した負のピクセル数だけ要素を移動させます。
例えば、変数「newScrollAmount」が100pxであれば、カッコ内を「-${newScrollAmount}」とすることで-100px。つまり、左に100px移動することになります。
updateArrowVisibility関数を呼び出します。この関数はスクロール量と最大スクロール量を受け取り、左右の矢印ボタンの表示/非表示を切り替えるものです。
同様の操作をrightArrowのクリックイベントの処理に適したようにコードを追加します。
leftArrow.addEventListener('click', () => {
const containerWidth = container.offsetWidth;
const maxScrollAmount = boxContainer.offsetWidth - containerWidth;
const currentScrollAmount = Math.abs(parseInt(boxContainer.style.transform.split('(')[1])) || 0;
const newScrollAmount = Math.max(currentScrollAmount - scrollAmount, 0);
boxContainer.style.transform = `translateX(-${newScrollAmount}px)`;
updateArrowVisibility(newScrollAmount, maxScrollAmount);
});
rightArrow.addEventListener('click', () => {
const containerWidth = container.offsetWidth;
const maxScrollAmount = boxContainer.offsetWidth - containerWidth;
const currentScrollAmount = Math.abs(parseInt(boxContainer.style.transform.split('(')[1])) || 0;
const newScrollAmount = Math.min(currentScrollAmount + scrollAmount, maxScrollAmount);
boxContainer.style.transform = `translateX(-${newScrollAmount}px)`;
updateArrowVisibility(newScrollAmount, maxScrollAmount);
});
functionで、updateArrowVisibility関数のにおいて、変数「scrollAmount」が0の時は、左矢印をHideクラスで非表示にします。同様に、スクロール量が最大の時は、右矢印を非表示にします。
function updateArrowVisibility(scrollAmount, maxScrollAmount) {
if (scrollAmount === 0) {
leftArrow.classList.add('Hide');
} else {
leftArrow.classList.remove('Hide');
}
if (scrollAmount === maxScrollAmount) {
rightArrow.classList.add('Hide');
} else {
rightArrow.classList.remove('Hide');
}
}
実演
以上のHTML・CSS・JavaScriptの3つを用いると、冒頭で紹介した動作ができます。
また、以下に実際の動作を確認できます。
まとめ
矢印の導入はCSSでできますが、矢印を押して動作させるには、JavaScriptが必要になります。
ウェブデザインで矢印を作成ことは、ユーザーが直感的に操作しやすくできて、デザインのバランスが整います。
また、矢印を押すことで、横にスライドできるということは閲覧しているユーザーにも簡単に示唆できます。
付録.ソースコード(一括)
本記事で扱ったソースコードをHTMLで1つで記述したものです。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.Container {
position: relative;
width: 100%;
overflow: hidden;
}
.Box-Container {
display: flex;
width: fit-content;
transition: transform 0.3s ease;
transform: translateX(0);
}
.Box {
flex-shrink: 0;
width: 300px;
height: 200px;
margin-right: 10px;
border-radius: 10px;
background-color: #ccc;
}
.Arrow {
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 30px;
height: 30px;
background-color: rgba(0, 0, 0, 0.3);
color: #fff;
font-size: 20px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.Arrow.left {
left: 0;
}
.Arrow.right {
right: 0;
}
.Hide {
display: none;
}
</style>
</head>
<body>
<div class="Container">
<div class="Box-Container">
<div class="Box"></div>
<div class="Box"></div>
<div class="Box"></div>
<div class="Box"></div>
<div class="Box"></div>
<div class="Box"></div>
<!-- 必要な数の.Box要素を追加 -->
</div>
<div class="Arrow left"><</div>
<div class="Arrow right">></div>
</div>
<script>
const container = document.querySelector('.Container');
const boxContainer = document.querySelector('.Box-Container');
const leftArrow = document.querySelector('.Arrow.left');
const rightArrow = document.querySelector('.Arrow.right');
const scrollAmount = 200; // 3回で最大値まで行く程度の数値
leftArrow.addEventListener('click', () => {
const containerWidth = container.offsetWidth;
const maxScrollAmount = boxContainer.offsetWidth - containerWidth;
const currentScrollAmount = Math.abs(parseInt(boxContainer.style.transform.split('(')[1])) || 0;
const newScrollAmount = Math.max(currentScrollAmount - scrollAmount, 0);
boxContainer.style.transform = `translateX(-${newScrollAmount}px)`;
updateArrowVisibility(newScrollAmount, maxScrollAmount);
});
rightArrow.addEventListener('click', () => {
const containerWidth = container.offsetWidth;
const maxScrollAmount = boxContainer.offsetWidth - containerWidth;
const currentScrollAmount = Math.abs(parseInt(boxContainer.style.transform.split('(')[1])) || 0;
const newScrollAmount = Math.min(currentScrollAmount + scrollAmount, maxScrollAmount);
boxContainer.style.transform = `translateX(-${newScrollAmount}px)`;
updateArrowVisibility(newScrollAmount, maxScrollAmount);
});
function updateArrowVisibility(scrollAmount, maxScrollAmount) {
if (scrollAmount === 0) {
leftArrow.classList.add('Hide');
} else {
leftArrow.classList.remove('Hide');
}
if (scrollAmount === maxScrollAmount) {
rightArrow.classList.add('Hide');
} else {
rightArrow.classList.remove('Hide');
}
}
</script>
</body>
</html>