32 CSS Floating Action Button Designs 12 / 32
Draggable FAB
Fully draggable floating action button with corner snapping, touch and mouse support, particle trail effect, and position indicator.
The code
<div class="fb12">
<!-- corner snap zones -->
<div class="fb12-snap-zone" id="fb12-sz-tl">TL</div>
<div class="fb12-snap-zone" id="fb12-sz-tr">TR</div>
<div class="fb12-snap-zone" id="fb12-sz-bl">BL</div>
<div class="fb12-snap-zone" id="fb12-sz-br">BR</div>
<div id="fb12-pos-label"></div>
<div class="fb12-page-mock">
<h1>Draggable<br>Floating Button</h1>
<p>Grab the indigo FAB and drag it anywhere on screen. It snaps to the nearest corner when released. Touch and mouse supported.</p>
<div class="fb12-hint-grid">
<div class="fb12-hint-card">
<div class="fb12-icon">✋</div>
<span>Drag anywhere on screen</span>
</div>
<div class="fb12-hint-card">
<div class="fb12-icon">🎯</div>
<span>Snaps to nearest corner</span>
</div>
<div class="fb12-hint-card">
<div class="fb12-icon">📱</div>
<span>Touch & mouse support</span>
</div>
</div>
</div>
<!-- DRAGGABLE FAB -->
<div id="fb12-drag-fab" role="button" aria-label="Draggable action button" tabindex="0">
<div class="fb12-drag-btn">
<svg viewBox="0 0 24 24"><path d="M19 11h-6V5h-2v6H5v2h6v6h2v-6h6z"/></svg>
</div>
</div>
</div> <div class="fb12">
<!-- corner snap zones -->
<div class="fb12-snap-zone" id="fb12-sz-tl">TL</div>
<div class="fb12-snap-zone" id="fb12-sz-tr">TR</div>
<div class="fb12-snap-zone" id="fb12-sz-bl">BL</div>
<div class="fb12-snap-zone" id="fb12-sz-br">BR</div>
<div id="fb12-pos-label"></div>
<div class="fb12-page-mock">
<h1>Draggable<br>Floating Button</h1>
<p>Grab the indigo FAB and drag it anywhere on screen. It snaps to the nearest corner when released. Touch and mouse supported.</p>
<div class="fb12-hint-grid">
<div class="fb12-hint-card">
<div class="fb12-icon">✋</div>
<span>Drag anywhere on screen</span>
</div>
<div class="fb12-hint-card">
<div class="fb12-icon">🎯</div>
<span>Snaps to nearest corner</span>
</div>
<div class="fb12-hint-card">
<div class="fb12-icon">📱</div>
<span>Touch & mouse support</span>
</div>
</div>
</div>
<!-- DRAGGABLE FAB -->
<div id="fb12-drag-fab" role="button" aria-label="Draggable action button" tabindex="0">
<div class="fb12-drag-btn">
<svg viewBox="0 0 24 24"><path d="M19 11h-6V5h-2v6H5v2h6v6h2v-6h6z"/></svg>
</div>
</div>
</div>.fb12, .fb12 *, .fb12 *::before, .fb12 *::after { box-sizing: border-box; margin: 0; padding: 0; }
.fb12 {
font-family: 'Inter', sans-serif;
background: #f1f5f9;
min-height: 100vh;
overflow: hidden;
color: #334155;
display: grid;
place-items: center;
position: relative;
}
/* ── page mockup ── */
.fb12-page-mock {
width: min(720px, 100%);
padding: 32px 24px;
text-align: center;
}
.fb12-page-mock h1 {
font-size: clamp(1.8rem, 5vw, 2.6rem);
font-weight: 700;
letter-spacing: -.025em;
color: #0f172a;
margin-bottom: 14px;
}
.fb12-page-mock p {
color: #64748b;
font-size: .95rem;
line-height: 1.65;
max-width: 46ch;
margin: 0 auto 32px;
}
.fb12-hint-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 14px;
max-width: 480px;
margin: 0 auto;
}
.fb12-hint-card {
background: #fff;
border: 1px solid #e2e8f0;
border-radius: 14px;
padding: 16px 12px;
text-align: center;
box-shadow: 0 1px 4px rgba(0,0,0,.05);
}
.fb12-hint-card .fb12-icon { font-size: 1.6rem; margin-bottom: 8px; }
.fb12-hint-card span { font-size: .76rem; color: #64748b; font-weight: 500; display: block; }
/* ── DRAGGABLE FAB ── */
#fb12-drag-fab {
position: fixed;
bottom: 32px;
right: 32px;
z-index: 1000;
touch-action: none;
user-select: none;
cursor: grab;
}
#fb12-drag-fab.fb12-dragging { cursor: grabbing; }
.fb12-drag-btn {
width: 64px;
height: 64px;
border-radius: 50%;
background: linear-gradient(135deg, #6366f1, #4f46e5);
border: none;
display: grid;
place-items: center;
box-shadow:
0 8px 28px rgba(99,102,241,.45),
inset 0 1px 0 rgba(255,255,255,.2);
transition: transform .18s cubic-bezier(.34,1.56,.64,1), box-shadow .18s ease;
pointer-events: none;
position: relative;
}
#fb12-drag-fab:not(.fb12-dragging):hover .fb12-drag-btn {
transform: scale(1.08);
box-shadow: 0 12px 36px rgba(99,102,241,.6), inset 0 1px 0 rgba(255,255,255,.2);
}
#fb12-drag-fab.fb12-dragging .fb12-drag-btn {
transform: scale(1.12);
box-shadow: 0 18px 48px rgba(99,102,241,.55), 0 4px 8px rgba(0,0,0,.2), inset 0 1px 0 rgba(255,255,255,.2);
cursor: grabbing;
}
.fb12-drag-btn svg { width: 26px; height: 26px; fill: #fff; pointer-events: none; }
/* drag handle dots */
.fb12-drag-btn::before {
content: '⋮⋮';
position: absolute;
top: -5px;
left: 50%;
transform: translateX(-50%);
font-size: .6rem;
color: rgba(255,255,255,.5);
letter-spacing: 2px;
pointer-events: none;
}
/* ripple trail */
.fb12-trail {
position: fixed;
width: 12px;
height: 12px;
border-radius: 50%;
background: rgba(99,102,241,.35);
pointer-events: none;
transform: translate(-50%,-50%);
animation: fb12-trail-fade .6s ease-out forwards;
z-index: 999;
}
@keyframes fb12-trail-fade {
0% { transform: translate(-50%,-50%) scale(1); opacity: .5; }
100% { transform: translate(-50%,-50%) scale(.1); opacity: 0; }
}
/* position indicator */
#fb12-pos-label {
position: fixed;
top: 16px;
left: 50%;
transform: translateX(-50%);
background: rgba(15,23,42,.85);
backdrop-filter: blur(8px);
color: rgba(255,255,255,.7);
font-size: .72rem;
font-weight: 600;
letter-spacing: .04em;
padding: 7px 16px;
border-radius: 20px;
z-index: 1001;
font-family: monospace;
opacity: 0;
transition: opacity .2s;
}
#fb12-pos-label.fb12-visible { opacity: 1; }
/* snap zones hint (corners) */
.fb12-snap-zone {
position: fixed;
width: 80px;
height: 80px;
border: 2px dashed rgba(99,102,241,.2);
border-radius: 50%;
pointer-events: none;
z-index: 998;
display: flex;
align-items: center;
justify-content: center;
font-size: .6rem;
color: rgba(99,102,241,.3);
font-weight: 600;
letter-spacing: .06em;
text-transform: uppercase;
transition: border-color .2s, color .2s;
}
.fb12-snap-zone.fb12-active { border-color: rgba(99,102,241,.6); color: rgba(99,102,241,.7); }
#fb12-sz-tl { top: 16px; left: 16px; }
#fb12-sz-tr { top: 16px; right: 16px; }
#fb12-sz-bl { bottom: 16px; left: 16px; }
#fb12-sz-br { bottom: 16px; right: 16px; }
@media (prefers-reduced-motion: reduce) {
.fb12-drag-btn { transition: none; }
.fb12-trail { animation: none; }
} .fb12, .fb12 *, .fb12 *::before, .fb12 *::after { box-sizing: border-box; margin: 0; padding: 0; }
.fb12 {
font-family: 'Inter', sans-serif;
background: #f1f5f9;
min-height: 100vh;
overflow: hidden;
color: #334155;
display: grid;
place-items: center;
position: relative;
}
/* ── page mockup ── */
.fb12-page-mock {
width: min(720px, 100%);
padding: 32px 24px;
text-align: center;
}
.fb12-page-mock h1 {
font-size: clamp(1.8rem, 5vw, 2.6rem);
font-weight: 700;
letter-spacing: -.025em;
color: #0f172a;
margin-bottom: 14px;
}
.fb12-page-mock p {
color: #64748b;
font-size: .95rem;
line-height: 1.65;
max-width: 46ch;
margin: 0 auto 32px;
}
.fb12-hint-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 14px;
max-width: 480px;
margin: 0 auto;
}
.fb12-hint-card {
background: #fff;
border: 1px solid #e2e8f0;
border-radius: 14px;
padding: 16px 12px;
text-align: center;
box-shadow: 0 1px 4px rgba(0,0,0,.05);
}
.fb12-hint-card .fb12-icon { font-size: 1.6rem; margin-bottom: 8px; }
.fb12-hint-card span { font-size: .76rem; color: #64748b; font-weight: 500; display: block; }
/* ── DRAGGABLE FAB ── */
#fb12-drag-fab {
position: fixed;
bottom: 32px;
right: 32px;
z-index: 1000;
touch-action: none;
user-select: none;
cursor: grab;
}
#fb12-drag-fab.fb12-dragging { cursor: grabbing; }
.fb12-drag-btn {
width: 64px;
height: 64px;
border-radius: 50%;
background: linear-gradient(135deg, #6366f1, #4f46e5);
border: none;
display: grid;
place-items: center;
box-shadow:
0 8px 28px rgba(99,102,241,.45),
inset 0 1px 0 rgba(255,255,255,.2);
transition: transform .18s cubic-bezier(.34,1.56,.64,1), box-shadow .18s ease;
pointer-events: none;
position: relative;
}
#fb12-drag-fab:not(.fb12-dragging):hover .fb12-drag-btn {
transform: scale(1.08);
box-shadow: 0 12px 36px rgba(99,102,241,.6), inset 0 1px 0 rgba(255,255,255,.2);
}
#fb12-drag-fab.fb12-dragging .fb12-drag-btn {
transform: scale(1.12);
box-shadow: 0 18px 48px rgba(99,102,241,.55), 0 4px 8px rgba(0,0,0,.2), inset 0 1px 0 rgba(255,255,255,.2);
cursor: grabbing;
}
.fb12-drag-btn svg { width: 26px; height: 26px; fill: #fff; pointer-events: none; }
/* drag handle dots */
.fb12-drag-btn::before {
content: '⋮⋮';
position: absolute;
top: -5px;
left: 50%;
transform: translateX(-50%);
font-size: .6rem;
color: rgba(255,255,255,.5);
letter-spacing: 2px;
pointer-events: none;
}
/* ripple trail */
.fb12-trail {
position: fixed;
width: 12px;
height: 12px;
border-radius: 50%;
background: rgba(99,102,241,.35);
pointer-events: none;
transform: translate(-50%,-50%);
animation: fb12-trail-fade .6s ease-out forwards;
z-index: 999;
}
@keyframes fb12-trail-fade {
0% { transform: translate(-50%,-50%) scale(1); opacity: .5; }
100% { transform: translate(-50%,-50%) scale(.1); opacity: 0; }
}
/* position indicator */
#fb12-pos-label {
position: fixed;
top: 16px;
left: 50%;
transform: translateX(-50%);
background: rgba(15,23,42,.85);
backdrop-filter: blur(8px);
color: rgba(255,255,255,.7);
font-size: .72rem;
font-weight: 600;
letter-spacing: .04em;
padding: 7px 16px;
border-radius: 20px;
z-index: 1001;
font-family: monospace;
opacity: 0;
transition: opacity .2s;
}
#fb12-pos-label.fb12-visible { opacity: 1; }
/* snap zones hint (corners) */
.fb12-snap-zone {
position: fixed;
width: 80px;
height: 80px;
border: 2px dashed rgba(99,102,241,.2);
border-radius: 50%;
pointer-events: none;
z-index: 998;
display: flex;
align-items: center;
justify-content: center;
font-size: .6rem;
color: rgba(99,102,241,.3);
font-weight: 600;
letter-spacing: .06em;
text-transform: uppercase;
transition: border-color .2s, color .2s;
}
.fb12-snap-zone.fb12-active { border-color: rgba(99,102,241,.6); color: rgba(99,102,241,.7); }
#fb12-sz-tl { top: 16px; left: 16px; }
#fb12-sz-tr { top: 16px; right: 16px; }
#fb12-sz-bl { bottom: 16px; left: 16px; }
#fb12-sz-br { bottom: 16px; right: 16px; }
@media (prefers-reduced-motion: reduce) {
.fb12-drag-btn { transition: none; }
.fb12-trail { animation: none; }
}(function() {
const fab = document.getElementById('fb12-drag-fab');
const posLabel = document.getElementById('fb12-pos-label');
const SNAP = 24; // px from edge
const TRAIL = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
let isDragging = false, startX, startY, fabX, fabY, lastMoveX, lastMoveY;
// Set initial position
fabX = window.innerWidth - fab.offsetWidth - 32;
fabY = window.innerHeight - fab.offsetHeight - 32;
setPos(fabX, fabY);
function setPos(x, y) {
x = Math.max(SNAP, Math.min(x, window.innerWidth - fab.offsetWidth - SNAP));
y = Math.max(SNAP, Math.min(y, window.innerHeight - fab.offsetHeight - SNAP));
fab.style.left = x + 'px';
fab.style.top = y + 'px';
fab.style.right = 'auto';
fab.style.bottom = 'auto';
fabX = x; fabY = y;
}
function snapToCorner() {
const cx = fabX + fab.offsetWidth / 2;
const cy = fabY + fab.offsetHeight / 2;
const W = window.innerWidth;
const H = window.innerHeight;
const PAD = 28;
let tx = cx < W/2 ? PAD : W - fab.offsetWidth - PAD;
let ty = cy < H/2 ? PAD : H - fab.offsetHeight - PAD;
// animated spring to corner
fab.style.transition = 'left .35s cubic-bezier(.34,1.56,.64,1), top .35s cubic-bezier(.34,1.56,.64,1)';
setPos(tx, ty);
setTimeout(() => { fab.style.transition = ''; }, 400);
}
function spawnTrail(x, y) {
if (TRAIL) return;
const dot = document.createElement('div');
dot.className = 'fb12-trail';
dot.style.left = x + 'px';
dot.style.top = y + 'px';
document.body.appendChild(dot);
setTimeout(() => dot.remove(), 700);
}
function highlightSnap() {
const cx = fabX + fab.offsetWidth / 2;
const cy = fabY + fab.offsetHeight / 2;
const W = window.innerWidth, H = window.innerHeight;
const isLeft = cx < W/2, isTop = cy < H/2;
document.getElementById('fb12-sz-tl').classList.toggle('fb12-active', isLeft && isTop);
document.getElementById('fb12-sz-tr').classList.toggle('fb12-active', !isLeft && isTop);
document.getElementById('fb12-sz-bl').classList.toggle('fb12-active', isLeft && !isTop);
document.getElementById('fb12-sz-br').classList.toggle('fb12-active', !isLeft && !isTop);
}
// Mouse
fab.addEventListener('mousedown', e => {
e.preventDefault();
isDragging = true;
fab.classList.add('fb12-dragging');
startX = e.clientX - fabX;
startY = e.clientY - fabY;
posLabel.classList.add('fb12-visible');
});
window.addEventListener('mousemove', e => {
if (!isDragging) return;
setPos(e.clientX - startX, e.clientY - startY);
highlightSnap();
posLabel.textContent = `x:${Math.round(fabX)} y:${Math.round(fabY)}`;
if (Math.abs(e.clientX - (lastMoveX||e.clientX)) > 12 || Math.abs(e.clientY - (lastMoveY||e.clientY)) > 12) {
spawnTrail(e.clientX, e.clientY);
lastMoveX = e.clientX; lastMoveY = e.clientY;
}
});
window.addEventListener('mouseup', () => {
if (!isDragging) return;
isDragging = false;
fab.classList.remove('fb12-dragging');
snapToCorner();
posLabel.classList.remove('fb12-visible');
document.querySelectorAll('.fb12-snap-zone').forEach(z => z.classList.remove('fb12-active'));
});
// Touch
fab.addEventListener('touchstart', e => {
const t = e.touches[0];
isDragging = true;
fab.classList.add('fb12-dragging');
startX = t.clientX - fabX;
startY = t.clientY - fabY;
posLabel.classList.add('fb12-visible');
}, { passive: true });
window.addEventListener('touchmove', e => {
if (!isDragging) return;
const t = e.touches[0];
setPos(t.clientX - startX, t.clientY - startY);
highlightSnap();
posLabel.textContent = `x:${Math.round(fabX)} y:${Math.round(fabY)}`;
}, { passive: true });
window.addEventListener('touchend', () => {
if (!isDragging) return;
isDragging = false;
fab.classList.remove('fb12-dragging');
snapToCorner();
posLabel.classList.remove('fb12-visible');
document.querySelectorAll('.fb12-snap-zone').forEach(z => z.classList.remove('fb12-active'));
});
})(); (function() {
const fab = document.getElementById('fb12-drag-fab');
const posLabel = document.getElementById('fb12-pos-label');
const SNAP = 24; // px from edge
const TRAIL = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
let isDragging = false, startX, startY, fabX, fabY, lastMoveX, lastMoveY;
// Set initial position
fabX = window.innerWidth - fab.offsetWidth - 32;
fabY = window.innerHeight - fab.offsetHeight - 32;
setPos(fabX, fabY);
function setPos(x, y) {
x = Math.max(SNAP, Math.min(x, window.innerWidth - fab.offsetWidth - SNAP));
y = Math.max(SNAP, Math.min(y, window.innerHeight - fab.offsetHeight - SNAP));
fab.style.left = x + 'px';
fab.style.top = y + 'px';
fab.style.right = 'auto';
fab.style.bottom = 'auto';
fabX = x; fabY = y;
}
function snapToCorner() {
const cx = fabX + fab.offsetWidth / 2;
const cy = fabY + fab.offsetHeight / 2;
const W = window.innerWidth;
const H = window.innerHeight;
const PAD = 28;
let tx = cx < W/2 ? PAD : W - fab.offsetWidth - PAD;
let ty = cy < H/2 ? PAD : H - fab.offsetHeight - PAD;
// animated spring to corner
fab.style.transition = 'left .35s cubic-bezier(.34,1.56,.64,1), top .35s cubic-bezier(.34,1.56,.64,1)';
setPos(tx, ty);
setTimeout(() => { fab.style.transition = ''; }, 400);
}
function spawnTrail(x, y) {
if (TRAIL) return;
const dot = document.createElement('div');
dot.className = 'fb12-trail';
dot.style.left = x + 'px';
dot.style.top = y + 'px';
document.body.appendChild(dot);
setTimeout(() => dot.remove(), 700);
}
function highlightSnap() {
const cx = fabX + fab.offsetWidth / 2;
const cy = fabY + fab.offsetHeight / 2;
const W = window.innerWidth, H = window.innerHeight;
const isLeft = cx < W/2, isTop = cy < H/2;
document.getElementById('fb12-sz-tl').classList.toggle('fb12-active', isLeft && isTop);
document.getElementById('fb12-sz-tr').classList.toggle('fb12-active', !isLeft && isTop);
document.getElementById('fb12-sz-bl').classList.toggle('fb12-active', isLeft && !isTop);
document.getElementById('fb12-sz-br').classList.toggle('fb12-active', !isLeft && !isTop);
}
// Mouse
fab.addEventListener('mousedown', e => {
e.preventDefault();
isDragging = true;
fab.classList.add('fb12-dragging');
startX = e.clientX - fabX;
startY = e.clientY - fabY;
posLabel.classList.add('fb12-visible');
});
window.addEventListener('mousemove', e => {
if (!isDragging) return;
setPos(e.clientX - startX, e.clientY - startY);
highlightSnap();
posLabel.textContent = `x:${Math.round(fabX)} y:${Math.round(fabY)}`;
if (Math.abs(e.clientX - (lastMoveX||e.clientX)) > 12 || Math.abs(e.clientY - (lastMoveY||e.clientY)) > 12) {
spawnTrail(e.clientX, e.clientY);
lastMoveX = e.clientX; lastMoveY = e.clientY;
}
});
window.addEventListener('mouseup', () => {
if (!isDragging) return;
isDragging = false;
fab.classList.remove('fb12-dragging');
snapToCorner();
posLabel.classList.remove('fb12-visible');
document.querySelectorAll('.fb12-snap-zone').forEach(z => z.classList.remove('fb12-active'));
});
// Touch
fab.addEventListener('touchstart', e => {
const t = e.touches[0];
isDragging = true;
fab.classList.add('fb12-dragging');
startX = t.clientX - fabX;
startY = t.clientY - fabY;
posLabel.classList.add('fb12-visible');
}, { passive: true });
window.addEventListener('touchmove', e => {
if (!isDragging) return;
const t = e.touches[0];
setPos(t.clientX - startX, t.clientY - startY);
highlightSnap();
posLabel.textContent = `x:${Math.round(fabX)} y:${Math.round(fabY)}`;
}, { passive: true });
window.addEventListener('touchend', () => {
if (!isDragging) return;
isDragging = false;
fab.classList.remove('fb12-dragging');
snapToCorner();
posLabel.classList.remove('fb12-visible');
document.querySelectorAll('.fb12-snap-zone').forEach(z => z.classList.remove('fb12-active'));
});
})();More from 32 CSS Floating Action Button Designs
Neon Glow FABCompose + Tooltip FABClassic PlusSpeed DialPulse RingMorphing FABLabeled PillScroll to TopNeon CyberGlass FABBrutalist StampNotification Badge
View the full collection →