為什麼匯入網頁後 Figma 的 Auto Layout 會跑位
瀏覽器裡對齊的一排卡片,進了 Figma 有一張低了四個像素。哪一處都沒壞到能指出來。這篇講的是到底發生了什麼。
你把一個網頁匯入 Figma,圖層面板填滿了,但總覺得哪裡不對。瀏覽器裡對齊的一排卡片,現在有一張往下掉了四個像素。原本置中的導覽列,變成「大概置中」。哪一處都沒壞到能指出來,可是這個檔案已經跟你旁邊開著的截圖對不上了。
這幾乎都是 Auto Layout,被套在了不該套的地方。值得弄清楚原因,因為解法不是「關掉 Auto Layout」,而是分辨兩套版面系統何時真的一致、何時是工具在猜。
兩套本來就不該一致的版面引擎
瀏覽器用 CSS 排版。Flexbox、Grid、float、行內流、外距合併、把文字擠出自身方框的 line-height、各平台不同的次像素捨入。幾十年累積的規則,其中大多是只會碰上一次的邊界情況。
Figma 用 Auto Layout 排版。這是個小得多的系統,而且是刻意的:一個方向、一個間距、四個內距、兩個軸向的對齊,加上每個子元素的 grow 和 stretch。大致就這些。
Auto Layout 不是 flexbox 的重新實作。它像 flexbox 的程度,跟腳踏車像機車差不多。所以當轉換工具讀到 display: flex 就寫下 layoutMode: "HORIZONTAL",它其實是在下一個判斷:這兩套系統會把每個子元素放在同一個位置。有時候是對的。更多時候是「差不多對」,而那更糟。
兩者悄悄分歧的地方
下面這些看起來都像 flexbox,Auto Layout 一個也重現不了。
- flex 項目上的外距。 CSS 裡子元素可以帶自己的 margin,包括用
margin-left: auto把一組元素推到右邊。Auto Layout 只有整個 frame 共用的一個間距,根本沒有個別子元素的外距。 - space-around 與 space-evenly。 Auto Layout 有的是
SPACE_BETWEEN。另外兩種分配剩餘空間的方式不同,也沒有設定能重現它們。 - align-items: baseline。 不同字級的文字落在同一條基線上,標題和價格列很常見。Auto Layout 依方框的邊和中心對齊,不依基線。
- 帶小數的 flex-grow。
flex: 1能對應到layoutGrow: 1。flex: 2和flex: 0.5沒有對應。 - flex-wrap。 換行後的一排跟單行是完全不同的幾何,而在哪裡換行取決於擷取當下的容器寬度。
- 文字重新量測。 這一條最常絆倒工具。隨內容自適應的文字圖層是 Figma 自己量的,用 Figma 手上的字型,依 Figma 算出的字級。只要這個量測結果跟瀏覽器差一個像素,堆疊中排在後面的所有同層元素都會位移。
正因為最後這一條,這個問題常常要等你裝上缺少的字型之後才出現,或者只在別人的電腦上出現。
那為什麼轉換工具還是照套
因為一個滿是 Auto Layout frame 的檔案,看起來比滿是絕對定位矩形的檔案更像好產品。展示時好看,功能表上能多一條。而且在常見情況下——一排單純的列、間距均勻的卡片格線——它確實比較好:你縮放 frame,它會正常反應。
問題在於,不去核對就分不出「常見情況」和「差一點點」,而核對比不核對費事。
該怎麼辦
如果已經匯入了
選取看起來不對的 frame,把版面模式設成無,在 Figma 右側面板的版面區。子元素會保持目前位置,所以如果位移已經發生,這麼做是把它凍結而不是還原。因此真正有用的做法通常是重新匯入,而不是修補。
動手前先確認一件事:這個頁面用的字型,你電腦上裝了嗎?字型被替換會讓每個文字圖層重新量測,而文字寬度不對的檔案,怎麼調版面都救不回來。開啟檔案時 Figma 會告訴你缺哪些字型。
如果你正在挑工具
問它:兩套系統不一致時你怎麼處理。可能的答案只有三種,其中只有一種站得住。
- 看到 flexbox 就一律套上 Auto Layout。 快、展示好看,然後交給你一個悄悄跑位的檔案。
- 從不套用。 永遠正確,永遠沒用。你會拿到一堆絕對定位的圖層,精確但編輯起來很痛苦。
- 只在能重現原樣時才套。 既正確又有用,但要求工具真的去預測 Figma 會怎麼做,然後比對。
Snapture 怎麼判斷
Snapture 選第三種,機制一段話就說得完。
擷取的時候它已經知道每個元素在哪,因為它讀的是算繪後的頁面:每個子元素都有瀏覽器算出來的真實矩形。在套用版面之前,它會模擬 Figma 引擎處理同一個 frame 會怎麼做——內距、間距、對齊、grow 的分配——為每個子元素算出一個預測矩形。然後比對兩組結果。如果每個子元素都落在瀏覽器所放位置的 半個像素 以內,就套用版面;只要有一個沒落進去,整個 frame 就保留精確的絕對座標。
另一頭還有第二道檢查。Figma 外掛套用版面之後,會再量一次子元素,這次對的是真引擎而不是預測;如果有任何東西超出同樣的半個像素,就把這個 frame 退回擷取時的座標。這道檢查之所以存在,是因為文字圖層可能在匯入時以任何模擬都預見不到的方式被重新量測。
實際比例是這樣
把轉換工具跑在真實頁面上,就看得出它有多挑。這些是實測頁面上同一次量測的數據。
| 頁面 | 節點總數 | Auto Layout frame |
|---|---|---|
| linear.app | 2,082 | 261 |
| stripe.com | 1,592 | 99 |
| tailwindcss.com | 1,540 | 89 |
| github.com | 785 | 42 |
| developer.mozilla.org | 253 | 5 |
有意思的是 MDN 這一列。253 個節點裡只有 5 個 Auto Layout frame,看起來像工具失靈。那是工具在正常運作:MDN 的內文排版主要是文件流和 float,Auto Layout 根本不模擬這些,所以關卡幾乎全部拒絕,保留了精確座標。對那個頁面來說,這才是對的取捨。
Linear 則相反,幾乎整站都由間距均勻的 flex 列搭起來。它有 261 個 frame 真的通過了比對,而這些 frame 在 Figma 裡縮放時表現正常。
簡單說
匯入之後的 Auto Layout,只有在有東西驗證過的前提下才值得信。Flexbox 和 Auto Layout 相似到足以騙過轉換工具,又不同到足以讓你的檔案跑位,而且這個差別通常表現為幾個像素而不是明顯的損壞——恰恰是最花時間去找的那類錯誤。
如果一個工具說不出兩者不一致時它做什麼,那就當它不會去核對。
用你自己的網頁試試 5 次免費擷取,功能完整。不必綁卡,不必註冊。English · 한국어 · 日本語 · 简体中文 · 繁體中文 · Español · Português · Français · Deutsch · Русский · Italiano · Bahasa Indonesia