矢印を押すと横に移動する。
主に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)にします。矢印の背景色を指定します。
rgbaはそれぞれ、Red:赤、Green:緑、Blue:青、Alpha:透明度を意味します。
rgba("赤","緑","青","透明度")
「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の実装が必要です。
Webデザインを学びたい
HTMLやCSSなどはマークアップ言語と呼ばれてプログラミングと異なります。
プログラミングは指示通りに処理がされると完成ですが、
フロントエンドは、Webデザインも重要になります。
デザインの幅を広げたいけれど、コーディングに悩んでいませんか?
美しいデザインを実現するためには、常に新しいスキルを身につけることが重要です。
Udemyは動画でHTMLやCSSの基礎から最新のデザインテクニックを実践形式で学べます。
購入した講座は再生・停止・スキップなどが可能なオンデマンド形式なので、
講座中に独自でアレンジして試行錯誤ができます。
HTML/CSS/JavaScriptに興味がある人はUdemy学習を取り入れましょう。
数多くある講座の中から特におすすめな講座を3つ紹介します。
夏のビックセール開催中(8月29日まで)
対象のコースが1300円から(最大95%OFF)
HTML、CSS、JavaScriptの学習ができて、フレームワークの扱い方、セキュリティー、その他プログラミング言語を学ぶために必要な考え方など幅広く情報を網羅している。
WEBシステムの仕組みと挙動、システム構築などWEBシステムの基礎の学習が可能。
JSとCSSに焦点を当てた講座。基礎レベルから実務レベルまで網羅していて、最終的にアニメーションやコードの最適化、安定化について学ぶ。
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関数を使います。
アロー関数は、矢印( =>)を利用して関数のINPUTとOUTPUTを表現します。
function式よりもコードの短縮化ができますが、制限がありすべての場面で有効ではありません。
構文は以下の通りです。
要素.addEventListener(種類, () => {
//処理
});
変数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>