Bouton copier dans le presse-papiers (JavaScript et React)
Bouton copier dans le presse-papiers
Bouton copier dans le presse-papiers en JavaScript et React | We.Inc
Créez un bouton copier avec navigator.clipboard.writeText : démo fonctionnelle, hook React, copie de HTML enrichi et d'images avec ClipboardItem, retour Copié accessible et gestion des erreurs.
Appelez navigator.clipboard.writeText(text) depuis un gestionnaire de clic. Il renvoie une promesse : attendez-la avec await, affichez ensuite un court message Copié et interceptez le cas d'erreur. L'API ne fonctionne qu'en HTTPS ou sur localhost, et elle exige une vraie action de l'utilisateur comme un clic : ne l'appelez donc pas au chargement de la page.
Façons de placer des données dans le presse-papiers
Un bouton copier paraît trivial, pourtant les extraits bien classés oublient souvent ce qui pose problème : la promesse peut être rejetée, les cadres intégrés peuvent être bloqués, et les utilisateurs de lecteurs d'écran n'entendent jamais que quelque chose s'est passé. La démo ci-dessous copie réellement dans votre navigateur, et le code couvre chacun de ces cas.
Appuyez sur un bouton Copier dans la démo. Le libellé passe à Copié pendant deux secondes, et un message d'état masqué l'annonce.
Collez dans la zone de test pour vérifier exactement ce qui se trouve dans votre presse-papiers.
Essayez le bouton de copie enrichie, puis collez dans un e-mail ou un éditeur de documents pour voir la version HTML conserver sa mise en forme.
Copiez ci-dessous le JavaScript pur, le hook React ou le code de copie enrichie.
Gérez toujours le rejet. Affichez par exemple Appuyez sur Ctrl+C pour copier et sélectionnez le texte pour que la personne puisse terminer à la main.
Annoncez la réussite avec une zone role="status". Changer seulement une icône n'apprend rien aux utilisateurs de lecteurs d'écran.
Gardez une largeur stable au libellé du bouton quand il passe à Copié, pour que rien ne saute autour.
Copiez la valeur depuis vos données, pas depuis le innerText d'un élément stylé, qui peut récupérer des espaces masqués ou superflus.
Dans une iframe, Chromium exige que le parent autorise clipboard-write via la Permissions Policy, par exemple allow="clipboard-write".
Questions fréquentes
Pourquoi navigator.clipboard vaut-il undefined ?
La page n'est pas dans un contexte sécurisé. L'API Clipboard n'est exposée que sur les pages HTTPS et sur localhost : un site servi en HTTP simple ou depuis une adresse du réseau local ne l'aura pas.
Pourquoi writeText lève-t-il NotAllowedError ?
Le navigateur a refusé l'écriture, généralement parce qu'il n'y a pas eu d'action récente de l'utilisateur, que la page n'avait pas le focus ou qu'un cadre était bloqué par la Permissions Policy. Appelez-le directement dans un gestionnaire de clic et évitez les longs await avant.
Faut-il une bibliothèque pour copier dans le presse-papiers avec React ?
Non. Un hook de dix lignes autour de navigator.clipboard.writeText suffit. Les bibliothèques ajoutent surtout une solution de repli execCommand pour de très vieux navigateurs, dont les navigateurs actuels n'ont pas besoin.
Peut-on copier une image dans le presse-papiers ?
Oui, avec navigator.clipboard.write et un ClipboardItem dont la clé est image/png et la valeur un Blob PNG. Utilisez d'abord ClipboardItem.supports() pour vérifier un type ; le PNG est le format que les navigateurs acceptent le plus sûrement.
document.execCommand('copy') est-il encore acceptable ?
Il est obsolète. Il fonctionne encore dans de nombreux navigateurs, selon des conditions variables, mais le nouveau code doit utiliser l'API Clipboard asynchrone, avec comme solution de repli une demande de copie manuelle.
Les trois règles imposées par le navigateur
Écrire dans le presse-papiers est une action privilégiée : les navigateurs exigent donc une page sécurisée, un document ayant le focus et, dans Firefox et Safari, un geste récent de l'utilisateur pour chaque écriture. Chromium peut aussi accorder une permission clipboard-write persistante.
En pratique, déclenchez la copie depuis un clic ou une touche, faites l'écriture tôt dans le gestionnaire et considérez l'échec comme normal plutôt qu'exceptionnel.
Un retour que chacun peut percevoir
Changez le libellé en Copié pendant environ deux secondes, puis rétablissez-le. Une infobulle qui n'apparaît qu'au survol est invisible sur écran tactile et pour les utilisateurs du clavier.
Placez le même message dans une zone live polie. role="status" l'annonce sans interrompre ce que le lecteur d'écran était en train de lire.
Copies enrichies et événements copy personnalisés
Un ClipboardItem peut contenir à la fois une version text/plain et une version text/html. Les applications qui comprennent le HTML collent la version mise en forme, les champs de texte brut prennent l'autre.
Pour modifier ce que copie un Ctrl+C normal, par exemple en ajoutant une ligne de source, écoutez l'événement copy, appelez event.preventDefault() et définissez vos propres données avec event.clipboardData.setData().
JavaScript pur
Bouton copier avec retour et solution de repli
L'élément de statut est masqué visuellement mais lu à voix haute. En cas d'échec, le texte est sélectionné pour que la personne puisse appuyer sur Ctrl+C ou Cmd+C.
Hook React
useCopyToClipboard
Renvoie l'état et une fonction de copie. Le minuteur est annulé au démontage, il ne met donc jamais à jour un composant supprimé.
Texte enrichi, images et événement copy
Copier du HTML avec une version texte brut de repli
Chaque type MIME est un Blob. Les cibles du collage choisissent le format le plus riche qu'elles comprennent.
Ajouter une ligne de source aux copies normales
À utiliser avec modération. Modifier ce que les gens copient peut les agacer : réservez-le aux citations ou au code, où une source est utile.
Erreurs et leurs causes
Quand la copie échoue
Ce que vous voyez
Cause probable
Solution
navigator.clipboard vaut undefined
Page servie en HTTP simple
Servez en HTTPS, ou testez sur localhost
NotAllowedError
Pas de geste utilisateur, ou l'onglet n'a pas le focus
Appelez-le dans le gestionnaire de clic
NotAllowedError dans une iframe
La Permissions Policy bloque clipboard-write
Ajoutez allow="clipboard-write" sur l'iframe
Copie d'image refusée
Type MIME non pris en charge
Convertissez en PNG et vérifiez ClipboardItem.supports()
Copié
Échec
Copier
Copier le texte enrichi
Copié dans le presse-papiers
La copie a échoué. Sélectionnez le texte et appuyez sur Ctrl+C ou Cmd+C.
Essayez
Des boutons copier pour du texte brut et du HTML enrichi, avec une zone de collage pour vérifier le résultat.