Pasting link from right-click context menu pastes only URL in Safari
OS: macOS 13-14 · Device: Desktop or Laptop Any · Browser: Safari 16+ · Keyboard: US QWERTY
Open case →Scenario
When pasting links into contenteditable elements, different browsers handle the link data differently. Some browsers paste only the URL, while others preserve the link title and HTML structure.
When pasting links into contenteditable elements, different browsers handle the link data differently. Some browsers paste only the URL, while others preserve the link title and HTML structure.
Use Clipboard API to read link data and manually create link elements:
editor.addEventListener('paste', async (e) => {
e.preventDefault();
const clipboardData = e.clipboardData || window.clipboardData;
const pastedText = clipboardData.getData('text/plain');
// Check if pasted text is a URL
const urlPattern = /^https?:\/\/.+/;
if (urlPattern.test(pastedText.trim())) {
// Try to get link title from clipboard
let linkTitle = pastedText;
try {
const htmlData = clipboardData.getData('text/html');
if (htmlData) {
const parser = new DOMParser();
const doc = parser.parseFromString(htmlData, 'text/html');
const link = doc.querySelector('a');
if (link) {
linkTitle = link.textContent || link.href;
}
}
} catch (err) {
// Fallback to URL
}
// Create link element
const link = document.createElement('a');
link.href = pastedText.trim();
link.textContent = linkTitle;
link.target = '_blank';
link.rel = 'noopener noreferrer';
// Insert link at cursor position
const selection = window.getSelection();
if (selection.rangeCount > 0) {
const range = selection.getRangeAt(0);
range.deleteContents();
range.insertNode(link);
range.collapse(false);
selection.removeAllRanges();
selection.addRange(range);
}
}
});
Detect plain URL pastes and convert them to links:
function isUrl(text) {
const urlPattern = /^https?:\/\/.+/;
return urlPattern.test(text.trim());
}
function convertUrlToLink(url) {
const link = document.createElement('a');
link.href = url;
link.textContent = url;
return link;
}
Visual view of how this scenario connects to its concrete cases and environments. Nodes can be dragged and clicked.
Each row is a concrete case for this scenario, with a dedicated document and playground.
| Case | OS | Device | Browser | Keyboard | Status |
|---|---|---|---|---|---|
| ce-0301-safari-paste-link-url-only-en | macOS 13-14 | Desktop or Laptop Any | Safari 16+ | US QWERTY | draft |
Open a case to see the detailed description and its dedicated playground.
OS: macOS 13-14 · Device: Desktop or Laptop Any · Browser: Safari 16+ · Keyboard: US QWERTY
Open case →Other scenarios that share similar tags or category.
When using the Clipboard API (navigator.clipboard.readText() or navigator.clipboard.read()) to programmatically paste content into a contenteditable region, the paste operation may fail or not work as expected.
When pasting content from a rich text source into a contenteditable element, the resulting DOM loses headings, lists, or inline formatting that were present in the source.
After pasting content into a contenteditable region, the caret position does not end up at the expected location, sometimes jumping to the beginning of the pasted content or to an unexpected position.
In Chrome on Windows, calling `preventDefault()` on the `paste` event does not always prevent the default paste behavior. Content may still be pasted despite the prevention.
When attempting to paste images (from clipboard) into a contenteditable region, the behavior is inconsistent across browsers. Some browsers ignore the paste, while others may insert a placeholder or fail silently.
Have questions, suggestions, or want to share your experience? Join the discussion below.