Wordpress

區塊主題子主題怎麼建?讓客製化不被更新洗掉的完整做法

多數人一聽到「子主題」,直覺反應是「不就是那個用來擋主題更新洗掉客製化的資料夾」。這句話放在傳統佈景主題上沒錯,套到區塊主題卻只對了一半,子主題要保護的東西沒有變,保護的做法卻整套換了。

如果你在 Twenty Twenty-Four 這類區塊主題上,還沿用傳統子主題那套「在 functions.php 手動掛樣式表」的寫法,很可能會發現樣式根本沒套用,或是掛了半天卻什麼事都沒發生,因為區塊主題的外觀,大多改由 theme.json 這份設定檔管理,不再靠一行一行的 PHP 程式碼載入。區塊主題子主題(Block Theme Child Theme)沿用的仍是「繼承父主題全部功能與外觀,只覆寫自己想改的部分」這個大原則,父主題更新也一樣不會動到子主題檔案,只是覆寫的媒介從程式邏輯換成了設定檔與範本檔案。WordPress 官方也已經明確表示,區塊主題子主題現在是完全支援的正式功能,不是還在試驗階段的半成品。

搞懂這套新機制,你才不會白忙一場,拿舊方法在新架構上敲半天結果一行都沒生效,也不會反過來多做一步,明明後台的網站編輯器就存得住的改動,卻堅持另外開一個子主題。傳統子主題跟區塊主題的覆寫機制放在一起比對,才看得出來換了哪一套做法。

區塊主題子主題是什麼?跟傳統子主題差在覆寫方式

子主題的官方定義很單純,它會繼承父主題的全部功能與外觀,你只需要針對想調整的地方另外寫覆寫檔案,父主題本身的檔案完全不用動,之後父主題升級版本,也不會影響到你寫在子主題裡的東西。這個原則不論主題類型都通用,差別在於「覆寫」實際指的是什麼。

傳統子主題靠 functions.php 載入樣式表

傳統(經典)主題的子主題機制,核心邏輯放在 functions.php。子主題的 functions.php 不會取代父主題的 functions.php,兩者都會被載入,而且子主題會先於父主題執行。這代表你可以在子主題的 functions.php 裡掛入自訂函式、修改鉤子行為,同時父主題原本的功能照樣運作,不會互相排斥。

樣式的部分就沒那麼自動了。多數傳統主題不會自己把子主題的 style.css 掛進頁面,你得在子主題 functions.php 裡用 wp_enqueue_style() 手動把父子兩份樣式表都排進去。如果父主題本身完全沒有 enqueue 任何樣式表,更要記得補上這一步,不然子主題的外觀調整整份都不會生效,必要時還得搭配 get_parent_theme_file_uri() 一併掛上父主題的樣式表。這一整套「寫 PHP 邏輯、控制載入順序」的做法,就是傳統子主題最典型的操作方式。

區塊主題子主題改用範本檔案與 theme.json 覆寫

換到區塊主題,樣式跟版面的載入方式整個不一樣。樣式的部分改由 theme.json 這份設定檔統一管理,你不必再手動 enqueue 樣式表,區塊主題原本的樣式處理大多本來就透過 theme.json 完成,這一步在區塊主題上通常用不到。

頁面版型的部分,則改用 HTML 範本檔案取代原本寫在 PHP 裡的邏輯判斷。覆寫的做法也變得很直覺,只要在子主題裡放一個跟父主題同名的檔案,不論是範本、範本部件(如頁首、頁尾),或是圖案(pattern),WordPress 都會優先讀取子主題那一份;圖案還多一個條件,子主題檔案的 registered Slug 要跟父主題完全一致,系統才認得出這是同一個東西的覆寫版本。

傳統子主題靠 functions.php 手動載入樣式表,區塊主題子主題改用 theme.json 設定檔與 HTML 範本覆寫,兩者都繼承父主題、更新不動子主題
保護的目標沒變,換掉的只是覆寫媒介:傳統靠 PHP 邏輯與手動 enqueue,區塊主題改用 theme.json 與同名範本檔案。

客製化寫進主題檔案,更新就會整批覆蓋掉

主題更新的本質,是整個主題資料夾被換成新版本,這句話聽起來理所當然,卻是搞懂什麼時候真的需要子主題的關鍵。

存進資料庫的改動,主題更新影響不到

不是所有客製化都要靠子主題保護。透過後台「網站編輯器(Site Editor)」做的顏色、字體、版面、範本調整,實際存放的位置是資料庫,不是主題資料夾裡的檔案。主題更新只會換掉檔案系統裡的內容,資料庫裡的紀錄根本不會被動到,這些客製化理論上不受影響。

官方文件把區塊主題呈現前台內容的順序,拆成四個層次,最底層是 WordPress 本身內建的預設 theme.json,再上一層是父主題,接著是子主題,最上層則是使用者在網站編輯器裡做的客製化。這第四層被形容成有點像子主題的「孫主題」,兩者最大的差別就在於,使用者客製化這一層存在資料庫,不是檔案系統,天生就不受主題更新影響。搞懂這四層的順序,你才知道自己現在動的東西,會不會被下一次更新蓋掉。

區塊主題前台呈現由下而上分四層:WordPress 內建預設、父主題、子主題、使用者客製化,上層覆寫下層
上層覆寫下層;最上層的使用者客製化存在資料庫,天生不受主題更新影響。

直接改到 theme.json 或範本檔案的改動,主題更新才會洗掉

反過來說,真正會被主題更新覆蓋的,是直接編輯 theme.json、HTML 範本、CSS、PHP 或 JS 檔案本身,例如打開程式碼編輯器,直接改父主題資料夾裡的檔案內容。這些改動完全沒有保護機制,下次更新整份主題資料夾被換掉的那一刻,你改的東西就跟著消失。

還有一種情況,連網站編輯器都幫不上忙,theme.json 裡有些比較進階的設定組合,介面上根本沒有對應的按鈕可以移除或調整。遇到這種設定,唯一的解法就是自己建一份子主題的 theme.json,直接在裡面覆寫掉那個欄位。換句話說,子主題不是為了保險而多做的一步,而是遇到這兩種情況時唯一真正有效的做法。

子主題只靠兩個檔案就能啟用

一個能被 WordPress 辨識、可以啟用的最小子主題,其實比多數人想像的簡單。

style.css 檔頭的 Template 欄位要精確對到父主題資料夾名

子主題資料夾要放在 wp-content/themes/ 底下,資料夾名建議用全小寫加連字號的 kebab-case 命名(例如 grand-sunrise),避免空格與大寫字母造成的相容性問題。必要的檔案只有一個,style.css,而且檔頭要多寫一個一般主題沒有的欄位,Template

這個欄位的值必須 100% 對應父主題資料夾的名稱,而且是相對於 wp-content/themes 這層路徑,大小寫與連字號都要完全一致。官方文件舉的例子很具體,子主題若叫做 Grand Sunrise,父主題是內建的 Twenty Twenty-Four(資料夾為 wp-content/themes/twentytwentyfour),子主題 style.css 檔頭就要寫 Theme Name: Grand SunriseTemplate: twentytwentyfour。這裡是整個建置過程最容易出錯的地方,Template 值只要打錯一個字元,WordPress 就會找不到對應的父主題,子主題直接壞掉,連啟用畫面都會出現錯誤提示。

子主題 theme.json 只填要覆寫的欄位就好

建議同時放一份 theme.json,即使暫時留空或只填幾個欄位也沒關係。很多人以為子主題的 theme.json 要整份複製父主題的內容才算完整,其實不必,子主題只需要放你真的想覆寫的那幾個欄位,其餘設定會自動沿用父主題與 WordPress 內建的預設值。

theme.json 的規格對 core、theme、user 這三個來源都採同一套格式,主題本來就可以用自己的 theme.json 覆寫 WordPress 內建的預設值,這套機制子主題一樣適用。目前最新的規格是 version 3,從 WordPress 6.6 開始導入;舊版本仍然向下相容,但新功能之後只會開發在最新版本上,建議子主題的 theme.json 開頭就直接標明 "version": 3,免得日後又要回頭補。裝好 style.csstheme.json 之後,記得到後台「外觀 > 佈景主題」把子主題實際啟用,子主題才會真正生效。

子主題 theme.json 覆寫的是整個欄位,不是逐項合併

子主題 theme.json 跟父主題合併時,有一個幾乎沒人一開始就搞懂、卻最容易讓人白忙一場的機制。

色票與字級這類陣列設定會被整個換掉

子主題 theme.json 跟父主題 theme.json 合併時,規則其實分兩種。單一屬性值,像是某個顏色的預設值、某個間距的數字,可以只改這一項,子主題優先,其餘沒動到的部分照樣繼承父主題。但陣列型的設定,像是色票、字級清單、漸層、間距清單,合併方式卻是整批取代,不是逐項疊加。

具體來說,如果父主題色票原本有 10 種顏色,子主題 theme.json 只加了 1 種新顏色,結果不會變成 11 種,而是整份色票只剩下子主題那 1 種,父主題原本的 10 種色票全部消失,連在編輯器的色票選單都看不到了。字級、漸層、間距清單也是同一套合併規則。這個行為是 WordPress 團隊設計如此,不是程式錯誤,不少開發者第一次踩到都以為是自己哪裡設定錯了。

theme.json 合併分兩種,單一屬性值逐項覆寫,色票等陣列設定整批取代;父主題 10 色加子主題 1 色只剩 1 色
陣列型設定不是相加:父主題 10 色加子主題 1 色,結果整份只剩子主題那 1 色。

用 wp_theme_json_data_theme 篩選器合併父主題色票

遇到這個問題,正解不是把父主題色票整份複製貼到子主題,那樣做,父主題色票之後一改,子主題又得手動同步一次,完全違背子主題省事的初衷。WordPress 提供了一個叫 wp_theme_json_data_theme 的篩選器,可以在子主題的 functions.php 裡動態合併父子兩份色票,不用手動維護兩份清單。

這個篩選器的用途,是篩選主題提供的全域樣式與設定資料,回傳一個 WP_Theme_JSON_Data 物件供讀取與更新。實際用法是在子主題 functions.php 裡,用 PHP 的 array_merge() 把父主題原本的色票陣列跟子主題新加的顏色合併起來,再透過這個物件的方法把合併結果寫回去。這樣一來,父主題色票增減,子主題都會自動跟著更新,不必每次手動對照。

覆寫範本要對到同一個檔案路徑與名稱

範本(頁面版型)與範本部件(像頁首、頁尾)的覆寫規則,原理其實很單純,檔案路徑與檔名要跟父主題完全對上,WordPress 才知道這是要蓋掉哪一個。

範本載入順序,子主題永遠排在父主題前面

WordPress 尋找範本檔案時有固定的優先順序,子主題的 HTML 檔案排第一,接著是子主題的 PHP 檔案,再來才輪到父主題的 HTML 檔案,最後是父主題的 PHP 檔案。這套順序連混合主題(部分頁面用傳統 PHP 模板、部分用區塊範本)都適用,子主題只要放一個對應的 HTML 檔案,一樣蓋得掉父主題的 PHP 模板。

舉一個實際的例子,假設父主題是混合主題,同時有 index.phpsingle.phppage.phpheader.php 這些 PHP 檔案,也有 /templates/404.html/parts/header.html 這些區塊範本;子主題只放了 /templates/index.htmlsingle.html,以及 /parts/header.html 三個檔案。實際運作時,WordPress 使用的組合會是,page.php 沿用父主題(因為子主題沒放對應檔案覆寫)、index.htmlsingle.html 用子主題那份、404.html 沿用父主題那份、頁首部件則用子主題的 header.html。子主題也不是只能覆寫父主題既有的範本,新增一個父主題沒有的範本、部件或圖案,同樣是允許的做法。

範本載入優先順序為子主題 HTML、子主題 PHP、父主題 HTML、父主題 PHP,放同名檔案由子主題覆寫、沒放則沿用父主題
放一個同名檔案,子主題就蓋掉父主題那份;沒放對應檔案的範本則沿用父主題。

樣式變化檔案要用相同檔名覆寫

「樣式變化(style variations)」是後台可以直接切換的整套配色與字體組合,子主題也覆寫得到。做法是在子主題的 styles/ 資料夾裡,放一個跟父主題檔名完全相同的 JSON 檔案。子主題啟用時,WordPress 會同時掃描子主題與父主題的 styles/ 資料夾,掃到的每一份檔案都會被註冊成一個可選的樣式變化。

如果子主題跟父主題出現同名的變化檔案,子主題那一份會蓋掉父主題的版本;子主題本身也可以新增父主題沒有的全新樣式變化。要注意的是,子主題目前沒有辦法移除父主題某一個樣式變化,只能用覆寫的方式替換內容,這一點跟前面範本覆寫的規則是同一套邏輯。

拿掉圖案與區塊樣式要靠取消註冊函式

還有一種情境,範本覆寫跟 theme.json 都解決不了,子主題會直接繼承父主題註冊過的區塊圖案(pattern),以及自訂區塊樣式(block style,例如編輯器選單裡可以選的「圓角圖片」這種樣式)。但沒有辦法只靠 theme.json 把它們拿掉,理由跟前面範本沒辦法真正刪除是同一套道理,子主題的覆寫機制天生只做得到蓋掉,做不到移除。

真的想拿掉某個圖案或區塊樣式,要在子主題 functions.php 裡明確呼叫取消註冊的函式,unregister_block_pattern() 可以取消註冊某個圖案,unregister_block_style() 則用來取消註冊某個自訂區塊樣式。theme.json 裡列出的範本與範本部件也是同樣道理,就算你在子主題 theme.json 裡把它們從清單拿掉,並不會真的停用,移除機制本來就跟覆寫機制是分開設計的兩件事。

子主題刪不掉父主題範本,新設定也擋不住

子主題建好之後,父主題還是會持續更新,你會遇到父主題新增範本、砍掉範本這兩種情況,因應方式完全不一樣。

子主題想拿掉父主題範本,其實做不到只能覆蓋

先破解一個常見的期待,子主題沒辦法真正刪除父主題已經有的某個範本,就算你在子主題 theme.json 裡把它從清單拿掉,那個範本一樣不會停用。範本與範本部件雖然可以列在 theme.json 裡,但清單只是列出有哪些,不是開關,拿掉清單裡的項目並不會讓範本真的消失。

想讓某個範本的內容變空白,或是改成導向別的頁面,唯一能做的是用覆蓋的方式替換內容,放一個同名檔案,把內容改成你要的樣子。這跟前面範本覆寫用的是同一條規則,子主題可以覆寫任何範本、部件、圖案,做法就是放同名檔案,差別只在於這次覆寫的目的是清空而不是調整。

父主題加新設定,子主題沒覆寫的話照樣吃到

另一個容易被忽略的邊界情況是,子主題 theme.json 只保護已經覆寫過的那些欄位。假設父主題與子主題原本都沒有設定自訂漸層,之後父主題在某次更新裡新增了一組自訂漸層,因為子主題沒有針對這個欄位寫過覆寫值,子主題就會直接繼承父主題新加的這組漸層。

這提醒你子主題不是萬能防護罩,沒覆寫到的欄位,父主題更新的內容還是會生效。這個結論跟前面 theme.json 採 core、theme、user 三層同規格、主題可以覆寫 core 預設值的原則,其實是同一個推論方向,沒有人主動覆寫的那一層,就會直接沿用上一層的值,不論那個上一層是 WordPress 內建預設,還是父主題新增的設定。

用 Create Block Theme 外掛,不寫程式碼也能建子主題

前面都是手動寫檔案的做法,如果你不想自己建資料夾、寫 style.css,WordPress 官方外掛目錄裡有一支專門為這個情境設計的工具。

存檔、建子主題、匯出 zip,是三個不同動作

Create Block Theme 是 WordPress.org 官方外掛目錄收錄、由 WordPress 核心貢獻者維護的開放原始碼外掛,目前版本要求 WordPress 6.8 以上才能安裝。裝好之後,操作路徑在後台「外觀 > Create Block Theme」,或是網站編輯器右上角的專屬圖示,點開就能看到幾個功能,建立空白主題、以目前啟用的主題為基礎建立新主題、建立目前父主題的子主題、建立新的樣式變化,以及把你在編輯器裡做的樣式改動存回目前的主題。

這幾個按鈕最容易搞混,一定要分清楚各自做什麼。「Save Changes」是把你在網站編輯器裡做的改動,存回目前啟用中的主題本身,等於把資料庫裡的客製化寫回主題檔案;「Create Child Theme」是另外建立一個以目前主題為父主題的全新子主題,把客製化包進這個新子主題裡,父主題本身不受影響;「Export Zip」則是把(子)主題打包成可安裝的 zip 檔案,方便搬到別的網站或留作備份。三個按鈕是三個獨立的動作,點錯地方,改動就會存到不是你原本想要的地方。

Create Block Theme 外掛三個動作:Save Changes 存回目前主題、Create Child Theme 另建子主題、Export Zip 打包成 zip
三個按鈕各做各的:存回目前主題、另建子主題、打包匯出,點錯地方改動就會存錯位置。

匯出後的子主題資料夾,已經包含要覆寫的檔案

外掛匯出的子主題,不需要你再手動整理就能直接安裝到別的網站使用。它會自動把範本裡用到的所有圖片,複製進主題自己的 assets 資料夾,不會漏掉外部圖片路徑;也會確保範本與圖案裡使用的區塊標記是可以匯出的格式,以及大部分字串都是可翻譯的格式,避免搬到別的站台之後才發現東西讀不到或無法翻譯。

官方也提醒,這支外掛比較偏開發用途的工具,可以把它想成是 WordPress 的開發模式,透過它做的改動,有可能永久改變網站或主題內容,操作前最好先確認自己在做什麼,尤其是「Save Changes」這個直接寫回目前主題的動作,執行前最好先備份。整體來說,手動建置適合想搞懂機制、需要精細控制的情境,這支外掛則適合想快速上手、不想碰程式碼的情境,兩條路徑最後做出來的子主題,其實是同一套東西。

傳統子主題跟區塊主題子主題,保護的目標從來沒變,讓你的客製化撐過主題更新,還能繼續生效。差別只在於覆寫的媒介換了,一邊靠 PHP 邏輯與手動 enqueue,一邊靠範本檔案與 theme.json 裡的欄位。

真正決定你需不需要子主題的,從來不是這個主題新不新,而是你打算怎麼改。透過網站編輯器做的顏色、字體、版面調整,存進資料庫,主題更新動不到;一旦你直接打開程式碼編輯器改 theme.json、範本或 PHP 檔案,子主題就是唯一能讓改動撐過下一次更新的做法。搞懂這條分界線,你才知道自己現在做的事,該交給網站編輯器,還是該先建一個子主題再動手。

常見問答

本區問答由 AI 依文章內容自動整理,僅供快速參考,正式內容仍以全文為準。

區塊主題子主題要怎麼啟用?

子主題只需要兩個檔案,一份 style.css,檔頭要加 Template 欄位、值要對到父主題資料夾名稱;另一份 theme.json 只填想覆寫的欄位即可,其餘沿用父主題。裝好後記得到「外觀 > 佈景主題」實際啟用,子主題才會生效。

子主題新增一個顏色,其他色票怎麼不見了?

theme.json 的陣列型設定(像色票、字級清單)合併時是整批取代,不是逐項疊加;子主題只要新增一種顏色,父主題原本的色票就會整份被換掉,只剩子主題新增的那幾筆,不會保留父主題原有的項目。

子主題可以把父主題的範本整個刪除嗎?

子主題沒辦法真正刪除父主題已有的範本,就算在 theme.json 清單裡拿掉該項目,範本本身也不會停用;唯一做法是放一個同名檔案覆寫內容,把它清空或導向別的頁面,達到你要的效果。

用網站編輯器改的設定,主題更新會洗掉嗎?

用網站編輯器做的顏色、字體、版面等調整,實際存放在資料庫而不是主題資料夾裡的檔案,主題更新只會替換檔案系統的內容,不會動到資料庫,所以這類客製化不受主題更新影響。

Create Block Theme 外掛可以做什麼?

Create Block Theme 是 WordPress 官方外掛目錄收錄的工具,不用寫程式碼就能建立空白主題、以目前主題建立子主題,或把網站編輯器裡做的樣式改動存回主題,也能把(子)主題打包成 zip 檔案。

資料來源
  1. Child Themes – Theme Handbook — WordPress
  2. Global Settings & Styles (theme.json) – Block Editor Handbook — WordPress
  3. Style Variations – Theme Handbook — WordPress
  4. wp_theme_json_data_theme – Hook Reference — WordPress
  5. Create Block Theme — WordPress