WordPress 程式碼區塊加入 Copy 按鈕與水平捲動:使用 CSS + JavaScript 實作一鍵複製

在撰寫技術文章時,經常會需要放入各種指令、設定檔與程式碼範例。如果內容只有短短幾行,讀者手動選取並複製或許還不算麻煩。但當內容變長之後,光是要完整選取整段程式碼,就會變得有些不方便。

今天就來教大家如何在 WordPress 程式碼區塊加入 Copy 按鈕與水平捲動,讓讀者直接將整段內容複製到剪貼簿,閱讀體驗也會好上不少。

以我自己的使用習慣來說,我會使用「程式碼區塊」來放置各種指令、設定檔內容與程式碼。至於指令執行後的輸出結果,則會使用「未格式化文字區塊」來呈現。

這樣不僅能清楚區分要執行的內容與執行後的結果,閱讀文章時也會更加直覺。

安裝 WPCode 外掛

WPCode 是一款用來管理 WordPress 自訂程式碼的外掛,讓我們可以直接從 WordPress 後台加入與管理各種 Code Snippet 程式碼片段,而不需要直接修改佈景主題的 functions.php 或其他核心檔案。

我們只要利用少量的 JavaScript 動態加入 Copy 按鈕,再透過 CSS 調整按鈕外觀,就能替網站上的程式碼區塊加入一鍵複製功能。

點選 Code Snippets 的 Header & Footer,我們就可以在 Header 透過 JavaScript 加入 Copy 按鈕。

添加 JavaScript 的語法如下,點選 Save Change。

<!-- 自訂 Copy 按鈕永遠固定在右上角,下面的程式碼可以左右滑動 -->
<script>
	document.addEventListener('DOMContentLoaded', function () {
	    document.querySelectorAll('.wp-block-code').forEach(function (block) {
			/* 避免重複處理 */
			if (block.parentElement.classList.contains('code-block-wrapper')) {
				return;
			}
			
			const code = block.querySelector('code');
			
			if (!code) {
				return;
			}
			
			/* 建立外層容器 */
			const wrapper = document.createElement('div');
			wrapper.className = 'code-block-wrapper';
			
			/* 將 wrapper 插入原本 pre 的位置 */
			block.parentNode.insertBefore(wrapper, block);
			
			/* 將 pre 移入 wrapper */
			wrapper.appendChild(block);
			
			/* 建立 Copy 按鈕 */
			const button = document.createElement('button');
			button.className = 'copy-code-button';
			button.type = 'button';
			button.textContent = 'Copy';
			
			/* 將按鈕放在 wrapper,而不是 pre 裡面 */
			wrapper.appendChild(button);
			
			/* Copy */
			button.addEventListener('click', async function () {
				try {
					await navigator.clipboard.writeText(code.innerText);
					button.textContent = '✓ Copied';
					setTimeout(function () {
						button.textContent = 'Copy';
					}, 2000);
				} catch (err) {
					console.error('Copy failed:', err);
				}
			});
		});
	});
</script>

點選外觀的自訂,目前使用的 Blocksy 背景主題,點選附加的 CSS。

添加 CSS 的語法如下,點選發佈。

/* ========================================
   程式碼區塊外層
   ======================================== */

.code-block-wrapper {
    position: relative;
}


/* ========================================
   程式碼區塊
   ======================================== */

.code-block-wrapper .wp-block-code {
    /* 頂部保留 Copy 按鈕空間 */
    padding-top: 48px !important;

    /* 只有程式碼區塊可以左右捲動 */
    overflow-x: auto;
}


/* ========================================
   程式碼內容
   ======================================== */

.code-block-wrapper .wp-block-code code {
    /* 保留原始格式,不自動換行 */
    white-space: pre;

    /* 不強制切斷網址、路徑、指令 */
    word-break: normal;
    overflow-wrap: normal;
}


/* ========================================
   Copy 按鈕
   ======================================== */

.code-block-wrapper > .copy-code-button {
    position: absolute;

    top: 8px;
    right: 10px;

    padding: 6px 12px;

    border: 1px solid #d0d7de;
    border-radius: 6px;

    background: #ffffff;
    color: #24292f;

    font-size: 12px;
    font-weight: 500;
    line-height: 1.4;

    cursor: pointer;

    /* 確保按鈕位於程式碼區塊上方 */
    z-index: 10;

    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);

    transition:
        background 0.2s,
        border-color 0.2s,
        box-shadow 0.2s;
}


/* ========================================
   Copy 按鈕 Hover
   ======================================== */

.code-block-wrapper > .copy-code-button:hover {
    background: #f3f4f6;
    border-color: #afb8c1;

    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12);
}


/* ========================================
   Copy 按鈕點擊
   ======================================== */

.code-block-wrapper > .copy-code-button:active {
    background: #e9ecef;
    box-shadow: none;
}

若未格式化文字也想要有水平捲動的效果,添加 CSS 的語法如下。

/* ========================================
   未格式化文字關掉自動換行,提供水平捲動
   ======================================== */
.wp-block-preformatted {
    /* 保留原始格式,不自動換行 */
    white-space: pre;

    /* 不強制切斷網址、路徑、指令 */
    word-break: normal;
    overflow-wrap: normal;
}

隨便找一篇文章驗證是否生效,可以到程式碼區塊已經加入 Copy 按鈕。此外,程式碼與未格式化文字的區塊,若超出螢幕寬度的部分會左右滑動,而不是把內容自動折成很多行。

以前在 Medium 只能接受平台提供的功能,現在 WordPress 覺得哪裡不好用,就自己改到順手為止。

今天的分享就到這邊,感謝收看。