WordPress 子佈景主題樣式無法載入
你的子佈景主題 style.css 之所以沒有載入,是因為 WordPress 不會自動為你 enqueue。子佈景主題的樣式表必須在子佈景主題的 functions.php 裡手動註冊。
發布於
你的子佈景主題 style.css 之所以沒有載入,是因為 WordPress 不會自動為你 enqueue。子佈景主題的樣式表必須在子佈景主題的 functions.php 裡手動註冊,而這段 enqueue 幾乎一定會犯以下兩種錯誤之一:要嘛根本沒寫,要嘛載入時沒把父佈景主題的樣式表宣告成相依項目,於是你的規則落在 cascade 裡錯誤的位置而被覆蓋掉。修好 enqueue,樣式就回來了。你八成是從 2013 年某篇教學抄來的那個老 @import 招式,是錯誤的解法。
為什麼會發生
一個典型的子佈景主題由兩個必要檔案組成:一個標頭區塊裡指名父佈景主題的 style.css,以及一個 functions.php。標頭裡的 Template: 這一行會告訴 WordPress 該從哪個父佈景主題繼承模板。這是 WordPress 唯一會自動做的事。它讀取標頭、接上模板的 fallback,然後就停了。它從來不會在前端 enqueue 你的子佈景主題 style.css。
而父佈景主題則是從它自己的 functions.php 裡 enqueue 它自己的樣式表,掛在 wp_enqueue_scripts 上。你的子佈景主題 functions.php 先執行,接著才是父佈景主題的,然後掛在那個 hook 上的所有東西才觸發。如果你的子佈景主題從來沒有為它自己的檔案呼叫 wp_enqueue_style,瀏覽器就永遠不會去請求它。頁面看起來就像未經修改的父佈景主題,因為它本來就是。
第二種失敗更隱晦。你 enqueue 了子佈景主題樣式表,它也載入了,但你的覆蓋規則毫無作用。這是載入順序的問題。當兩條規則的 specificity 相同時,最後載入的那條獲勝。如果你的子佈景主題 CSS 在父佈景主題之前載入,那麼每次平手都是父佈景主題贏。wp_enqueue_style 上的相依陣列就是用來強制順序的。
還有一件人們常搞錯的事:get_template_directory_uri() 指向的是父佈景主題資料夾,而 get_stylesheet_directory_uri() 指向的是目前啟用的(子)佈景主題資料夾。把它們對調,你就會又 enqueue 了一次父佈景主題的 style.css,卻始終沒碰到子佈景主題的。
依序修正
**第一步,先確認實際載入了什麼。**打開壞掉的頁面、檢視原始碼,搜尋你的子佈景主題資料夾名稱。WordPress 會把已 enqueue 的樣式渲染成 <link id="handle-css" href="...">——這個 id 就是你的 handle 加上 -css。如果你的子佈景主題 style.css 根本不在 <head> 裡,那就是 enqueue 沒有執行。如果它在那裡但樣式沒生效,那就是相依項目/順序的問題。這一項檢查就能告訴你,你遇到的是兩種錯誤中的哪一種。
**第二步,找出父佈景主題真正的 handle。*大多數現代佈景主題(Astra、GeneratePress、Twenty- 系列)都已經以某個特定 handle enqueue 它們自己的樣式表——astra-theme-css、generate-style-css、twenty-twenty-four-style 等等。你需要那個一字不差的字串。用 grep 搜父佈景主題,或是從檢視原始碼裡的 <link id="...-css"> 讀出來(去掉結尾的 -css)。
第三步,寫這段 enqueue。對於父佈景主題已經自己載入樣式表這種常見情況,你不要重新 enqueue 父佈景主題。你只 enqueue 子佈景主題,並把父佈景主題的 handle 列為相依項目,好讓你的樣式在它之後載入:
<?php
add_action( 'wp_enqueue_scripts', 'child_enqueue_styles', 20 );
function child_enqueue_styles() {
wp_enqueue_style(
'child-style',
get_stylesheet_directory_uri() . '/style.css',
array( 'astra-theme-css' ), // <-- the parent's REAL handle
wp_get_theme()->get( 'Version' )
);
}
如果父佈景主題沒有自己 enqueue 樣式表(某些較舊或極簡的佈景主題仰賴 @import),那就兩個都 enqueue,並讓子佈景主題相依於父佈景主題:
<?php
add_action( 'wp_enqueue_scripts', 'child_enqueue_styles' );
function child_enqueue_styles() {
wp_enqueue_style(
'parent-style',
get_template_directory_uri() . '/style.css'
);
wp_enqueue_style(
'child-style',
get_stylesheet_directory_uri() . '/style.css',
array( 'parent-style' ),
wp_get_theme()->get( 'Version' )
);
}
wp_get_theme()->get('Version') 這個引數就是你的 cache-buster。把子佈景主題 style.css 標頭裡的 Version: 這一行調高,瀏覽器就會重新抓取。省略它,你就會改了 CSS 卻發誓什麼都沒變——其實只是被快取了。
如果 functions.php 有語法錯誤,整個檔案會無聲無息地掛掉,你所有的 enqueue 都不會執行——這呈現出來的樣子跟「樣式無法載入」一模一樣。打開 WP_DEBUG,或把你的 debug.log 貼到我們的 WordPress 錯誤記錄檔解讀器,快速找出那個致命錯誤。
不該做的事
**不要用 @import。**Codex 時代的建議是把 @import url("../parenttheme/style.css"); 放在子佈景主題 style.css 的最上方。它是有效,但很慢——瀏覽器必須先解析完子佈景主題的 CSS,才能開始下載父佈景主題的 CSS,於是這兩個請求變成串列而不是並行。WordPress 官方手冊多年來一直建議別這麼做。如果你的教學叫你這樣做,那篇教學就是你樣式卡頓的元凶。
**不要把 handle 寫死成 'parent-style' 並盲目 enqueue 父佈景主題檔案。**那段有名的 Codex 範例正是這麼做的,而它對任何已經以不同 handle 註冊樣式表的佈景主題來說都是錯的。你最後會把父佈景主題 CSS 載入兩次,而你的相依項目指向一個可能根本不存在的 handle。
**不要在 functions.php 的頂層直接呼叫 wp_enqueue_style。**它必須在一個掛到 wp_enqueue_scripts 的函式裡執行。呼叫得太早,它什麼都不會做。
**不要把父佈景主題整份 functions.php 複製到子佈景主題裡。**兩者都會載入;子佈景主題的先執行。複製它會造成函式重複宣告以及一個致命錯誤。
有一點要注意:以上這些全都是針對傳統(PHP 模板)佈景主題。如果你的父佈景主題是區塊佈景主題,樣式大多透過 theme.json 和網站編輯器來運作,而 style.css 的覆蓋行為也不一樣——這種情況我會比較不信任,會直接測試而不是假設這段 enqueue 就是解法。
還是卡住?
確認子佈景主題 style.css 標頭裡的 Template: 這一行,一字不差地符合父佈景主題資料夾的名稱、且大小寫有別——不是父佈景主題的顯示名稱。然後再檢查一次檢視原始碼:handle 有出現、在父佈景主題之後載入、版本查詢字串已調高。如果 <link> 有在、最後載入、CSS 卻仍然沒生效,那就不再是 enqueue 的問題了——是 specificity 的問題,解法就得移進規則本身。