Copy code button (server side)
<article>
<h1>Copy code button (server side)</h1>
<p>The copy button is in the HTML file served.</p>
<p>Here lies a CSS code block sporting a copy button.</p>
<pre tabindex="0" class="shiki" style="background-color: #272822"><header><button>Copy Code</button></header><code><span class="line"><span style="color: #F92672">some-box</span><span style="color: #F8F8F2"> {</span></span>
<span class="line"><span style="color: #F8F8F2"> </span><span style="color: #66D9EF; font-style: italic">width</span><span style="color: #F8F8F2">: </span><span style="color: #AE81FF">20</span><span style="color: #F92672">px</span><span style="color: #F8F8F2">;</span></span>
<span class="line"><span style="color: #F8F8F2"> </span><span style="color: #66D9EF; font-style: italic">height</span><span style="color: #F8F8F2">: </span><span style="color: #AE81FF">20</span><span style="color: #F92672">px</span><span style="color: #F8F8F2">;</span></span>
<span class="line"><span style="color: #F8F8F2"> </span><span style="color: #66D9EF; font-style: italic">background</span><span style="color: #F8F8F2">: </span><span style="color: #66D9EF">black</span><span style="color: #F8F8F2">;</span></span>
<span class="line"><span style="color: #F8F8F2"> </span><span style="color: #66D9EF; font-style: italic">margin-bottom</span><span style="color: #F8F8F2">: </span><span style="color: #AE81FF">1.5</span><span style="color: #F92672">rem</span><span style="color: #F8F8F2">;</span></span>
<span class="line"><span style="color: #F8F8F2">}</span></span></code></pre>
<p>Here lies a HTML code block with a copy button. It overflows, the sticky header ensures the button is always visible.</p>
<pre tabindex="0" style="background-color: #272822"><header><button>Copy Code</button></header><code><span class="line"><span style="color: #F8F8F2">&lt;</span><span style="color: #F92672">div</span><span style="color: #F8F8F2">&gt;long text to show overflow and how you want to handle it&lt;/</span><span style="color: #F92672">div</span><span style="color: #F8F8F2">&gt;</span></span></code></pre>
<p>Here lies a <code>pre</code> block that does not contain a <code>code</code> element. You can see it does <em>not</em> have a copy button, as expected! Huzzah!</p>
<pre style="border: 1px dashed lightgrey;">This is a pre block without code.</pre>
</article> /* Code blocks */
pre:has(code) {
position: relative;
/* add scrollbar if there is horizontal overflow */
overflow-y: auto;
padding-inline: 0.5rem;
padding-block-end: 0.75rem;
margin: 0.5rem 0;
border-radius: 0.75rem;
}
/* Sticky header of the code block, It is never out of view. */
pre:has(code) header {
position: sticky;
top: 0;
left: 0;
width: 100%;
/* moves button to end of the header */
display: flex;
justify-content: end;
padding-block: 0.25rem;
}
/* The copy button. Style as you like! */
pre:has(code) button {
font-size: 0.9rem;
background-color: #828282;
margin-block: auto;
border: ridge 1px #7b7b7c;
border-radius: 5px;
text-shadow: #c4c4c4 0 0 2px;
}
/* Optional hover style for the copy button */
pre:has(code) button:hover {
background-color: #bcbabb;
}
/* general styles */
/* general styles */
*,
*:before,
*:after {
box-sizing: border-box;
}
body {
min-height: 100dvh;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
}
code {
font-size: 1rem;
font-family: "Fira Code", monospace;
}
article {
width: 100%;
max-width: 500px;
padding-inline: 0.25rem;
}
h1 {
font-size: 1.3rem;
} const copyButtonLabel = "Copy Code";
// only pre elements that have a code as a child
let blocks = document.querySelectorAll("pre:has(code)");
blocks.forEach((block) => {
let button = block.querySelector("button");
// handle click event
button.addEventListener("click", async () => {
await copyCode(block, button);
});
});
async function copyCode(block, button) {
let code = block.querySelector("code");
let text = code.innerText;
await navigator.clipboard.writeText(text);
// visual feedback that task is completed
button.innerText = "Code Copied";
setTimeout(() => {
button.innerText = copyButtonLabel;
}, 700);
} Description
A button for code blocks to copy the code to the clipboard
Tutorial
You can read this tutorial for a walkthrough of the code.