CSS揭祕之形狀

Mr_F發表於2017-05-04

一.自適應的橢圓

問題:

我們肯定都注意到過,我們給一個正方形元素新增一個足夠大的border-radius(指定大於正方形元素邊長一半的半徑),就可以使其變成一個圓形(如圖1-1.png)。

示例:

width: 200px;
height: 200px;
backgrund: #FFC727;
border-radius: 100px;複製程式碼

CSS揭祕之形狀
圖1-1.png

規範還特別指出了其中的原因:

“當任意兩個相鄰圓角的半徑之和超過border box的尺寸時,使用者代理必須按比例減小各個邊框半徑所使用的值,直到它們不會相互重疊為止。”

我們有時可能不願意給一個元素設定固定的寬高,而是希望讓元素能根據內容自己調整並適應。如果我們現在需要這樣的效果:如果元素的寬高相等,就顯示為一個圓,如果不相等就顯示為橢圓。我們前面的程式碼並不能滿足這樣的效果,那我們應該怎麼來產生一個橢圓呢?

解決方案:

其實就是一個你可能並不知道的真相,那就是border-radius它可以單獨指定水平半徑和垂直半徑,用(/)分隔兩值即可。這樣我們就可以得到一個相對精確的橢圓(圖1-2.png)。

示例:

width: 200px;
height: 150px;
background: #ffc727;
border-radius: 100px / 75px;複製程式碼

CSS揭祕之形狀
圖1-2.png

這樣就得到了一橢圓,但是它元素的尺寸變化,border-radius值也需要改變,那也是有點麻煩的。那我們怎麼辦呢?
其實呢,哈哈,那就是border-radius值是接收百分比值的;
所以設定border-radius: 50%;就可以實現一個自適應的橢圓了;

好吧,那我們就來看看border-radius吧。
1. border-radius:<length-percentage>{1,4} [ / <length-percentage>{1,4} ]?
where
<length-percentage> = <length> | <percentage>

(1.1) border-radius 用來設定邊框圓角。當使用一個半徑時確定一個圓形;當使用兩個半徑時確定一個橢圓,這個(橢)圓與邊框的交集形成圓角效果。(圖1-3.png)

CSS揭祕之形狀
圖1-3.png---來自MDN

(1.2)border-radius前一個語法取值可以取1~4個值,看下圖(圖1-4.png)就很清楚了,指定的是水平半徑;
後一個語法取值也可以取1~4個值(同前一個語法),指定的是垂直半徑;

CSS揭祕之形狀
圖1-4.png---來自css揭祕

(1.3)看一些示例吧

二分之一橢圓(圖1-5.png)

width: 200px;
height: 150px;
background: #ffc727;
border-radius: 50% /100% 100% 0 0;
<!--border-top-left-radius: 50% 100%;-->
<!--border-top-right-radius: 50% 100%;-->
<!--border-bottom-right-radius: 50% 0px;-->
<!--border-bottom-left-radius: 50% 0px;-->複製程式碼

CSS揭祕之形狀
圖1-5.png


四分之一橢圓(圖1-6.png)

width: 200px;
height: 150px;
background: #ffc727;
border-radius: 100% 0 0 0;複製程式碼

CSS揭祕之形狀
圖1-6.png


隨便加了點陰影(圖1-7.png)

width: 200px;
height: 150px;
background: #ffc727;
border-radius: 50%/100% 0;
box-shadow: 0px 10px 20px 0;複製程式碼

CSS揭祕之形狀
圖1-7.png

二.平行四邊形

問題:

我們可以通過skew()來對矩形進行拉伸來生成一個平行四邊形(如圖2-1.png);

CSS揭祕之形狀
圖2-1.png

平行四邊形是生成了,但是裡面的內容“hello”也進行了拉伸,這樣就比較難閱讀,也不好看。那麼有什麼辦法只讓形狀拉伸,而保持內容不變呢?

解決方案:

我們可以把所有樣式都應用到為元素上,然後對偽元素進行變形。因為我們的內容並不是包含在偽元素裡,所以內容不會受到形變的影響。

示例:(圖2-2.png)

.box{
    margin: 100px;
    width:100px;
    height:40px;
    position:relative;
    text-align: center;
    line-height:40px;
    color: #fff;
}
.box::before{
    content: "";
    position: absolute;
    top:0;
    left: 0;
    right:0;
    bottom: 0;
    background: #ffc727;
    transform: skew(-45deg);
    z-index:-1;
}複製程式碼

CSS揭祕之形狀
圖2-2.png

三.菱形圖片

我們可以通過clip-path屬性來快速實現菱形圖片的效果,不過它現在還是一個實驗中的功能,它的相容性不是很好。
clip-path:<clip-source> | [ <basic-shape> || <geometry-box> ] | none
where
<clip-source> = <url>
<basic-shape> = <inset()> | <circle()> | <ellipse()> | <polygon()>
<geometry-box> = <shape-box> | fill-box | stroke-box | view-box

示例:(圖3-1.png)

img{
    clip-path: polygon(50% 0,100% 50%,50% 100%,0 50%);
}複製程式碼

CSS揭祕之形狀
圖3-1.png

basic-shape有四種基本形狀(inset,cicle,ellipse,polygon),感覺好方便啊,那我們就一起來看看吧。
(3.1)<inset()> :定義一個插圖矩形
where
<inset()> = inset( <length-percentage>{1,4} [ round <border-radius> ]? )
inset()可以傳入5個引數(第5個引數可選),分別對應top,right,bottom,left,round radius,我們看一下下面的示例(圖3-2.png),就清楚了;

示例:(圖3-2.png)

clip-path: inset(10px 10px 50px 20px round 30px);複製程式碼

CSS揭祕之形狀
圖3-2.png

(3.2)<circle()>:圓
where
<circle()> = circle( [ <shape-radius> ]? [ at <position> ]? )
circle()可以傳人2個可選引數;
第一個引數是圓的半徑,預設為圖片寬高中短的那個為直徑;
注意:這個引數是支援百分比的,如果用百分比:
圓的半徑/百分比=sqrt(width^2+height^2)/sqrt(2)。

第二個引數是圓心位置,預設為圖片中心。

示例:(圖3-3.png)

clip-path: circle(30% at 150px 120px);複製程式碼

CSS揭祕之形狀
圖3-3.png

圓的半徑 = [sqrt(300^2+225^2)/sqrt(2)]*30% ≈ 80 px;

(3.3)<ellipse()>:橢圓
where
<ellipse()> = ellipse( [ <shape-radius>{2} ]? [ at <position> ]? )
ellipse()可以傳入3個可選引數;
前2個參數列示的分別是橢圓X軸半徑和Y軸半徑,預設是圖片寬(高)的一半,支援百分比;
第三個引數是橢圓中心位置,預設圖片中心。

示例:(圖3-4.png)

clip-path: ellipse(25% 25% at 50% 25%);複製程式碼

CSS揭祕之形狀
圖3-4.png

(3.4)<polygon()>:多邊形
where
<polygon()> = polygon( <fill-rule>? , [ <length-percentage> <length-percentage> ]# )
polygon()中前一個語法<fill-rule>表示填充規則用來確定該多邊形的內部。可能的值有nonzero和evenodd,預設值是nonzero;
後面列表中的每對參數列示多邊形的頂點座標(X,Y);

示例:(圖3-5.png)

clip-path: polygon(50% 0,100% 50%,0 100%);複製程式碼

CSS揭祕之形狀
圖3-5.png

clip-path這個屬性還可以參與動畫呢,只要我們使用的是同一種形狀函式。

示例:(圖3-6.png)

img{
    clip-path: ellipse(75% 25%);
    transition: 1s clip-path;
}
img:hover{
    clip-path: ellipse(50% 50%);
}複製程式碼

CSS揭祕之形狀
圖3-6.png

四.切角效果
我這裡用上面的clip-path來實現下,可以通過css漸變和border-image實現。
(4.1)clip-path實現切角效果

示例:(圖4-1.png)
CSS

.box{
    width:200px;
    height:200px;
    background: #FFc727;
    clip-path: polygon(20px 0,calc(100% - 20px) 0,100% 20px,100% calc(100% - 20px),calc(100% - 20px) 100%,20px 100%,0 calc(100% - 20px),0 20px);
}複製程式碼

這樣要改一切角,就要改好多地方,不是很方便,我們就用一下前處理器,我使用的是LESS,這樣就稍稍好了一些,但也不夠DRY。
LESS

.corner(@radius){
    @ca: e("calc(100% - @{radius})");
    <!--@ca: calc(~"100% - @{radius}");-->
    clip-path: polygon(@radius 0,@ca 0,100% @radius,100% @ca,@ca 100%,@radius 100%,0 @ca,0 @radius);
}
.box{
    width:200px;
    height:200px;
    background: #FFc727;
    .corner(20px);
}複製程式碼

CSS揭祕之形狀
圖4-1.png

未來,可能會引入一個新的屬性corner-shape,配合border-radius使用,這樣就可以快速實現一些切角的問題。
corner-shape介紹:lea.verou.me/2013/03/bor…
corner-shape體驗:leaverou.github.io/corner-shap…


本內容根據《css揭祕》, MDN 和自己的理解進行整理;
感謝您的閱讀。

相關文章