1. 問題全貌 (The Problem)
現象: 滑動橫向捲動的畫廊(Scroll Snap)時:
- 靜止時:圖片四周圓角完美。
- 滑動時:圖片的圓角突然消失,邊緣變成直角。
- 底部異常:即便修復了頂部,底部兩個角依然在滑動時呈現銳利的直角。
2. 關鍵洞察:視覺與邏輯的錯位 (User Insights)
在修復過程中,開發者(用戶)敏銳地指出了解決問題的兩個核心邏輯,這成為了破局的關鍵:
2.1 “隱形的直角容器” 理論
- 現象:靜止時我們看到圓角,是因為我們被“騙”了。實際上,包裹圖片的父容器(占位符)一直都是直角的。
- 原因:靜止時,圖片本身的
border-radius生效,而容器直角部分與背景色(暗色或白色)融為一體,導致視覺上無法感知到容器直角的存在。 - 破綻:一旦滑動開始,這個“隱形”的直角容器移動到了下一張圖片的位置,或者背景發生變化,那個原本隱形的直角區域就暴露了出來,遮擋或穿透了圖片的圓角。
2.2 “視覺圓角 vs 圖片圓角” 理論
- 圖片圓角 (Logical Radius):代碼通常只給每張單獨的圖片設置圓角。這意味著,只有圖片的四個物理頂點是圓的。
- 視覺圓角 (Visual Radius):但在畫廊滑動(Carousel)這種交互中,用戶盯著看的是那個不動的“相框”窗口。
- 衝突:當圖片滑動時,圖片的“腰部”(中間直邊部分)會經過“相框”的角落。如果相框本身不具備強制圓角裁剪能力,那麼圖片腰部的直邊就會填滿相框的角落。
- 結論:我們需要的不是給圖片加圓角,而是要給這個**“視覺窗口”(相框)**加圓角。無論內容怎麼動,窗口永遠保持圓角裁剪。
3. 修復歷程
3.1 第一階段:視口裁剪 (Clip-Path)
基於上述“視覺圓角”理論,我們不再糾結於圖片本身,而是對滾動容器應用幾何裁剪:
- 操作:
clip-path: inset(0 round 1rem)。 - 效果:這強制規定了“相框”必須是圓角的。無論圖片怎麼滑,超出圓角邊界的內容(包括圖片腰部的直角)都會被切掉。
- 遺留問題:雖然大框架對了,但細節上發現頂部左右兩個角只是“微微圓角”,甚至不夠圓,顯得不夠精緻,與靜止時不一致。
3.2 第二階段:移除內邊距 (Padding Removal)
(Commit: a0ee566…)
在解決了基本的裁剪思路後,開發者發現 clip-path 裁剪出的圓角與預期不符。
- 發現:滾動容器原本設置了
padding(內邊距)。 - 衝突:
padding導致clip-path作用的邊界與圖片的實際內容邊界之間存在空隙。圖片實際上是在一個比它自己稍大的盒子裡滑動,這使得clip-path裁剪的圓角並沒有緊貼著圖片的邊緣,導致看起來“只是微微圓角,而非真正的全圓角”。 - 修正:移除容器的
padding,讓clip-path邊界與圖片內容邊界物理重合,確保圓角裁剪的弧度完全等同於設計值(如 1rem)。
3.3 第三階段:幾何結構歸位 (Structural Decoupling)
解決了頂部的微小瑕疵後,底部直角依然頑固存在。這回到了“隱形容器”的高度問題。
用戶發現:有圖片說明的,底部變直角;清空說明的,底部變圓角。
幾何錯位分析:
- 滾動容器封裝了
[ 圖片 + 文字 ]。 - 容器高度 = 圖片 + 文字。
clip-path的圓角裁剪作用於容器的最底部(文字下方)。- 相對於圖片底部而言,該位置處於容器的中間(直邊區域)。
- 因此,圖片底部邊緣在滑動時,經過的是容器的直邊區域,而非圓角區域。
最終解決方案: 將說明文字從滾動容器中物理剝離。
- DOM 重構:滾動容器內只保留圖片,使其高度嚴格等於圖片高度。
- 結果:容器的底部圓角裁剪線現在完美貼合圖片底部。
- 動態注入:使用 JS 將對應的說明文字動態渲染到容器下方的獨立區域。
4. 總結 (Summary)
本次修復驗證了三個重要的前端架構原則:
- 窗口理論 (The Viewport Theory):在做滑動視圖時,圓角應該屬於視口(窗口),而不是內容。內容在動,窗口不動,只有這樣才能保證視覺的一致性。
- 邊界一致性 (Boundary Alignment):
clip-path或裁剪容器不能有padding,除非你計算得極其精確。最穩健的做法是讓裁剪容器與內容尺寸物理重合 (padding: 0)。 - 物理純淨性 (Physical Purity):參與幾何裁剪的容器,其內部應該純淨無雜質。任何額外的元素(如文字)都會改變容器的物理邊界,導致裁剪邏輯與視覺預期不符。
評論