1. 程式人生 > >有關CSS的overflow和border-radius的那些事,你的圓角被覆蓋了嗎?

有關CSS的overflow和border-radius的那些事,你的圓角被覆蓋了嗎?

事件起因

最初是網友的一個提問,來自於我的知識星球社群:

說實話,不得不佩服這個網友的眼力,這麼小的細節都能發現。不過這也正是 FineUI 一直前進的動力,來自社群的監督和促進。

從截圖上看,貌似圓角部分被內部節點覆蓋了。換句話說:外部的圓角沒有截斷內部的元素!

由於這位網友測試的是 Cupertino 主題,圓角只有 6px,不大明顯:

換成 Le Frog 主題,這個問題就更加突出了:

分析問題

對於這個問題,有幾種可選的解決辦法:

1. 去除窗體控制元件的圓角邊框,畢竟作業系統的窗體都是直角的,這個應該也無可厚非(只不過這個改動和之前不一致,肯定會勾起部分使用者的不滿情緒)

2. 給內部節點元素也加上圓角邊框,防止內部節點的覆蓋父節點的圓角邊框

第二個方式倒是可行的方案,在瀏覽器除錯工具中嘗試如下:

由於外層節點 .f-panel 擁有 CSS 樣式類 f-corner-all:

.f-corner-all {
    border-radius: 6px;
}

這裡給內部的 .f-panel-header 增加一個樣式類 f-corner-top:

.f-corner-top {
    border-top-right-radius: 6px;
    border-top-left-radius: 6px;
}

似乎已經完美解決這個問題了。

其實不然,由於窗體內部的結構比較複雜,比如存在底部工具欄的情況(底部工具欄又可能有多個):

因此,判斷哪個元素位於最下面,是正文元素,還是某個工具欄控制元件,就是一個麻煩事。

並且還存在使用者動態顯示隱藏工具欄的情況,這就更增加了複雜度。

所以這個問題我遲遲沒有動手修改。

直到有一天,我突然發現,同是 Cupertino 主題,下拉選單的圓角邊框是正常的,不信你來看(單田芳說):

解決問題

我似乎看到了問題解決的希望,同一個主題,有個地方正常,有的地方不正常,是是否比較兩者的差異了!

經過仔細對比,問題逐步浮出水面,卻原來下拉選單有這麼個CSS屬性:

.f-menu {
    overflow: auto;
}

而窗體控制元件沒有定義 overflow 屬性,我們看下瀏覽器預設的 overflow 屬性:

原來,如果未定義 overflow 屬性,那麼節點的這個屬性預設值是 visible(有點出乎意料,我還以為是 auto 呢)。

現在好了,既然比較出差異,應用這個改變即可(為了便於觀察,我們把 border-radius 改為 12px):

問題解決!

小結

所有BUG都是如此,未解決之前看似洪水猛獸,找到根源之後卻是紙老虎。不過關鍵在於解決問題的方法和途徑,中間所歷經的過程才是最寶貴的。

You are not along

這篇文章似乎已經解決,但是到底為什麼會這麼呢?

為什麼 border-radius 和 overflow: auto(或者hidden)配合起來才好使呢?

我相信大部分我能遇到的問題,別人已經遇到過並給出解決方案,很多時候我們不能通過正確的檢索找到之前那個遇到相同問題的人。

分享在此:

<div class="progressbar">
    <div class="buffer"></div>
</div>
.progressbar { height: 5px; width: 100px; border-radius: 5px; }
.buffer { width: 25px; height: 5px; background: #999999; }

As you can see I use border-radius on the container (.progressbar), but the content (.buffer) goes 'outside' the container. I'm seeing this on Google Chrome.

Is this the expected behavior?

P.S. This isn't about how to fix it, this is about whether it should work like this.

作者遇到相同的問題:容器定義了border-radius,但是內容還是超出了容器的圓角定義。

最後,作者丟擲了這個疑惑:這不是關於如何修正它,而是關於它是否應該像這樣工作的問題?

回答更精彩:

Yes, as crazy as it sounds, it actually is. Here's why:

The default overflow for <div> elements (and most other things) is visible, and the spec says this about overflow: http://www.w3.org/TR/CSS21/visufx.html

The overflow value of the box must be something other than visible (that means autohiddenscroll and others) in order for the corners to clip its children.

最終給出的結論:

為了讓子節點不超出容器圓角邊框,容器的overflow屬性必須是除visible之外的其他值(比如 auto, hidden, scroll...)