It is impossible to highlight and copy code blocks when you are unable to use your hands.
If you’ve been watching my streams in 2025, you’ll know that I’m currently suffering from carpel tunnel syndrome. In an attempt to rest my hands and ease the pain, I have been trying to code, navigate the internet, and use my machine with my voice. This has not been without significant challenges, and until you experience this for yourself, it is very difficult to understand just how hostile technology is towards people who have limited or no use of their hands. Those of you who know me, know I am a huge advocate for an accessible web and accessibility practices, but given this is the first time I have experienced the limited use of my hands, I had no idea just how important it was to give people the ability to perform as few actions as possible on a machine to get their job done.
It is extremely difficult to highlight blocks of code and copy them with voice commands. At this point, for me at least, it is impossible. (Either it is actually impossible, or I haven’t had the brainpower to work out how to do it yet. Learning to navigate the web and code without your hands takes a huge mental toll.) For this reason, when you’re writing about code, especially when you’re creating tutorials that involve the reader copying and pasting code, it is absolutely imperative that you include a way for people with limited use of their hands to copy that code in a single action.
Prior to my experience with carpal tunnel syndrome, I was of the opinion that a copy code button was superfluous. But I was wrong. And so, one of my first voice-based coding tasks was to add a copy code button on all code snippets featured on my blog posts. I am working on another blog post where I talk about my voice coding journey, but in case you’re interested, the tools I have been using are Talon and Cursorless inside VSCode. Relearning how to do everything on a computer with your voice involves a steep learning curve, but this whole endeavour is giving me some pain relief already. And yes, I am writing this blog post with my voice as much as my tools allow.
My copy code snippet button solution is written in plain HTML, CSS and JavaScript inside an Eleventy project using the JavaScript templating engine (hence the use of string interpolation with curly braces).
The HTML (and some preliminary JavaScript to build the HTML)
In a blog post about code, you’ll probably have more than one code block snippet on the page. For this reason, you need to assign each code block with a unique ID in order to target the correct content to copy. You can generate a unique ID in any way you like, such as by using an external library to do so, but here’s how I did it for each code snippet at build time.
function makeId(length) {
let result = "";
const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
const charactersLength = characters.length;
let counter = 0;
while (counter < length) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
counter += 1;
}
return result;
}
const thisCodeID = makeId(10);
Given that formatted and syntax-highlighted code blocks will contain extra HTML and CSS classes to power the formatting and highlighting, we need to ensure that the copy button only copies the raw code content to the clipboard. My solution to this was to store the raw code string in a meta tag for easy retrieval in JavaScript (in contrast to stripping out extraneous HTML tags; and even then, we wouldn’t want to strip HTML tags from an HTML code snippet!). When storing the raw code string in a meta tag, you’ll also want to use encodeURIComponent
so that the code doesn’t actually execute on the page if it is able to (such as in the case of JavaScript). This meta tag lives next to each code block on my blog posts.
<meta
data-code-id="${thisCodeID}"
data-code-to-copy="${encodeURIComponent(codeSnippet)}"
>
Next, add a button next to or inside the code block, referencing the unique identifier you created earlier. I also chose to add a little clipboard SVG icon next to the button text. If you choose to omit the button text and use an icon only, make sure to use an aria-label to ensure the button has an accessible name (e.g. "Copy code snippet") that can be understood by assistive technologies such as screen readers.
<button type="button" data-copy="${thisCodeId}">
Copy
</button>
The CSS
I’m not going to prescribe how to style this copy button on your own blog posts, but I chose to position mine absolutely at the top right of each code block. Ensure you include styles on the button for focus
, active
and focus-visible
to ensure that people who are reading your blog posts without a mouse and navigating through the clickable elements using a keyboard or their voice have a clear indication of which element is currently focussed and has been clicked.
The JavaScript
Finally, use JavaScript to find each copy button on the page, and add the following event listener to each button. This code grabs the unique identifier for the raw code snippet from the button, finds the relevant meta
tag, and copies the raw code stored in that meta
tag to the clipboard. Ensure to use decodeURIComponent
to copy the raw code snippet to its original form.
const copyButtons = document.querySelectorAll(`[data-copy]`);
copyButtons.forEach((button) => {
button.addEventListener("click", (e) => {
const codeId = e.target.dataset.copy;
const codeAsText = document.querySelector(`[data-code-id=${codeId}]`).dataset.codeToCopy;
navigator.clipboard.writeText(decodeURIComponent(codeAsText));
});
});
This solution will transfer pretty well to your favourite front end framework of choice. And remember, temporary disabilities can happen to anyone; none of us are immortal.
🦋 likes on Bluesky
Like this post on Bluesky to see your face on this pageSalma Alam-Naylor
I'm a live streamer, software engineer, and developer educator. I help developers build cool stuff with blog posts, videos, live coding and open source projects.