作成した3つのソーシャルボタン
今回は、同じSNSボタンでも、ホバー時の演出が異なる3つのパターンを作成します。それぞれ異なる視覚効果で、ユーザーの注意を引きつけます。
パターン1:ツールチップポップアップ
ホバー時にSNS名がツールチップとして上部に表示されます。
HTML
<div class="social-buttons">
<div class="social-button x">
<i class="fab fa-x-twitter"></i>
<span class="label">X</span>
</div>
<div class="social-button facebook">
<i class="fab fa-facebook-f"></i>
<span class="label">Facebook</span>
</div>
<div class="social-button instagram">
<i class="fab fa-instagram"></i>
<span class="label">Instagram</span>
</div>
<div class="social-button line">
<i class="fab fa-line"></i>
<span class="label">LINE</span>
</div>
</div> CSS
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: #f5f5f5;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
padding: 2rem;
}
.social-buttons {
display: flex;
gap: 1.5rem;
flex-wrap: wrap;
justify-content: center;
}
.social-button {
position: relative;
width: 60px;
height: 60px;
border-radius: 15px;
display: flex;
align-items: center;
justify-content: center;
background: #f5f5f5;
cursor: pointer;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
overflow: visible;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
}
.social-button:hover {
transform: translateY(-5px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3);
}
.social-button i {
font-size: 1.8rem;
color: white;
z-index: 1;
position: relative;
}
.social-button .label {
position: absolute;
top: -50px;
left: 50%;
transform: translateX(-50%) translateY(20px) scale(0.8);
background: white;
color: #333;
padding: 0.5rem 1rem;
border-radius: 8px;
font-size: 0.9rem;
font-weight: 600;
white-space: nowrap;
opacity: 0;
pointer-events: none;
transition: all 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15);
}
.social-button .label::after {
content: '';
position: absolute;
bottom: -6px;
left: 50%;
transform: translateX(-50%);
width: 0;
height: 0;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-top: 6px solid white;
}
.social-button:hover .label {
opacity: 1;
transform: translateX(-50%) translateY(0) scale(1);
}
.social-button.x {
background: linear-gradient(135deg, #14171a 0%, #000000 100%);
}
.social-button.facebook {
background: linear-gradient(135deg, #1877f2 0%, #0e5fc1 100%);
}
.social-button.instagram {
background: linear-gradient(135deg, #e1306c 0%, #c13584 50%, #833ab4 100%);
}
.social-button.line {
background: linear-gradient(135deg, #00b900 0%, #00a000 100%);
} AIへのプロンプト例
以下のようなプロンプトをAIに送信します:
4つのSNSボタン(X、Facebook、Instagram、LINE)を作成してください。
### 初期状態
- それぞれのSNSブランドカラーのグラデーション背景
- 白いアイコン
- 角丸で柔らかい影
### ホバー時
- ボタンが少し上に浮き上がる
- SNS名がツールチップとして上部に表示される
- ツールチップは下向きの三角形の矢印付き
- 滑らかにフェードインしながら上から出現
このボタンの特徴
- 非破壊的な表示 ボタン自体は変形せず、ツールチップが追加表示される
- 三角形の矢印 CSS三角形テクニックで視覚的な関連性を強調
- バウンス効果 cubic-bezierでツールチップが弾むように出現
- シンプルな実装 JavaScriptなしで:hoverのみで完結
コードのポイント
ツールチップの配置:
.social-button .label {
position: absolute;
top: -50px; /* ボタンの上に配置 */
left: 50%; /* 水平中央揃え */
transform: translateX(-50%) translateY(20px) scale(0.8); /* 初期状態 */
opacity: 0;
}
.social-button:hover .label {
opacity: 1;
transform: translateX(-50%) translateY(0) scale(1); /* 最終状態 */
} position: absoluteで通常のレイアウトフローから外し、自由に配置left: 50%とtranslateX(-50%)で水平方向に完全中央配置- 初期状態では
translateY(20px)で下に、scale(0.8)で小さく - ホバー時に
translateY(0)とscale(1)で元の位置とサイズに
CSS三角形の作成:
.social-button .label::after {
content: '';
position: absolute;
bottom: -6px; /* ツールチップの下端に配置 */
left: 50%;
transform: translateX(-50%);
width: 0;
height: 0;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-top: 6px solid white; /* 下向きの三角形 */
} width: 0; height: 0でボックスのサイズをゼロにborderを使って三角形を描画(上のborderだけ色を付ける)border-leftとborder-rightを透明にすることで、下向きの三角形を作成
バウンス効果のイージング:
.social-button .label {
transition: all 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
} cubic-bezier(0.34, 1.56, 0.64, 1): 第2引数が1を超えるバウンス曲線- オーバーシュート効果で、ツールチップが勢いよく出現して少し戻る動き
- 視覚的に活き活きとした印象を与える
パターン2:横展開エフェクト
ホバーしたボタンが横に展開し、SNS名が表示されます。他のボタンは縮小します。
HTML
<div class="social-buttons">
<div class="social-button x" data-label="X">
<i class="fab fa-x-twitter"></i>
</div>
<div class="social-button facebook" data-label="Facebook">
<i class="fab fa-facebook-f"></i>
</div>
<div class="social-button instagram" data-label="Instagram">
<i class="fab fa-instagram"></i>
</div>
<div class="social-button line" data-label="LINE">
<i class="fab fa-line"></i>
</div>
</div>
<script>
const buttonsContainer = document.querySelector('.social-buttons');
const buttons = document.querySelectorAll('.social-button');
buttons.forEach((button, index) => {
button.addEventListener('mouseenter', function() {
buttons.forEach(btn => {
btn.classList.remove('expand', 'shrink');
const existingLabel = btn.querySelector('.label');
if (existingLabel) {
existingLabel.remove();
}
});
const gridTemplate = [];
for (let i = 0; i < buttons.length; i++) {
gridTemplate.push(i === index ? '3fr' : '0.6fr');
}
buttonsContainer.style.gridTemplateColumns = gridTemplate.join(' ');
this.classList.add('expand');
const label = document.createElement('span');
label.className = 'label';
label.textContent = this.dataset.label;
this.appendChild(label);
buttons.forEach(btn => {
if (btn !== this) btn.classList.add('shrink');
});
});
});
buttonsContainer.addEventListener('mouseleave', function() {
buttonsContainer.style.gridTemplateColumns = '1fr 1fr 1fr 1fr';
buttons.forEach(btn => {
btn.classList.remove('expand', 'shrink');
const label = btn.querySelector('.label');
if (label) label.remove();
});
});
</script> CSS
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: #f5f5f5;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
padding: 2rem;
}
.social-buttons {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
gap: 1rem;
width: 300px;
margin: 0 auto;
transition: grid-template-columns 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
.social-button {
position: relative;
height: 60px;
width: 100%;
border-radius: 15px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
overflow: hidden;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
.social-button.shrink {
opacity: 0.6;
}
.social-button.expand {
justify-content: flex-start;
padding-left: 20px;
}
.social-button i {
font-size: 1.8rem;
color: white;
transition: transform 0.3s ease;
}
.social-button .label {
color: white;
font-size: 1rem;
font-weight: 600;
margin-left: 15px;
white-space: nowrap;
opacity: 0;
transform: translateX(-20px);
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
.social-button.expand .label {
opacity: 1;
transform: translateX(0);
}
.social-button.x {
background: linear-gradient(135deg, #14171a 0%, #000000 100%);
}
.social-button.facebook {
background: linear-gradient(135deg, #1877f2 0%, #0e5fc1 100%);
}
.social-button.instagram {
background: linear-gradient(135deg, #e1306c 0%, #c13584 50%, #833ab4 100%);
}
.social-button.line {
background: linear-gradient(135deg, #00b900 0%, #00a000 100%);
} AIへのプロンプト例
以下のようなプロンプトをAIに送信します:
4つのSNSボタン(X、Facebook、Instagram、LINE)を作成してください。
### 初期状態
- 4つのボタンが均等に並んでいる
- それぞれのSNSブランドカラーのグラデーション背景
- 白いアイコン
- 角丸で柔らかい影
### ホバー時
- ホバーしたボタンが横に展開
- ボタンの左側にアイコン、右側にSNS名が表示される
- 他のボタンは縮小して薄くなる
### コンテナから離れたとき
- すべてのボタンが元の状態に戻る
このボタンの特徴
- 動的レイアウト CSS Gridの列幅をJavaScriptで動的に変更
- 視覚的フィードバック ホバーしていないボタンは縮小・透明化して注目を促す
- ラベルの遅延表示 transformとopacityでラベルが滑らかに出現
- 状態管理 クラスとDOM操作で拡張・縮小状態を制御
コードのポイント
Grid列の動的変更:
.social-buttons {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr; /* 初期状態 */
transition: grid-template-columns 0.4s cubic-bezier(0.4, 0, 0.2, 1);
} // ホバー時に列幅を変更
const gridTemplate = [];
for (let i = 0; i < buttons.length; i++) {
gridTemplate.push(i === index ? '3fr' : '0.6fr'); // 3fr : 0.6fr の比率
}
buttonsContainer.style.gridTemplateColumns = gridTemplate.join(' '); grid-template-columnsにtransitionを適用して滑らかに列幅を変更- ホバーしたボタンは
3fr(3倍)、他は0.6fr(0.6倍)に設定 fr単位を使うことで、全体の幅に対する比率で制御
ラベルの動的生成と表示:
// ラベルを動的に追加
const label = document.createElement('span');
label.className = 'label';
label.textContent = this.dataset.label;
this.appendChild(label); .social-button .label {
opacity: 0;
transform: translateX(-20px); /* 左から出現 */
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
.social-button.expand .label {
opacity: 1;
transform: translateX(0); /* 元の位置へ */
} - JavaScriptで
<span>要素を動的に生成・追加 - CSSで
opacityとtranslateXを使って左からフェードイン expandクラスが付いたときに表示アニメーション実行
パターン3:アイコンズーム
ホバー時にアイコンが大きく拡大し、ゆっくり元のサイズに戻ります。
HTML
<div class="social-buttons">
<div class="social-button x">
<i class="fab fa-x-twitter"></i>
<span class="label">X</span>
</div>
<div class="social-button facebook">
<i class="fab fa-facebook-f"></i>
<span class="label">Facebook</span>
</div>
<div class="social-button instagram">
<i class="fab fa-instagram"></i>
<span class="label">Instagram</span>
</div>
<div class="social-button line">
<i class="fab fa-line"></i>
<span class="label">LINE</span>
</div>
</div> CSS
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: #f5f5f5;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
padding: 2rem;
}
.social-buttons {
display: flex;
gap: 1.5rem;
flex-wrap: wrap;
justify-content: center;
}
.social-button {
position: relative;
width: 60px;
height: 60px;
border-radius: 15px;
display: flex;
align-items: center;
justify-content: center;
background: #f5f5f5;
cursor: pointer;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
overflow: visible;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
}
.social-button:hover {
transform: translateY(-5px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3);
}
.social-button i {
font-size: 1.8rem;
color: white;
z-index: 1;
position: relative;
transition: none;
}
.social-button:hover i {
animation: iconZoom 2s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}
.social-button .label {
display: none;
}
@keyframes iconZoom {
0% {
transform: scale(1);
}
20% {
transform: scale(5);
}
100% {
transform: scale(1);
}
}
.social-button.x {
background: linear-gradient(135deg, #14171a 0%, #000000 100%);
}
.social-button.facebook {
background: linear-gradient(135deg, #1877f2 0%, #0e5fc1 100%);
}
.social-button.instagram {
background: linear-gradient(135deg, #e1306c 0%, #c13584 50%, #833ab4 100%);
}
.social-button.line {
background: linear-gradient(135deg, #00b900 0%, #00a000 100%);
} AIへのプロンプト例
以下のようなプロンプトをAIに送信します:
4つのSNSボタン(X、Facebook、Instagram、LINE)を作成してください。
### 初期状態
- それぞれのSNSブランドカラーのグラデーション背景
- 白いアイコン
- 角丸で柔らかい影
### ホバー時
- ボタンが少し上に浮き上がる
- アイコンが瞬間的に大きく拡大
- その後、ゆっくりと元のサイズに戻る
- 拡大時はバウンス効果を持たせる
このボタンの特徴
- ドラマチックな演出 アイコンが5倍まで瞬間拡大してから元に戻る
- バウンス効果 cubic-bezierでオーバーシュートする動き
- 長めのアニメーション 2秒かけてゆっくり変化し、印象に残る
- シンプルな構造 JavaScriptを使わずCSSアニメーションのみで実装
コードのポイント
キーフレームアニメーション:
@keyframes iconZoom {
0% {
transform: scale(1); /* 初期サイズ */
}
20% {
transform: scale(5); /* 0.4秒で5倍に拡大 */
}
100% {
transform: scale(1); /* 残り1.6秒で元に戻る */
}
} 0%から20%(0.4秒)で一気に5倍に拡大20%から100%(1.6秒)でゆっくり元のサイズに戻る- 急激な拡大と緩やかな縮小でインパクトのある演出
バウンス効果のイージング:
.social-button:hover i {
animation: iconZoom 2s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
} cubic-bezier(0.34, 1.56, 0.64, 1): バウンス効果のあるイージング- 第2引数
1.56が1を超えることで、オーバーシュート(行き過ぎて戻る)動きを実現 forwardsで、アニメーション終了後も最終状態(scale(1))を維持
transition無効化:
.social-button i {
transition: none; /* transitionを無効化 */
} transition: noneでtransitionによる自動補間を無効化- アニメーションの動きをキーフレームで完全に制御
- 意図しない動きの混在を防ぐ
まとめ
ソーシャルボタン実装のポイント
- ツールチップパターン absolute配置、CSS三角形、バウンスイージングで情報を非破壊的に表示
- 横展開パターン JavaScriptでGridのfr単位を動的に変更し、視線を誘導
- アイコンズームパターン キーフレームアニメーションで瞬間的な拡大と緩やかな縮小を演出
- SNSブランドカラー 各SNSの公式カラーグラデーションで統一感とブランド認識を向上
- 用途に応じた使い分け 情報提示、注目誘導、エンターテインメント性など目的に合わせて選択
次回は、より複雑なインタラクティブ要素について学んでいきます。