你該知道的《css揭祕》--形狀篇

關於如下內容,咱們假設結構層的變動是不容許的。css

咱們也儘可能不去添加額外的HTML,以作到樣式層與結構層的分離,如若實在沒有其餘的可能性,才退而求其次來增長額外的HTML。html

自適應橢圓

製做一個自適應的橢圓是形狀篇中最簡單的圖形了,簡直不能再簡單了。

衆所周知,製做與圓相關的圖形,用到的屬性就要 border-radius 了。咱們知道,border-radius能夠單獨指定水平和垂直半徑,使用斜槓 (/) 來分開,兩個值相等能夠製做一個圓弧,若是不相等,即是一個橢圓弧了。git

.demo{
    border-radius: 100px / 75px;
}
複製代碼

其實border-radius是一個簡寫屬性,咱們有兩種方式能夠爲元素的每一個角指定不一樣的值。github

第一種簡寫方式dom

.demo{
   border-radius:10px 20px 30px 40px / 50px 60px 70px 80px;
   /* 斜槓(/)前表明水平半徑,後表明垂直半徑,順序分別爲左上角開始,順時針走向,因此這段代碼表示左上角(10px/50px) 右上角(20px/60px)右下角(30px/70px)左下角(40px/80px) */
}
複製代碼

第二種是分開寫的方式svg

.demo{
    border-top-left-radius:10px/50px;
    border-top-right-radius:20px/60px;
    border-bottom-right-radius:30px/70px;
    border-bottom-left-radius:40px/80px;
}
複製代碼

若是生成一個自適應的橢圓就很簡單了,只要每一個角的水平半徑爲寬的50%,垂直半徑爲高的50%,就ok了。 代碼簡寫爲:函數

.ellipse{
    border-radius:50%;
}
複製代碼

平行四邊形

平行四邊形也是頁面中常出現的一種圖形,咱們可能很容易就想到,使用skew()將矩形傾斜必定角度便可。oop

.parallelograms{
    transform: skew(-45deg);
    /*...... */
}
複製代碼

惋惜效果不如人意,文字也跟着傾斜了,這時候很容易想到,藉助一層dom結構,再把內部文字傾斜回來。post

<div class="parallelograms">
    <div>二十首情詩與絕望的歌</div>
</div>
複製代碼
.parallelograms{
    margin: 50px auto;
    max-width: 200px;
    padding: 10px;
    line-height: 30px;
    text-align: center;
    color:#fff;
    background-color: #58a;
    transform:skew(-45deg);
}
.parallelograms div{
    transform: skew(45deg);
}
複製代碼

很好,效果不錯,可是卻添加額外的 HTML 元素。咱們不作過多討論。

接下來咱們討論第二種方式,使用 僞元素來實現,這時候就體現了僞元素的好處。 關於僞元素的內容可參考個人另外一邊文章你所不知道的cssui

思路:咱們能夠把僞元素做爲第一種方法中的輔助結構層,把全部樣式(背景、邊框等)應用到僞元素上,而後再對僞元素進行變形,獲得咱們的平行四邊形形狀,而正式內容不受影響,而後把僞元素定位z-index設爲-1,即可漏出正文的內容。

.parallelograms{
    margin: 50px auto;
    max-width: 200px;
    padding: 10px;
    line-height: 30px;
    text-align: center;
    color:#fff;
    position: relative;
}
.parallelograms:before{
    content:'';
    position: absolute;
    left:0;
    top:0;
    right:0;
    bottom:0;
    background-color: #58a;
    transform:skew(-45deg);
    z-index: -1;
}
複製代碼

提醒: 這個技巧不只對 skew() 變形來講頗有用,還適用於其餘任何變形樣式, 當咱們想變形一個元素而不想變形它的內容時就能夠用到它。

菱形圖片

看到這個圖形狀,是否是立刻想起上一小節平行四邊形的製做,同樣的道理,須要把圖片用一個

包裹起來,而後對其應用相反的 rotate() 變形樣式:

<div class="diamond">
    <img src="https://avatars1.githubusercontent.com/u/8121621?v=4" alt="..." />
</div>
複製代碼
.diamond {
    margin:30px auto;
    width: 100px;
    height: 100px;
    transform: rotate(45deg);
    overflow: hidden;
    border: 1px solid red; /*爲了更好的展現問題*/
}

.diamond img {
    max-width: 100%;
    transform: rotate(-45deg);
}

複製代碼

奈何,天不遂人願!問題在於 max-width:100% 中的100%是指width的100%,也就是400px,而正方形旋轉後最長邊爲對角線,是 根號2倍的width,天然圖片的寬度不夠了,咱們可使用 scale() 變形樣式來把這個圖片放大。找到問題後,咱們修復它,

代碼以下:

.diamond {
    margin:30px auto;
    width: 100px;
    height: 100px;
    transform: rotate(45deg);
    overflow: hidden;
    border: 1px solid red; /*爲了更好的展現問題*/
}

.diamond img {
    max-width: 100%;
    transform: rotate(-45deg) scale(1.42);
}
複製代碼

這個方法須要一層額外的 HTML 標籤,這是咱們不作優先考慮的。同時有一個最大的問題就是,只能處理正方形圖片,不然就會失效。

在上節中咱們使用過僞元素的技巧,一樣能夠用在這裏,代碼以下:

.diamond{
    margin:30px auto;
    width: 100px;
    height: 100px;
    overflow: hidden;
    position: relative;
    transform: rotate(45deg);
}
.diamond:before{
    content:'';
    position: absolute;
    left: 0;
    right:0;
    top:0;
    bottom:0;
    transform: rotate(-45deg) scale(1.42);
    background: url(https://avatars1.githubusercontent.com/u/8121621?v=4);
    background-size: cover;
}
複製代碼

原理與上面藉助結構層是同樣的,因此面臨一樣的問題,只能處理正方形圖片。

接下來咱們使用一種更爲好用的方法來解決不是正方形的圖片。(裁切路徑方案)

拋出代碼:

.diamond{
    /*......*/
    clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
}
複製代碼

clip-path 屬性是從svg中借鑑過來的,裁切路徑容許咱們把元素裁剪爲咱們想要的任何形狀。polygon()函數容許咱們用一系列(以逗號分隔的)座標點來指定任意的多邊形。

該方法一樣能夠實現上個章節中的平行四邊形,如下章節中的切角、梯形等等任意形狀,只須要按順序排列座標點便可,如下章節再也不作過多展現,本身能夠多多嘗試。

切角效果

切角效果,很容易想到的就是個人上篇文章 你該知道的《css揭祕》--背景與邊框篇 中的條紋背景製做中用到的線性漸變 linear-gradient()

咱們很輕易的能夠實現一個角被切掉的效果,代碼以下:

.bevel-corners{
    background: #58a; /*linear-gradient不支持的狀況下,做爲代碼回退機制*/ 
    background:linear-gradient(-45deg, transparent 15px, #58a 0);
}
複製代碼

接下來使用兩層漸變背景實現兩個角被切掉。

首先分析一下,默認狀況下, 這兩層漸變都會填滿整個元素,所以它們會相互覆蓋。須要讓它們都縮小一些,因而咱們使用 background-size 讓每層漸變分別只佔據整個元素一半的面積,而且 background-repeat設爲 no-repeat

代碼以下:

.bevel-corners{
    background: #58a;
    background:
    linear-gradient(-45deg, transparent 15px, #58a 0) right,
    linear-gradient(45deg, transparent 15px, #58a 0) left;
    background-size:50% 100%;
    background-repeat:no-repeat;
}
複製代碼

一樣的原理,咱們把每層漸變改成整個元素的四分之一,則四層漸變色,能夠實現四個角被切掉。

代碼以下:

.bevel-corners{
    background:#58a;
    background:
    linear-gradient(-45deg,transparent 15px, #58a 0) bottom right,
    linear-gradient(45deg,transparent 15px, #58a 0) bottom left,
    linear-gradient(135deg,transparent 15px, #58a 0) top left,
    linear-gradient(-135deg,transparent 15px, #58a 0) top right;
    background-size:50% 50%;
    background-repeat:no-repeat;
}
複製代碼

繼續增長難度,實現 弧形切角, 原理都同樣,換湯不換藥,只需將線性漸變改成徑向漸變便可。

實現代碼以下:

.scoop-corners{
    background: #58a; 
    background:
    radial-gradient(circle at top left, transparent 15px, #58a 0) top left,
    radial-gradient(circle at top right, transparent 15px, #58a 0) top right,
    radial-gradient(circle at bottom right, transparent 15px, #58a 0) bottom right,
    radial-gradient(circle at bottom left, transparent 15px, #58a 0) bottom left;
    background-size: 50% 50%; 
    background-repeat: no-repeat;
}
複製代碼

簡單的餅圖

實現最後一個圖形--餅圖(綠色爲餅圖,棕色來顯示比率)

基於 transform 的解決方案

思路:把圓形的左右兩部分指定爲上述兩種顏色,而後用僞元素覆蓋上去,經過旋轉來 決定露出多大的扇區。

20%的餅圖代碼以下:

.pie {
    width: 100px; 
    height: 100px;
    border-radius: 50%; 
    background: yellowgreen;
    background-image:linear-gradient(90deg, transparent 50%, #655 0);
}
.pie:before { 
    content: '';
    display: block; 
    margin-left: 50%;
    height: 100%;
    border-radius: 0 100% 100% 0 / 50%; 
    background-color: inherit; 
    transform-origin: left;
    transform: rotate(.2turn);
}
複製代碼

當旋轉超過50%以後,餅圖就變成了下圖這樣,

而後咱們可讓旋轉的僞元素的顏色反一下,變成棕色既能夠實現50%-100%比率的餅圖,

60%的餅圖代碼以下:

.pie:before { 
    content: '';
    display: block; 
    margin-left: 50%;
    height: 100%;
    border-radius: 0 100% 100% 0 / 50%; 
    background-color: #655; 
    transform-origin: left;
    transform: rotate(.1turn);
}

複製代碼

若是本文有幫到你,不妨給點個贊👍,我會更加有動力創做!

相關文章
相關標籤/搜索