Копирование в буфер обмена
navigator.clipboard.writeText— современный способ скопировать текст по клику на кнопку с визуальным подтверждением.
Задача
Кнопка «Скопировать» рядом с кодом, ссылкой или токеном — нажал, текст в буфере, кнопка подтвердила это визуально.
Решение
<div class="copy-block">
<code class="copy-block__text" id="copyText">npm install my-package</code>
<button class="copy-btn" id="copyBtn" aria-label="Скопировать">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/>
</svg>
<span class="copy-btn__label">Скопировать</span>
</button>
</div>
.copy-block {
display: flex;
align-items: center;
gap: 12px;
padding: 12px 16px;
background: #1e293b;
border-radius: 8px;
}
.copy-block__text { color: #e2e8f0; font-family: monospace; font-size: 0.9rem; flex: 1; }
.copy-btn {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 12px;
background: #334155;
color: #e2e8f0;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 0.8rem;
transition: background 0.2s;
white-space: nowrap;
}
.copy-btn:hover { background: #475569; }
.copy-btn.copied { background: #16a34a; color: #fff; }
const btn = document.getElementById('copyBtn');
const text = document.getElementById('copyText');
const label = btn.querySelector('.copy-btn__label');
async function copyToClipboard(str) {
try {
await navigator.clipboard.writeText(str);
return true;
} catch {
// Fallback для браузеров без Clipboard API (редкость)
const ta = document.createElement('textarea');
ta.value = str;
ta.style.position = 'fixed';
ta.style.opacity = '0';
document.body.appendChild(ta);
ta.select;
document.execCommand('copy');
ta.remove();
return true;
}
}
btn.addEventListener('click', async () => {
const ok = await copyToClipboard(text.textContent.trim());
if (!ok) return;
btn.classList.add('copied');
label.textContent = 'Скопировано!';
setTimeout(() => {
btn.classList.remove('copied');
label.textContent = 'Скопировать';
}, 2000);
});
Ключевые моменты
navigator.clipboard.writeText— async, требует HTTPS или localhost; самый современный способ.execCommand('copy')— устаревший fallback; работает через программныйselectна<textarea>.- Визуальная обратная связь (смена текста кнопки на 2 сек) — обязательна: пользователь должен знать, что произошло.
aria-labelна кнопке — важен, если кнопка только иконка.
Варианты
navigator.clipboard.read/readText— чтение из буфера; требует разрешения пользователя.- Для React: хук
useCopyToClipboardс состояниемcopied.