しまむら風:右下“うさぎリンク” — 吹き出し付きでスライド出現する常駐ボタン
ページ右下に表示されるうさぎのキャラクターリンクを再現したデザインUIです。 右からヌルッとスライド出現し、ヘッダー・フッターが画面内にある時は自動で非表示になります。 吹き出しには「いますぐCHECK!」とメッセージが入り、クリックで新しいタブで指定URLへ遷移します。 うさぎの画像は自由に変更できます。お好きなキャラクター画像(背景透過PNG推奨)に差し替えてください。
コードについて
本記事のコードは AI(ChatGPT)による生成をベースに作成・調整しています。ご利用の環境でテストの上ご使用ください。
免責 本コードの利用に伴う不具合・損害について、当サイトは責任を負いません。自己責任にてご利用ください。
免責 本コードの利用に伴う不具合・損害について、当サイトは責任を負いません。自己責任にてご利用ください。
デモ
コードをコピーして使おう!
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<!-- ビューポート設定:スマホでのズームや横幅を適正化 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<!-- タブや検索結果に表示されるページタイトル -->
<title>しまむら風:右下うさぎリンク</title>
<style>
/* ===============================
右下固定「うさぎリンク」CSS
セクション #rabbit-link-section 内に限定したスタイルです。
=============================== */
/* 右下常駐ボックス全体(吹き出し+うさぎ) */
#rabbit-link-section .rabbit-link{
position: fixed; /* ビューポート基準で固定配置(スクロールに追従) */
right: 16px; /* 右端から16pxのオフセット */
bottom: 16px; /* 下端から16pxのオフセット */
z-index: 9999; /* ほぼ最前面に(他要素より前へ) */
display: flex; /* 吹き出しと画像を横並びレイアウト */
align-items: flex-end; /* 子要素の垂直方向を下端で揃える */
gap: 12px; /* 吹き出しと画像の間隔を12pxにする */
transform: translateX(140%); /* 初期表示は画面外(右)へ退避しておく */
opacity: 0; /* 初期は不可視(フェードイン用) */
transition: /* 表示切替のアニメーションを定義 */
transform .6s cubic-bezier(.22,.61,.36,1), /* 右から滑らかにスライドイン */
opacity .6s ease; /* 透明度の変化も同時に行う */
pointer-events: none; /* 非表示中はクリック等のイベントを受け付けない */
}
/* 表示中:ヘッダー/フッターに被っていない時(後述JSで制御) */
#rabbit-link-section .rabbit-link.is-ready:not([data-hide="1"]){
transform: translateX(0); /* 退避を解除=画面内へスライドイン */
opacity: 1; /* 不透明にして見せる */
pointer-events: auto; /* ユーザー操作を受け付ける */
}
/* 非表示中:ヘッダー/フッターに被った時(交差検知で隠す) */
#rabbit-link-section .rabbit-link[data-hide="1"]{
opacity: 0; /* フェードアウトして隠す */
pointer-events: none; /* 非表示時は操作不可にする */
}
/* ===============================
吹き出し部分(画像風に太枠+角丸+右しっぽ)
=============================== */
#rabbit-link-section .bubble{
position: relative; /* 擬似要素(しっぽ)の絶対配置の基準にする */
background: #fff; /* 吹き出しの塗り:白 */
border: 3px solid #333; /* 黒に近い3pxの太い枠線で輪郭を出す */
border-radius: 16px; /* 角を16px丸めて柔らかい印象に */
color: #111; /* 本文色:濃いグレー(黒より柔らかい) */
font-weight: 700; /* 太字で視認性を上げる */
font-size: 15px; /* ベースの文字サイズ(モバイルでも読みやすい) */
line-height: 1.6; /* 行間をやや広めにして2行組でも詰まらないように */
padding: 12px 18px; /* 内側余白:上下12px, 左右18px */
box-shadow: none; /* 影は付けずフラットに(元画像の雰囲気に合わせる) */
text-align: center; /* テキストを中央揃え */
text-decoration: none; /* a要素化されても全体には下線を付けない */
}
/* 吹き出しの「黒縁+白内部」右しっぽを2層構造で作成(外側→内側の順) */
#rabbit-link-section .bubble::after{
content: ""; /* 擬似要素を生成(外側の黒縁三角) */
position: absolute; /* 親(.bubble)基準で絶対配置 */
top: 50%; /* 親の高さの中央に置く */
right: -12px; /* 親の右端から外へ12px突き出す位置 */
transform: translateY(-50%); /* 50%位置の基準を中央に補正 */
border-width: 8px; /* 三角形の大きさ(外側) */
border-style: solid; /* 三角形をborderで作る */
border-color: /* 右向き三角:左辺だけ着色し他は透明 */
transparent transparent transparent #333;
}
#rabbit-link-section .bubble::before{
content: ""; /* 擬似要素を生成(内側の白三角:中抜き表現) */
position: absolute; /* 親(.bubble)基準で絶対配置 */
top: 50%; /* 親の高さの中央に置く */
right: -9px; /* 外側三角より3px内側にして縁を作る */
transform: translateY(-50%); /* 50%位置の基準を中央に補正 */
border-width: 7px; /* 内側三角は外側よりひと回り小さく */
border-style: solid; /* 三角形をborderで作る */
border-color: /* 右向き三角:左辺だけ白で塗る */
transparent transparent transparent #fff;
z-index: 1; /* 外側(三角)より前面にして中抜きに見せる */
}
/* 吹き出しの2行目(補助テキスト) */
#rabbit-link-section .bubble small{
display: block; /* インライン要素をブロック化=確実に改行させる */
font-weight: 600; /* 1行目より少し軽めのウエイトで区別 */
color: #111; /* 文字色は本体と同じ */
margin-top: 2px; /* 1行目との間隔を2px空けて詰まり感を減らす */
}
/* “CHECK!” 部分だけ下線強調(任意のspanで対象化) */
#rabbit-link-section .bubble span{
text-decoration: underline; /* 下線を表示 */
text-decoration-thickness: 2px; /* 下線の太さを2pxに */
text-underline-offset: 2px; /* 文字と下線の距離を2px確保して読みやすく */
}
/* うさぎ画像(右側) */
#rabbit-link-section .rabbit{
width: 72px; /* 画像の幅(PC基準) */
height: 72px; /* 画像の高さ(正方形に揃える) */
object-fit: contain; /* 元画像の比率を維持して収める */
display: block; /* 画像の下に空白が出ないようブロック化 */
filter: drop-shadow(0 8px 12px rgba(0,0,0,.2)); /* うっすら影で浮かせる */
}
/* ===============================
モバイル最適化
=============================== */
@media (max-width: 480px){ /* 画面幅480px以下をモバイルとみなす */
#rabbit-link-section .rabbit{
width: 58px; /* うさぎ画像をやや小さく */
height: 58px; /* 高さも同じにして正方形維持 */
}
#rabbit-link-section .bubble{
font-size: 14px; /* 文字サイズを1段階下げる */
padding: 10px 14px; /* 余白も少し詰めて収まりを良くする */
}
#rabbit-link-section .bubble::after{
right: -10px; /* しっぽ(外側)を内側へ2px寄せてバランス調整 */
border-width: 7px; /* 三角サイズも一段小さく */
}
#rabbit-link-section .bubble::before{
right: -8px; /* しっぽ(内側)も同様に寄せる */
border-width: 6px; /* 外側より1px小さくして輪郭を残す */
}
}
/* ===============================
アニメーション無効化(ユーザー設定に配慮)
=============================== */
@media (prefers-reduced-motion: reduce){ /* 動きの少ない表示を希望する環境設定に追従 */
#rabbit-link-section .rabbit-link{
transition: none; /* すべてのトランジションを無効化 */
transform: none; /* 初期の退避も行わない=常時表示 */
opacity: 1; /* 透明度も固定で見せる */
}
}
/* ===============================
デモ用ヘッダー/フッター
(実サイトに導入する際は不要。動作確認用の背景ブロック)
=============================== */
header, footer{
height: 320px; /* ダミー領域の高さ */
background:#111827; /* 濃紺の背景色(視認性の高い色) */
color:#fff; /* 文字は白でコントラストを確保 */
display:flex; /* 中央寄せのためにFlexを使用 */
align-items:center; /* 垂直方向中央寄せ */
justify-content:center; /* 水平方向中央寄せ */
font-weight:700; /* 太字で見出し風に */
}
main{
height: 1600px; /* デモ用のスクロール領域の高さ */
border:1px dashed #e5e7eb; /* 目視できる点線の枠 */
border-radius:12px; /* 角丸で区切りを柔らかく */
margin:16px; /* 外側の余白 */
display:grid; /* 中央寄せの簡易レイアウト */
place-items:center; /* グリッドの中央に配置する省略記法 */
color:#64748b; /* テキストは落ち着いたグレー */
}
</style>
</head>
<body>
<!-- 画面上部:ヘッダー。ここが画面内にある間は“うさぎリンク”を隠します(後述JSの交差監視で制御) -->
<header>ヘッダー(この領域に重なる時は“うさぎ”を隠す)</header>
<!-- 長いメイン。スクロールで出現/非表示のタイミングを確認できます -->
<main>スクロールして挙動を確認してください</main>
<!-- 画面下部:フッター。ここが画面内にある間も“うさぎリンク”を隠します -->
<footer>フッター(この領域に重なる時は“うさぎ”を隠す)</footer>
<!-- ▼右下うさぎリンク(左:吹き出し/右:うさぎ) -->
<section id="rabbit-link-section" aria-label="右下常駐リンク">
<!-- aria-live="polite" は、状態変化(表示/非表示)を支援技術に穏やかに伝える意図 -->
<div class="rabbit-link" id="rabbit-link" aria-live="polite">
<!-- 並び順は「吹き出し → うさぎ」。左が吹き出し、右にうさぎ画像が来ます。 -->
<!--
★★ 差し替えポイント①(リンク先URL)★★
下記 href="https://example.com/" を、遷移させたいURLに変更してください。
例:チラシページ、キャンペーンLP、外部ストアなど。
target="_blank" + rel="noopener noreferrer" で新規タブ&セキュリティ確保。
-->
<a class="bubble"
href="https://example.com/"
target="_blank"
rel="noopener noreferrer"
aria-label="最新情報ページを新しいタブで開く">
<!-- 表示テキスト:1行目と2行目で訴求を分ける -->
チラシを<br>
<small>
いますぐ
<!-- “CHECK!”だけ下線を付けて強調(CSS直書き) -->
<span style="text-decoration: underline;">CHECK!</span>
</small>
</a>
<!--
★★ 差し替えポイント②(うさぎ画像URL)★★
下記 src="" のURLを、お好みの“背景透過PNG”に差し替えてください。
-->
<img class="rabbit"
src="https://png.pngtree.com/png-vector/20250516/ourlarge/pngtree-cute-rabbit-illustration-on-transparent-background-for-design-use-png-image_16301471.png"
alt="最新情報へ移動するうさぎ">
</div>
</section>
<script>
/* ===============================
右下固定「うさぎリンク」JS
・初回アニメの開始
・ヘッダー/フッターと重なる時の自動非表示
=============================== */
(function(){
// “うさぎリンク”本体を取得(見つからなければ何もしない)
const box = document.querySelector('#rabbit-link');
if(!box) return;
// 初期フレームでクラスを付けて、CSS側の「スライド表示アニメ」を開始
requestAnimationFrame(() => box.classList.add('is-ready'));
// ヘッダーとフッターの要素を取得
const header = document.querySelector('header');
const footer = document.querySelector('footer');
// IntersectionObserver で、header / footer がビューポートに入っているか(交差)を監視
const io = new IntersectionObserver((entries)=>{
// “どちらか1つでも交差していれば true”
const hit = entries.some(e => e.isIntersecting);
// data-hide="1" なら CSS 側で透明化&クリック不可に(=非表示扱い)
box.setAttribute('data-hide', hit ? '1' : '0');
}, {
root: null, // 画面(ビューポート)基準で監視
threshold: 0 // 1ピクセルでも交差したら「交差」とみなす
});
// それぞれ監視を開始(要素が存在する場合のみ)
if(header) io.observe(header);
if(footer) io.observe(footer);
})();
</script>
</body>
</html>
コメント