首頁圖片正常,文章搬進子目錄後卻不見了;檔名沒變,上傳的圖也還在。這時先看瀏覽器把圖片網址算成什麼。相同的 src="images/cover.svg",放在不同頁面位置,可能請求完全不同的目錄。
本文先處理相對 URL 的起點:HTML 圖片、CSS 背景與 base 元素各自從哪裡算。若完整請求路徑已經正確,才接著查檔案是否存在、權限或其他回應問題,不必第一步就修改伺服器重寫規則。
先把兩個網址並排
開啟開發者工具的 Network,重新整理頁面,找到失敗圖片。記下完整的 Request URL,再抄下 HTML 裡的 src。第一個是瀏覽器真的要拿的地址,第二個只是你寫進頁面的文字;兩者不一定長得一樣。
例如頁面是 https://example.com/guides/start/index.html,圖片寫 images/cover.svg,瀏覽器會往 /guides/start/images/cover.svg 找。若檔案實際放在網站根目錄的 /images/cover.svg,兩個位置就對不上。
在 Console 可以選到圖片後檢視:
const image = document.querySelector('.article-cover');
({
written: image.getAttribute('src'),
resolved: image.src,
pageBase: document.baseURI,
selected: image.currentSrc
})
將 class 換成目標圖片的選擇器。getAttribute 保留原本寫法,src 顯示解析後地址;有 srcset 時,也看 currentSrc,避免查了 src,實際下載卻是另一個候選圖。數值先記錄,再到 Network 核對同一個請求。
開頭斜線與上一層,是不同選擇
images/cover.svg 從目前基準目錄往下找;../images/cover.svg 先上一層;/images/cover.svg 則從解析基準 URL 的來源(origin)根路徑開始。不要在根目錄案例成功後,直接認定它適合部署在子路徑的網站。
如果整個網站放在 https://example.com/shop/,前面加斜線的 /images/cover.svg 會從該來源的根路徑開始,不會自動保留 shop。此時若圖片位於 /shop/images/cover.svg,要依實際部署結構產生正確路徑。很多建置工具另有資產基準設定,先查自己使用的工具,別用全站字串替換猜路徑。
const base = 'https://example.com/guides/start/index.html';
new URL('images/cover.svg', base).href;
// https://example.com/guides/start/images/cover.svg
new URL('../images/cover.svg', base).href;
// https://example.com/guides/images/cover.svg
new URL('/images/cover.svg', base).href;
// https://example.com/images/cover.svg
這個計算可以先確認方向,真正圖片是否存在仍要發出請求。在示例頁裡,圖檔放在 /assets/cover.svg;子目錄文章用 assets/cover.svg 會請求不存在的子目錄,改成 /assets/cover.svg 才拿到那個檔案。

CSS 背景從 CSS 檔的位置算
HTML 圖片修好,背景圖卻仍失效時,別把兩種引用一起套同一個規則。外部 CSS 裡的相對 url() 通常以樣式表 URL 為起點。假設 CSS 在 /styles/theme.css,其中寫 url("assets/cover.svg"),請求會往 /styles/assets/cover.svg 找,不是從文章目錄算。
若檔案在 /assets/cover.svg,這個目錄結構可寫成 url("../assets/cover.svg")。先在 Network 找到背景圖的失敗請求,再檢視是哪一個樣式表產生它。WordPress 主題、編譯後 CSS 與 CDN 資產的位置可能不同,不能只按本機原始碼資料夾推論。
內嵌 style 與外部 CSS 的來源也要分開確認。最有效的做法是看瀏覽器發出的完整地址,再回找那一行 CSS;只看畫面中沒有圖片,無法判斷是哪個起點算錯。
base 不只影響那一張圖
根路徑引用也要看解析基準的來源。若base指向另一個網域,/assets/cover.svg就會使用那個基準的協定、主機與連接埠;它不一定仍在頁面原本的網域。先查看document.baseURI,再核對完整請求網址。
HTML 的 <base href="..."> 會指定文件的 URL 基準,影響相對引用。發現圖片地址與你預想不同時,看 head 是否有 base,再核對 document.baseURI。不要為修一張圖片就直接新增 base,因為其他相對連結、表單等也可能跟著改變方向。
頁面原本沒有 base,就先修錯誤圖片引用;頁面確實依賴 base,則儲存原值,列出受影響的相對網址,再在測試頁比較。尤其不要把 HTML base 當成外部 CSS 目錄的替代設定,HTML 的解析基準與外部 CSS 的位置要各自判斷。
網址最後的斜線也會改變目錄
https://example.com/guides/start/ 的 start 是目錄;https://example.com/guides/start 在解析相對引用時,最後一段則可被當作檔案部分。對同一個 cover.svg,前者會得到 /guides/start/cover.svg,後者會得到 /guides/cover.svg。先看瀏覽器最後停在哪個 URL,包括轉址後有沒有斜線。
路由讓兩種網址都回同一份 HTML,不代表相對資產解析也相同。需要維持兩種入口時,資產路徑應按自己的部署基準統一產生;需要統一頁面網址時,則另由站點路由安排,不要在圖片教程裡一併更改正式轉址。
修正後至少檢查首頁、一個分類頁與一個深層文章頁。確認圖片確實下載成功,顯示的內容也正確,避免剛好收到另一個同名檔。保留原引用與本次修改,出問題時只回復這幾行。
完整路徑對上後仍404,可再查Windows與Linux檔名大小寫差異;那篇處理伺服器找檔條件,本文處理瀏覽器從哪個基準組出網址。兩個問題先分開,修法才不會互相混淆。
把失敗原因寫成可修的一行
交給模板維護者時,附上三項就很有用:頁面的最終網址、原引用文字、Network 真正請求的完整網址。例如「文章在 /nested/guide/index.html,引用 assets/cover.svg,實際去 /nested/guide/assets/cover.svg;圖檔在 /assets/cover.svg」。這比只說「圖片404」更容易安排修正。
若它是共用頁首的Logo,先查那一行由哪個模板產生,不要逐篇文章重貼圖片。如果它來自文章編輯器,則檢視內容裡儲存的是相對路徑還是完整媒體URL。兩種來源需要改的地方不同,先找到輸出位置,才能避免下一次儲存又把修正覆蓋。
網站有 CDN 或另外的資源網域時,保留完整的協定與主機一起比較。/assets/cover.svg 使用解析基準 URL 的來源;https://static.example.com/assets/cover.svg 則請求指定的資源主機。不要在不清楚資源歸屬時把所有主機名稱換成新網域,否則原本正常的外部素材也會被改壞。
網址中的查詢字串可能用於版本或圖片處理,但不會替你補回算錯的目錄。例如在失敗路徑後面加 ?v=2,仍然請求那個錯誤位置。先對上路徑,再按網站的快取方法更新版本;反覆加亂數只會把問題藏在更多請求裡。
遇到中文或空白檔名時,不要靠目視把百分比編碼改回中文字就宣稱地址不一致。複製完整請求URL,讓瀏覽器直接開啟,再與伺服器實際檔案或媒體紀錄核對。編碼、檔名及相對起點是不同條件,這篇案例只更動起點,沒有藉此判斷所有404原因。
修好一個入口後,檢查同一張圖在不同深度的頁面。例如首頁、/guides/列表、/guides/start/文章;若只有首頁正常,通常還需要檢視共用引用如何產生。不要用CSS把失敗圖片隱藏,否則內容看起來沒有破圖,實際上仍缺了訪客要看的資訊。
在預覽確認所有入口後,再把精確引用改動交到正式流程。回復時還原原本的HTML或CSS引用,不需要刪除圖檔,更不需要一併改動整個網站目錄。保留對照紀錄,下次搬站就能先核對這些資產基準。

評論0