ECサイトのTOPページで、女性と男性でビジュアルを切り替えたいとお話がありました。デザインにはそのためのボタンがドーンと配置されています。
ボタンでメインビジュアルを差し替えると言う、そんなは要件はありますか?
メニューで女性ページ男性ページに飛ばすのではなくですか?
はい。TOPページだけの専用のボタンで切り替えます。
犬と猫とか、白と黒とかで切り替える、みたいな感じ。
説明が難しいのでサンプルをご確認ください。
めずらしいなと思いつつ、出番はなさそうなので忘れ去られる前に、せっかく実装したので保管しようと思いました。
【共有】ソースコード
作成のサンプルイメージです。
Cookieを採用していて、ジェンダー切り替えをするとページをリロードしても選択ジェンダーが担保されて、再表示されます。

要件は以下です。
- 初期表示はWOMENを表示
- WOMEN/MENボタンを押したら表示が切り替わる
- ページを再表示しても選択していたボタンのジェンダーを担保していたい(Cookie)
- 切り替えたい所 1:swiperスライダー
- 切り替えたい所 2:swiper下のバナー
ジェンダー切り替えボタン
https://astrowave.jp/amnesia_record/gender_cookie.php
健忘録リスト
swiper
<!-- Swiper CSS -->
<link rel="stylesheet" href="https://unpkg.com/swiper/swiper-bundle.min.css">
<!-- Swiper JS -->
<script src="https://unpkg.com/swiper/swiper-bundle.min.js"></script>読みこませるのを忘れずに。
html
<div class="l_body__main">
<div class="wp_box">
<h3 class="p-top-onebanner__title">ボタン</h3>
<!-- gender -->
<ul class="gender">
<li><a href="#" class="gender-btn active" data-gender="women"><span>WOMEN</span></a></li>
<li><a href="#" class="gender-btn" data-gender="men"><span>MEN</span></a></li>
</ul>
<h3 class="p-top-onebanner__title">スライダー</h3>
<!-- swiper -->
<div class="p-top-hero__slider swiper c-slider-hero js-slider-hero2">
<div class="swiper-wrapper">
<!-- 各スライド -->
<div class="swiper-slide">
<div class="gender-switch-wrapper">
<!-- スライドコンテンツ -->
<div class="gender-content gender-women is-active">
<div class="c-slider-hero__image">
<picture>
<source srcset="./img/image_fx_1_women.jpg" media="(max-width: 767px)">
<img src="./img/image_fx_1_women.jpg" alt="">
</picture>
</div>
<div class="c-slider-hero__content">
<a class="c-link-parent" href="/amnesia_record/gender_cookie.php">
<h2 class="c-slider-hero__title u-font-en-h1">WOMENS COLLECTION</h2>
<div class="c-slider-hero__button">
<span class="c-link-parent__button">もっと見る</span>
</div>
</a>
</div>
</div>
<div class="gender-content gender-men">
<div class="c-slider-hero__image">
<picture>
<source srcset="./img/image_fx_1_men2.jpg" media="(max-width: 767px)">
<img src="./img/image_fx_1_men2.jpg" alt="">
</picture>
</div>
<div class="c-slider-hero__content">
<a class="c-link-parent" href="/amnesia_record/gender_cookie.php">
<h2 class="c-slider-hero__title u-font-en-h1">MENS COLLECTION</h2>
<div class="c-slider-hero__button">
<span class="c-link-parent__button">もっと見る</span>
</div>
</a>
</div>
</div>
</div>
</div>
<!-- 各スライド -->
<div class="swiper-slide">
<div class="gender-switch-wrapper">
<!-- スライドコンテンツ -->
<div class="gender-content gender-women is-active">
<div class="c-slider-hero__image">
<picture>
<source srcset="./img/image_fx_1_women2.jpg" media="(max-width: 767px)">
<img src="./img/image_fx_1_women2.jpg" alt="">
</picture>
</div>
<div class="c-slider-hero__content">
<a class="c-link-parent" href="/amnesia_record/gender_cookie.php">
<h2 class="c-slider-hero__title u-font-en-h1">WOMENS COLLECTION</h2>
<div class="c-slider-hero__button">
<span class="c-link-parent__button">もっと見る</span>
</div>
</a>
</div>
</div>
<div class="gender-content gender-men">
<div class="c-slider-hero__image">
<picture>
<source srcset="./img/image_fx_1_men.jpg" media="(max-width: 767px)">
<img src="./img/image_fx_1_men.jpg" alt="">
</picture>
</div>
<div class="c-slider-hero__content">
<a class="c-link-parent" href="/amnesia_record/gender_cookie.php">
<h2 class="c-slider-hero__title u-font-en-h1">MENS COLLECTION</h2>
<div class="c-slider-hero__button">
<span class="c-link-parent__button">もっと見る</span>
</div>
</a>
</div>
</div>
</div>
</div>
</div>
<!-- ページネーション -->
<div class="c-slider-hero__pagination c-slider-hero__pagination--white js-slider-pagination"></div>
<!-- ナビゲーションボタン(オプション) -->
<div class="c-slider-hero__arrow c-slider-hero__arrow--prev js-slider-prev"></div>
<div class="c-slider-hero__arrow c-slider-hero__arrow--next js-slider-next"></div>
</div>
<h3 class="p-top-onebanner__title">バナー</h3>
<!-- バナー -->
<div class="gender-switch-wrapper p-top-onebanner__image">
<div class="gender-content gender-women is-active" style="opacity: 1; visibility: visible; pointer-events: auto;">
<!-- WOMEN用の内容 -->
<a href="/amnesia_record/gender_cookie.php">
<picture>
<source srcset="./img/image_fx_1_women.jpg" media="(max-width: 767px)">
<img src="./img/image_fx_1_women.jpg" alt="">
</picture>
<div class="p-top-onebanner__content">
<h3 class="p-top-onebanner__subtitle">
<p class=" typesquare_option">WOMENS ITEMS</p></h3><div class="p-top-onebanner__button">
<span class="c-link">
もっと見る</span>
</div>
</div>
</a>
</div>
<div class="gender-content gender-men" style="opacity: 0; visibility: hidden; pointer-events: none;">
<!-- MEN用の内容 -->
<a href="/amnesia_record/gender_cookie.php">
<picture>
<source srcset="./img/image_fx_1_men2.jpg" media="(max-width: 767px)">
<img src="./img/image_fx_1_men2.jpg" alt="">
</picture>
<div class="p-top-onebanner__content">
<h3 class="p-top-onebanner__subtitle">
<p class=" typesquare_option">MENS ITEMS</p></h3><div class="p-top-onebanner__button">
<span class="c-link">
もっと見る</span>
</div>
</div>
</a>
</div>
</div>
</div>
</div>ボタンとswiperとバナーが配置されます。
css
cssがとても長いので、
このページのスクロール量が大変になるので省略です。
>>サンプルページの750行目より確認ください。heroSlider_readable.jsファイル(swiper用)
// heroSlider_readable.js
// 可読化+ページネーションアニメーション付き
let paginationAnimationId;
function animatePaginationSmooth(activeBullet, duration = 7000) {
if (!activeBullet) return;
let start = null;
if (paginationAnimationId) {
cancelAnimationFrame(paginationAnimationId);
}
function step(timestamp) {
if (!start) start = timestamp;
const elapsed = timestamp - start;
const progress = Math.min((elapsed / duration) * 100, 100);
activeBullet.style.background = `conic-gradient(#FFF 0%, #FFF ${progress}%, transparent ${progress}%, transparent 100%)`;
if (elapsed < duration) {
paginationAnimationId = requestAnimationFrame(step);
} else {
activeBullet.style.background = `conic-gradient(#FFF 0%, #FFF 100%, transparent 100%, transparent 100%)`;
}
}
paginationAnimationId = requestAnimationFrame(step);
}
function heroSliderWithPaginationAnimation() {
// Swiperライブラリが利用可能かチェック
if (typeof Swiper === 'undefined') {
console.log('Swiper library not loaded');
return;
}
const heroSliders = document.querySelectorAll('.js-slider-hero2'); // 必要に応じてクラス名を調整
// heroSlidersが存在し、forEachが利用可能かチェック
if (!heroSliders || heroSliders.length === 0) {
console.log('heroSliders not found');
return;
}
// forEachの代わりにforループを使用(より安全)
for (let i = 0; i < heroSliders.length; i++) {
const sliderWrapper = heroSliders[i];
// sliderWrapper自体がスライダーコンテナなので、直接使用
const slider = sliderWrapper;
const slides = slider ? slider.querySelectorAll('.swiper-slide') : [];
const pagination = sliderWrapper.querySelector('.js-slider-pagination');
const prev = sliderWrapper.querySelector('.js-slider-prev');
const next = sliderWrapper.querySelector('.js-slider-next');
// 必要な要素が存在しない場合はスキップ
if (!slider || !slides || slides.length === 0) {
console.log('Required slider elements not found', {
slider: !!slider,
slides: slides ? slides.length : 0,
pagination: !!pagination,
prev: !!prev,
next: !!next
});
continue;
}
console.log('Initializing Swiper with:', {
slides: slides.length,
pagination: !!pagination,
prev: !!prev,
next: !!next
});
if (slides.length <= 1) {
if (prev) prev.classList.add('is-hidden');
if (next) next.classList.add('is-hidden');
continue;
}
const autoplayDelay = 4000;
const swiper = new Swiper(slider, {
speed: 900,
slidesPerView: 1,
loop: true,
threshold: 10,
pagination: {
el: pagination,
clickable: true
},
navigation: {
nextEl: next,
prevEl: prev
},
autoplay: {
delay: autoplayDelay,
disableOnInteraction: false,
waitForTransition: true
},
simulateTouch: true,
touchRatio: 1,
grabCursor: true
});
console.log('Swiper initialized successfully:', swiper);
function startPaginationAnimation() {
document.querySelectorAll('.swiper-pagination-bullet').forEach(bullet => {
bullet.style.background = '';
});
const activeBullet = pagination.querySelector('.swiper-pagination-bullet-active');
animatePaginationSmooth(activeBullet, autoplayDelay);
}
// スライド切り替え開始時にタイトルをフェードアウト
swiper.on('slideChangeTransitionStart', function() {
slider.classList.add('is-transition');
});
// スライド切り替え完了時にタイトルをふわっと表示
swiper.on('slideChangeTransitionEnd', function() {
setTimeout(function() {
slider.classList.remove('is-transition');
}, 0);
});
swiper.on('autoplay', startPaginationAnimation);
swiper.on('slideChange', startPaginationAnimation);
swiper.on('paginationUpdate', startPaginationAnimation);
startPaginationAnimation();
// 初期表示時に最初のスライドのタイトルをふわっと表示
slider.classList.add('is-transition');
// 500ms後に最初のスライドのタイトルを表示
setTimeout(function() {
slider.classList.remove('is-transition');
}, 500);
}
}
window.addEventListener('DOMContentLoaded', function() {
console.log('DOMContentLoaded event fired');
heroSliderWithPaginationAnimation();
});好きなように変えてください。
javascript
ジェンダー切り替え動作と、Cookieの設定のスクリプトです。
<script>
// Cookie操作のヘルパー関数
function setCookie(name, value, days) {
var expires = "";
if (days) {
var date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toUTCString();
}
document.cookie = name + "=" + value + expires + "; path=/";
}
function getCookie(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for(var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
}
return null;
}
// ジェンダー切り替えの状態を保存する関数
function saveGenderState(gender) {
setCookie('selected_gender', gender, 30); // 30日間保持
}
// Cookieをクリアする関数
function clearAllCookies() {
// 特定のCookieを削除
setCookie('selected_gender', '', -1); // 過去の日付で削除
setCookie('number', '', -1); // 過去の日付で削除
// ページをリロードしてデフォルト状態に戻す
location.reload();
}
// ジェンダー切り替えの状態を復元する関数
function restoreGenderState() {
var savedGender = getCookie('selected_gender');
if (savedGender && (savedGender === 'women' || savedGender === 'men')) {
return savedGender;
}
return 'women'; // デフォルトはwomen
}
// ジェンダー切り替えの表示を更新する関数
function updateGenderDisplay(gender) {
// ボタンの状態を更新
var genderBtns = document.querySelectorAll('.gender-btn');
genderBtns.forEach(function(btn) {
if (btn.getAttribute('data-gender') === gender) {
btn.classList.add('active');
} else {
btn.classList.remove('active');
}
});
// コンテンツの表示を更新(ページ全体のすべてのgender-switch-wrapperを対象)
document.querySelectorAll('.gender-switch-wrapper').forEach(function(wrapper) {
var all = wrapper.querySelectorAll('.gender-content');
var target = wrapper.querySelector('.gender-content.gender-' + gender);
if (target && all.length > 0) {
fadeSwitch(target, all);
}
});
// デバッグ用ログ(開発時のみ)
if (window.location.hostname === 'localhost' || window.location.hostname.includes('dev')) {
console.log('Gender updated to:', gender, 'Found wrappers:', document.querySelectorAll('.gender-switch-wrapper').length);
}
}
// ジェンダー切り替え
function fadeSwitch(target, all) {
if (!target || !all || all.length === 0) return;
all.forEach(function(el) {
if (el === target) {
el.classList.add('is-active');
el.style.opacity = '1';
el.style.visibility = 'visible';
el.style.pointerEvents = 'auto';
} else {
el.classList.remove('is-active');
el.style.opacity = '0';
el.style.visibility = 'hidden';
el.style.pointerEvents = 'none';
}
});
}
document.addEventListener('DOMContentLoaded', function() {
// URLパラメータを優先し、なければCookieから復元
var urlParams = new URLSearchParams(window.location.search);
var urlGender = urlParams.get('gender');
var currentGender;
if (urlGender && (urlGender === 'women' || urlGender === 'men')) {
// URLパラメータがある場合はそれを優先
currentGender = urlGender;
// URLパラメータの状態もCookieに保存
saveGenderState(currentGender);
} else {
// URLパラメータがない場合はCookieから復元
currentGender = restoreGenderState();
}
// ページ全体のgender表示を更新
updateGenderDisplay(currentGender);
// ジェンダーボタンのクリックイベント
var genderBtns = document.querySelectorAll('.gender-btn');
genderBtns.forEach(function(btn) {
btn.addEventListener('click', function(e) {
e.preventDefault();
var gender = this.getAttribute('data-gender');
// ページ全体の表示を更新
updateGenderDisplay(gender);
// 状態をCookieに保存
saveGenderState(gender);
});
});
// Cookieクリアボタンのクリックイベント
var clearCookieBtn = document.getElementById('clearCookieBtn');
if (clearCookieBtn) {
clearCookieBtn.addEventListener('click', function(e) {
e.preventDefault();
// 確認ダイアログを表示
if (confirm('保存された設定をクリアしますか?\nこの操作は元に戻せません。')) {
clearAllCookies();
}
});
}
});
// ページ読み込み完了後に再度表示を更新(他のセクションの読み込み完了を待つ)
window.addEventListener('load', function() {
var currentGender = restoreGenderState();
updateGenderDisplay(currentGender);
});
</script>ボタンを押したらWOMEN/MENの要素へ交互にis-activeのクラスが差し代わるようですね。
はい。Cookieの保存は30日間にしています。
オプション
以下のようにURLに?パラメータを追加でアクセスすると、指定したジェンダーで表示されるようにしてます。
WOMEN表示: gender_cookie.php?gender=women
MEN表示: gender_cookie.php?gender=men
// URLパラメータを優先し、なければCookieから復元
var urlParams = new URLSearchParams(window.location.search);
var urlGender = urlParams.get('gender');
if (urlGender && (urlGender === 'women' || urlGender === 'men')) {
// URLパラメータがある場合はそれを優先
currentGender = urlGender;
// URLパラメータの状態もCookieに保存
saveGenderState(currentGender);
} else {
// URLパラメータがない場合はCookieから復元
currentGender = restoreGenderState();
}
MENの表示になるURL
https://astrowave.jp/amnesia_record/gender_cookie.php?gender=men
以上になります。
【AI】イラストを描いてもらった
今回の記事のキャッチ画像で使わせてもらいます「Google ImageFX」で作成した画像です。誰でもgoogleアカウントでログインして使えます。
この記事にピッタリなイラストのための考えたリクエストは、
「遺跡の祭壇でクリスタルに触れた時、眩しい光と共に目の前に、過去と未来の出来事が無限スクロールするように流れる様に驚く探検家。スクロール映像に寄りで、探検家は上半身の画角。探検家を女性に。」です。

トゥームレイダーみたいなの好きです。
星間旅路のメロディ
「宇宙の静けさに包まれながら、漂流する過去の音楽を捜し求め、銀河の奥底でその旋律に耳を傾ける。」
「この電波はどこの星からきたのだろうか。」
ロケットに乗って、重力ターンするのだ!




「【cookie】ジェンダー切り替えボタン」への1件のフィードバック
コメントは受け付けていません。