文章出處

前言

 當CSS3推出border-radius屬性時我們是那么欣喜若狂啊,一想到終于不用再添加額外元素來模擬圓角了,但發現border-radius還分水平半徑和垂直半徑,然后又發現border-top-left/right-radius的水平半徑之和大于元素寬度時,實際值會按比例分配元素寬度時,不禁會問"我真的懂border嗎?"。本系列將稍微深入探討一下那個貌似沒什么好玩的border!
《CSS魔法堂:重拾Border之——解構Border》
《CSS魔法堂:重拾Border之——圖片作邊框》
《CSS魔法堂:重拾Border之——不僅僅是圓角》
《CSS魔法堂:重拾Border之——更廣闊的遐想》

圓角進化論

 當設計稿上出現圓角按鈕/標簽頁時,我們會如何應對呢?CSS3到來之前最廣為人知的應該就是"滑動門"(sliding door)實現方式了。

滑動門實現法

<style type="text/css">
ul{padding:0;margin:0;}
li{padding:0;margin:0;list-style:none;}
a{margin:0;text-decoration:none;}

/*clearfix*/
.nav{
  *zoom: 1;
}
.nav::after{
  content: ".";
  display: block;
  clear: both;
  line-height: 0;
  visibility: hidden;
}
/*滑動門實現Tab*/
.nav .nav-item{
  float: left;
  margin-right: 5px;
}
.nav .nav-item a{
  display: inline-block;
  background: url("./background.jpg") no-repeat;
  color:#333;
  font-size: 12px;
  line-height: 2;
}
.nav .nav-item a span{
  display: inline-block;
  background: url("./background.jpg") no-repeat right top;
  padding: 0 10px 0 5px;
  margin-left: 5px;
}

.nav .nav-item a:hover{
  background: url("./background.jpg") no-repeat left -30px;
}
.nav .nav-item a:hover span{
  background: url("./background.jpg") no-repeat right -30px;
}
</style>
<ul class="nav">
  <li class="nav-item"><a href="javascript:void 0"><span>首頁</span></a></li>
  <li class="nav-item"><a href="javascript:void 0"><span>PDCA檢驗單查詢</span></a></li>
  <li class="nav-item"><a href="javascript:void 0"><span>成品通用標準審核</span></a></li>
</ul>

border-radius實現法

border-top-left-radius: [<length>|<percentage>]{1,2}
border-top-right-radius: [<length>|<percentage>]{1,2}
border-bottom-left-radius: [<length>|<percentage>]{1,2}
border-bottom-right-radius: [<length>|<percentage>]{1,2}
設置左上/右上/左下/右下角水平和垂直橢圓半徑
<length>:以帶單位的絕對值作為半徑;
<percentage>:以對應border box的尺寸(不是border-width)為參考系,設置半徑;
注意:結果值為0(默認值)時,為直角邊框
border-radius: [<length>|<percentage>]{1,4} [/[<length>|<percentage>]{1,4}]?:一次過設置4個角的橢圓半徑

 從上圖我們可以看到4個角分別對應4個獨立的橢圓形,而圓角正是4分之1個橢圓。
擼代碼!

<style type="text/css">
/*clearfix*/
.nav3{
  *zoom: 1;
}
.nav3::after{
  content: ".";
  display: block;
  clear: both;
  line-height: 0;
  visibility: hidden;
}
/*border-radius實現Tab*/
.nav3 .nav-item3{
  float: left;
  margin-right: 5px;
}
.nav3 .nav-item3 a{
  font-size: 12px;
  line-height: 2;

  display: inline-block;
  background: #0ac;
  padding: 0 10px;
  border: 1px solid #eee;
  border-radius: 8px 8px 0 0;
}
.nav3 .nav-item3 a:hover{
  background: #eef;
}
</style>
<ul class="nav3">
  <li class="nav-item3"><a href="javascript:void 0">首頁</a></li>
  <li class="nav-item3"><a href="javascript:void 0">PDCA檢驗單查詢</a></li>
  <li class="nav-item3"><a href="javascript:void 0">成品通用標準審核</a></li>
</ul>

圓角的何止是border box啊


 上圖的content box變成橢圓形了,而且content box中的文字好像飄到content box外面。但確實是content box變為橢圓形還是說僅僅是背景色是如此而已呢?讓我們添加overflow:hidden看看效果吧

 看來border-radius確實影響到content box了。其實border-radius將會影響到box model中的所有box。當我們通過border-radius設置border box的橢圓半徑后,CSS渲染引擎會根據公式自動計算出margin/padding/content box的橢圓半徑,然后為它們渲染出圓角。
注意

  1. margin/border/padding/content box中相同方向的角的橢圓的圓心重疊;
  2. 當橢圓半徑為0時,渲染為直角。

margin box圓角了

公式:margin-radius = border-radius + margin-width
border-radius > margin-width時,margin-width=1 + (margin-width/border-radius-1)^3以確保margin-radius趨向于直角。

padding box圓角了

公式:padding-radius = border-radius + border-width
當padding-radius為0時,渲染為直角

<style type="text/css">
.s1{
background: #FEE;
width: 0;
padding: 50px;
border: 10px solid red;
border-radius: 10px;

float:left;
margin-right: 20px;
}
.s2{
background: #FEE;
width: 0;
padding: 50px;
border: 10px solid red;
border-radius: 20px;

float:left;
}
</style>
<div class="s1"></div>
<div class="s2"></div>

content box/area圓角了

公式:content-radius = border-radius + border-width - padding-width
當content-radius為0時,渲染為直角

<style type="text/css">
.s1{
background: #FEE;
width: 100px;
height: 100px;
border: 10px solid red;
border-radius: 10px;

float:left;
margin-right: 20px;
}
.s2{
background: #FEE;
width: 100px;
height: 100px;
border: 10px solid red;
border-radius: 20px;

float:left;
}
</style>
<div class="s1"></div>
<div class="s2"></div>

注意
由于margin區域無法觸發點擊等事件,而圓角border box所占面積必定小于直角border box,因此為保持可點擊區域面積,圓角border box應設置更大的高寬值。

話說"大值特性"和"等比特性"

 @張鑫旭老師在《秋月何時了,CSS3 border-radius知多少?》提到"大值特性"和"等比特性"兩個特性。

<style type="text/css">
.s1{
box-sizing: border-box;
background: #FEE;
width: 100px;
height: 200px;
border: 10px solid red;
border-top-left-radius: 100px 200px;

float: left;
margin-right: 20px;
}
.s2{
box-sizing: border-box;
background: #FEE;
width: 100px;
height: 200px;
border: 10px solid red;
border-top-left-radius: 200px;

float: left;
}
</style>
<div class="s1"></div>
<div class="s2"></div>

你看div.s2明明把左上角的水平和垂直半徑設置為200px,但實際效果卻是兩者結果值均為100px,難道這就是"大值特性"?

<style type="text/css">
.s1{
box-sizing: border-box;
background: #FEE;
width: 200px;
height: 100px;
border: 10px solid red;
border-top-left-radius: 300px 100px;
border-top-right-radius: 900px 100px;
}
</style>
<div class="s1"></div>

僅僅看div.s1水平方向的橢圓半徑,left和right相加300+900=1200遠遠大于border box的寬度200px,也就是說兩個橢圓將發生重疊。對于這種情況CSS渲染引擎到底是如何處理的呢?

  1. 首先明確的是left+right必須小于等于border-box的寬度,也就是說兩個橢圓不能發生重疊。
  2. 然后根據"等比例特性"得到left/(left+right)=300/(300+900)=1/4right/(left+right)=900/(300+900)=3/4,得到left結果值為200/4=50,right結果值為3*200/4=150

 通過"等比例特性"我們很好地解釋了上圖中水平方向的效果,但大家有沒有發現垂直方向的半徑有點奇怪呢?我們明明設置半徑為100px,而且border box的高度恰好也是100px,按理應該是足夠的,為何垂直半徑的結果值不是100px呢?
 其實W3C Spec中已經說得很清楚了!

Let f = min(Li/Si), where i ∈ {top, right, bottom, left}, Si is the sum of the two corresponding radii of the corners on side i, and Ltop = Lbottom = the width of the box, and Lleft = Lright = the height of the box. If f < 1, then all corner radii are reduced by multiplying them by f.

其實"最大值特性"和"等比例特性"只是上述規則的表象而已,最根本的公式為f=min(Li/Si)
以第二個示例來計算一下吧
計算f的值

  1. top-left和top-right的水平半徑之和為1200px,而border box寬度為200px,那么f1=200/1200=1/6;
  2. top-left和bottom-left的垂直半徑之和為400px,而border box高度為400px,那么f2=400/400=1;
  3. bottom-left和bottom-right的水平半徑為0,忽略;
  4. top-right和bottom-right的垂直半徑之和為400px,而border box高度為400px,那么f3=400/400=1;
  5. f=min(f1,f2,f3),結果為f=f1

縮放各半徑

  1. top-left和top-right的水平半徑分別乘以f,得到結果值300/6=50900/6=150;
  2. top-left和top-right的垂直半徑分別乘以f,得到結果值400/6=66.66

被忽視的豬腳——相交線

 當設置border-leftborder-top后,我們很容易預測到左邊框和上邊框的樣式,但它倆相交部分的樣式呢?這里就涉及到相交線的問題了!

通過直角邊框找相交線

 圓角邊框是基于直角邊框的,這一點也體現在相鄰邊框的相交線上。

<style type="text/css">
  .box{
    width: 100px;
    height: 200px;
    border: 50px solid;
    border-left-color: red;
    border-top-color: blue;
    border-right-color: green;
    border-bottom-color: yellow;
  }
</style>
<div class="box"></div>


 我們可以看到兩邊相交所形成的矩形的對角線,將作為邊的相交點。通過相交點判斷邊框樣式應應用到哪一條邊上。
透視圖如下

延長相交線

 由于圓角邊框不像直角邊框那樣有棱有角,因此更難以分辨邊框樣式所對應的邊框。但只要我們沿直角邊框的相交線向圖形內延伸,一切則清晰明了了。

<style type="text/css">
  .rounded-box{
    width: 100px;
    height: 200px;
    border: 50px solid;
    border-left-color: red;
    border-top-color: blue;
    border-right-color: green;
    border-bottom-color: yellow;
    border-radius: 100px;
  }
</style>
<div class="rounded-box"></div>


透視圖如下

兼容性


 雖然各大瀏覽器均支持border-radius屬性,但其實現效果卻不盡相同,我們拿極端情況來作試驗,最能看出效果。結論是讓我們大跌眼鏡的:IE效果最為理想!!

<style type="text/css">
.s1{
  box-sizing: border-box;
  width: 200px;
  height: 200px;
  border: 50px solid;
  border-color: red blue green yellow;

  border-top-left-radius: 50% 100%;
  border-top-right-radius: 50% 100%;
}
</style>
<div class="s1"></div>

chrome34中

FF中

IE9

總結

 尊重原創,轉載請注明來自:http://www.cnblogs.com/fsjohnhuang/p/5458573.htm^_^肥仔John

感謝

CSS Backgrounds and Borders Module Level 3 4. Borders
秋月何時了,CSS3 border-radius知多少?
CSS滑動門Sliding door詳解
《圖解CSS3核心技術與案例實戰》——第3章 CSS3邊框


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 AutoPoster 的頭像
    AutoPoster

    互聯網 - 大數據

    AutoPoster 發表在 痞客邦 留言(0) 人氣()