Webサイトの第一印象を決める「ヒーローバナー」。
背景画像とキャッチコピー(見出し+説明文)をセットでフェード切り替えするファーストビュー
モダンでプロフェッショナルな演出を、HTML・CSS・JavaScript(jQueryなし)で
実装する方法を記事にしました。
完成イメージ
- 背景画像がクロスフェードで切り替わる
- それに合わせてテキスト(見出し+サブテキスト)もふわっと表示
- 黒のオーバーレイで文字の可読性も確保
- JavaScriptで制御
実際に書いたコードを記載しました。
よかったら参考にしてください。
HTML構成
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>タイトルチェンジ</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<section class="fv-content">
<div class="contents-wrapper">
<div class="background-container">
<img class="bg-img visible" src="imgs/img-1.JPG" alt="">
<img class="bg-img" src="imgs/img-1.JPG" alt="">
<img class="bg-img" src="imgs/img-1.JPG" alt="">
<img class="bg-img" src="imgs/img-1.JPG" alt="">
<div class="overlay"></div>
</div>
<div class="fv-textbox">
<div class="text-block">
<h2 class="fv-headline"></h2>
<p></p>
</div>
</div>
</div>
</section>
<main>
<section class="space-container">メインコンテンツ</section>
<section class="space-container">メインコンテンツ</section>
<section class="space-container">メインコンテンツ</section>
</main>
<script src="main.js"></script>
</body>
</html>
CSSスタイル
@charset "utf-8";
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.contents-wrapper{
width: calc(100% - 100px);
max-width: 1500px;
margin: 0 auto;
padding: 0 clamp(20px, 2.6596vw + -0.43px, 40px);
}
@media screen and (max-width:767px) {
.contents-wrapper{
width: calc(100% - 60px);
}
}
.fv-content {
position: relative;
width: 100%;
height: 100vh;
overflow: hidden;
}
@media screen and (max-width:767px) {
.fv-content {
height: 60vh;
}
}
.background-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
z-index: -1;
}
.bg-img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
opacity: 0;
transition: opacity 2s ease;
z-index: 0;
}
.bg-img.visible {
opacity: 1;
z-index: 1;
}
.overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
z-index: 2;
pointer-events: none;
}
.fv-textbox {
display: flex;
align-items: center;
height: 100vh;
z-index: 10;
margin-left: clamp(40px, 5.4645vw + -1.97px, 80px);
}
@media screen and (max-width:767px) {
.fv-textbox {
justify-content: center;
height: 50vh;
margin-left: 0;
}
}
.fv-textbox .fv-headline {
color: #fff;
font-weight: bold;
font-size: clamp(60px, 8.1967vw + -2.95px, 120px);
margin-bottom: 1rem;
text-shadow: 3px 3px 3px rgba(0, 0, 0, 0.7);
line-height: 1.1;
}
@media screen and (max-width:767px) {
.fv-textbox .fv-headline {
font-size: clamp(40px, 4.2827vw + 27.15px, 60px);
}
}
.fv-textbox p {
color: #fff;
font-size: clamp(14px, 2.1858vw + -2.79px, 30px);
text-shadow: 3px 3px 3px rgba(0, 0, 0, 0.7);
line-height: 1.2;
}
.fv-headline,
.fv-textbox p {
opacity: 0;
transition: opacity 2s .5s ease;
}
.fv-headline.fade-in,
.fv-textbox p.fade-in {
opacity: 1;
}
.fv-headline.fade-out,
.fv-textbox p.fade-out {
opacity: 0;
}
.space-container {
height: 1000px;
padding: 100px 0;
}
JavaScriptコード
const texts = [
{
headline: "IMMERSIVE<br>DIGITAL<br>EXPERIENCE",
description: "没入感のあるデジタル体験を設計するエクスペリエンス戦略",
background: "imgs/img-1.JPG"
},
{
headline: "AGILE<br>VISUAL<br>PROTOTYPING",
description: "スピードと柔軟性を兼ね備えたビジュアル開発の新常識",
background: "imgs/img-2.JPG"
},
{
headline: "SUSTAINABLE<br>BRAND<br>INNOVATION",
description: "持続可能な成長を実現するブランドイノベーション戦略",
background: "imgs/img-3.JPG"
},
{
headline: "DATA-DRIVEN<br>USER<br>INSIGHTS",
description: "ユーザーデータを軸にした確かな課題発見と改善提案",
background: "imgs/img-4.JPG"
}
];
const config = {
fadeInTime: 2000,
visibleTime: 4000,
fadeOutTime: 2000
};
let txtIndex = 0;
const headlineElement = document.querySelector(".fv-headline");
const descriptionElement = document.querySelector(".fv-textbox p");
const bgImages = document.querySelectorAll(".bg-img");
function fadeIn(el) {
el.classList.add("fade-in");
el.classList.remove("fade-out");
}
function fadeOut(el) {
el.classList.remove("fade-in");
el.classList.add("fade-out");
}
function switchBackgroundImage(newSrc, callback) {
const[imgA, imgB] = bgImages;
const visible = imgA.classList.contains("visible") ? imgA : imgB;
const hidden = visible === imgA ? imgB : imgA;
hidden.onload = () => {
hidden.classList.add("visible");
visible.classList.remove("visible");
setTimeout(()=> {
if (callback) callback();
}, 300);
};
hidden.src = newSrc;
}
function showNextSet() {
const current = texts[txtIndex];
switchBackgroundImage(current.background, () => {
headlineElement.innerHTML = current.headline;
descriptionElement.textContent = current.description;
fadeIn(headlineElement);
fadeIn(descriptionElement);
setTimeout(() => {
fadeOut(headlineElement);
fadeOut(descriptionElement);
}, config.visibleTime);
setTimeout(() => {
txtIndex = (txtIndex + 1) % texts.length;
showNextSet();
}, config.visibleTime +config.fadeOutTime);
});
}
window,addEventListener("DOMContentLoaded", () => {
showNextSet();
});
これからWebサイトを始めたい方へ!
今回のようなオリジナルのWebサイトを作って公開するには、レンタルサーバーの契約が必要です。
まだサーバーを持っていない方には、国内シェアNo.1の【エックスサーバー】がおすすめ!
✔ 表示速度が速い
✔ サポートも充実
✔ 初心者でもWordPressが簡単に始められる
\ 今ならドメイン永久無料&初期費用0円キャンペーン中! /
👉 エックスサーバーに新規登録する(公式サイト)
※アフィリエイトリンクをここに挿入
まとめ
この構成なら、背景画像とテキストの完全同期フェード切り替えがスムーズに実現できます。
ポートフォリオや企業サイトのトップページで、インパクトあるファーストビューを
作りたい方におすすめです!
ご質問やカスタマイズ希望があれば、お気軽にコメントしてください!


コメント