我是如何用 CSS 繪製各種形狀的
自適應的橢圓
1.自適應的橢圓
實現方式是通過border-radius這個屬性;border-radius它可以單獨指定水平和垂直半徑。用 / 分隔這兩個值。並且該屬性的值不僅可以接受長度值,還能接收百分比的值。百分比的值會基於元素的尺寸進行解析,寬是水平半徑的解析,高是垂直半徑的解析。
所以可以把兩個半徑的值都設定成50%;
border-radius: 50% / 50%; /* 值都是50% 就可以簡化成 border-radius: 50%; */
最終的效果:
2.半橢圓的實現
border-radius的值是可以分開設定的,用空格進行分開,甚至可以為四個角提供完全不同的水平和垂直的半徑。
border-radius四個值的渲染順序是從左上角開始,順時針渲染;
當只給定3個值時,第四個值和第二個相等;
當給定兩個值時,第三個值和第一個值相等,第四個值和第二個值相等。
所以半橢圓的實現方法就是:
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; */
最終效果:
同理的四分之一的橢圓的生成方法:
/* 不能設定圓角的就設定成 0 */ border-radius: 100% 0 0 0;
最終效果:
平行四邊形的實現
在生成平行四邊形時,直接對當前對div使用transform: skew(-45deg);變形,會導致div裡面的內容也會發生變形,就像下面這樣:
通用的解決辦法是通過偽元素的方法,就是把所有的樣式用到偽元素上,對偽元素進行變形,由於內容不在偽元素裡,所以內容不會受到影響。具體的實現如下:
<div class="parallelogram"> click </div>
.parallelogram { text-align: center; position: relative; } .parallelogram::before { transform: skew(-45deg); position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: -1; content: ' '; background: #fb3; }
生成的效果如下:
這種技巧不僅對於skew()變形來說有用,還適用於其他任何變形樣式,當想變形任何一個元素而不想改變它的內容的時候都可以用到它。
菱形圖片的生成
在css中,有些需求是要把圖片裁剪成菱形,使用css可以很好的解決這個問題,為不需要預先把圖片裁剪成菱形而影響後期的維護。
基於變形的方案
直接使用類似平行四邊形的方式旋轉,給img設定max-width: 100%,會導致圖片被裁剪成八邊形。因為100%會被解析成div的邊長。所以解決這個問題的辦法就是讓圖片的寬等於div這個容器的對角線的長度,比較好的辦法就是把圖片用scale放大根號2倍(大概是1.42倍),具體實現的程式碼如下:
<div class="picture"> <img src="cat.jpg" /> </div>
.picture { width: 400px; height: 400px; transform: rotate(45deg); overflow: hidden; } .picture1 > img { max-width: 100%; height: 400px; transform: rotate(-45deg) scale(1.42); }
效果如下:
scale和width放大的區別:scale的縮放圖片是以它的中心點進行縮放的(在不指定transform-origin的前提下),通過width屬性來放大圖片時,只會以它左上角的原點進行縮放,然後用額外的負邊距來調整圖片的位置。
裁切路徑方案上面的辦法還需要前套一層多餘的html標籤,使用clip-path這個屬性,這個原本是svg的屬性,使用polygon()這個多邊形的函式,使用的百分比的值會解析為元素自身的尺寸。
img { clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%); }
clip-path這個屬性還能參與動畫,只要動畫是在同一個形狀函式之間進行的,而且點的數量是相同的就可以,比如我們希望滑鼠hover時平滑的擴充套件為完成的面積,只需這樣:
.picture { clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%); transition: 1s clip-path; } .picture:hover { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%); }
切腳效果的實現
徑向漸變的方式
實現一個角被切掉的效果,可以使用漸變,漸變接受一個角度作為方向,並且允許文字溢位並超出切角區域(因為它只是背景圖案),具體實現如下:
div { background: #58a; background: linear-gradient(-45deg, transparent 15px, #58a 0); }
效果如下:
實現兩個切角的辦法:
div { width: 200px; height: 100px; background: #58a; background: linear-gradient(-45deg, transparent 15px, #58a 0) right, linear-gradient(45deg, transparent 15px, #65a 0) left; background-size: 50% 100%; background-repeat: no-repeat; }
效果如下:
同理的四個切角的實現:
div { width: 200px; height: 100px; background: #58a; background: linear-gradient(135deg, transparent 15px, #58a 0) top left, linear-gradient(-135deg, transparent 15px, #58a 0) top right, linear-gradient(-45deg, transparent 15px, #58a 0) bottom right, linear-gradient(45deg, transparent 15px, #58a 0) bottom left; background-size: 50% 50%; background-repeat: no-repeat; }
效果如下:
上面的程式碼可維護比較差,在改變切角和顏色時都要修改多處,所以我們可以使用scss的mixin來寫:
@mixin beveled-corners($bg, $tl:0, $tr:$tl, $br:$tl, $bl:$tr) { background: $bg; background: linear-gradient(135deg, transparent $tl, $bg 0) top left, linear-gradient(225deg, transparent $tr, $bg 0) top right, linear-gradient(-45deg, transparent $br, $bg 0) bottom right, linear-gradient(45deg, transparent $bl, $bg 0) bottom left; background-size: 50% 50%; background-repeat: no-repeat; }
呼叫時:
@include beveled-corners(#58a, 15px, 5px);
最後生成的效果是左上角和右下角是15px的切角,右上角和左下角是5px的切角。上面的minxin設定了初值,當傳入的值少於四個值時,就跟border-radius賦值一樣。
一樣的道理我們也可以建立弧形切角,至少改成徑向漸變
div { width: 200px; height: 100px; 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; }
效果如下:
內聯SVG與border-image的方式
SVG 可以實現與尺寸完全無關的完美縮放,當文字溢位的時候,則會起到普通邊框的作用,令文字折行。具體的實現如下:
div { width: 200px; height: 100px; border: 15px solid transparent; border-image: 1 url('data:image/svg+xml,\<svg xmlns="http://www.w3.org/2000/svg" width="3" height="3" fill="%2358a">\<polygon points="0,1 1,0 2,0 3,1 3,2 2,3 1,3 0,2"/>\</svg>'); }
效果如下:
解決中間的背景色的填充可以給div塊加一個和border一樣的背景色:
div { width: 200px; height: 100px; border: 15px solid transparent; border-image: 1 url(data:image/svg+xml,\<svg xmlns="http://www.w3.org/2000/svg" width="3" heigh="3" fill="%2358a">\<polygon points="0,1 1,0 2,0 3,1 3,2 2,3 1,3 0,2"/>\</svg>); background: #58a; background-clip: padding-box; }
裁切路徑方案CSS 裁切路徑最神奇的地方在於我們可以同時使用百分比數值(它會以元素自身的寬高作為基數度進行換算)和絕對長度值,從而提供巨大的靈活性。
如果用裁切路徑將一個元素切出20px大小的斜面切角,具體的程式碼如下:
background: #58a; 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);
這個方法最大的好處:可以使用任意型別的背景,甚至可以對替換元素(比如圖片)進行裁切
,並且支援動畫效果。
缺點:當內邊距不夠寬時,它會裁切掉文字。
梯形標籤頁的實現
梯形的實現可以通過
div { position: relative; display: inline-block; padding: .5em 1em .35em; color: white; } div::before { content: ''; position: absolute; top: 0; right: 0; bottom: 0; left: 0; z-index: -1; background: #58a; transform: scaleY(1.3) perspective(.5em) rotateX(5deg); transform-origin: bottom; }
效果如下:
變形效果會讓這個元素以它自身的中心線為軸進行空間上的旋轉,這會讓它的尺寸很難控制,解決辦法可以設定transform-origin:bottom;,當它在3D空間中旋轉時,把它的底邊固定。固定底邊的同時,高度的縮水會變得更加顯眼。為了解決這個問題,可以通過變形屬性(scaleY())來改變它的尺寸。
同樣的方法可以實現下面這種tab佈局:
具體程式碼如下:
nav > a { position: relative; display: inline-block; padding: .3em 1em 0; } nav > a::before { content: ''; position: absolute; top: 0; right: 0; bottom: 0; left: 0; z-index: -1; background: #ccc; background-image: linear-gradient(hsla(0,0%,100%,.6), hsla(0,0%,100%,0)); border: 1px solid rgba(0,0,0,.4); border-bottom: none; border-radius: .5em .5em 0 0; box-shadow: 0 .15em white inset; transform: perspective(.5em) rotateX(5deg); transform-origin: bottom; }
通過把transform-origin改成bottom left或bottom right,就可以立即得到左側傾斜或右側傾斜的標籤頁。
這個方法的缺點是:斜邊的角度依賴於元素的寬度。不過,對於寬度變化不大的多個元素(比如導航選單)來說,這個方法還是非常管用的。
簡單的餅圖的繪製
思路是把圓形的左右兩部分指定為上述兩種顏色,然後用偽元素覆蓋上去,通過旋轉來決定露出多大的扇區。具體的程式碼如下:
.pie { width: 100px; height: 100px; border-radius: 50%; background: yellowgreen; background-image: linear-gradient(to right, 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; }
實現的效果如下:
這種方式還支援動畫,就可以用CSS動畫來實現一個餅圖從0 變化到100% 的動畫,從而得到一個炫酷的進度指示器:
@keyframes spin { to { transform: rotate(.5turn); } } @keyframes bg { 50% { background: #655; } } .pie::before { content: ''; display: block; margin-left: 50%; height: 100%; border-radius: 0 100% 100% 0 / 50%; background-color: inherit; transform-origin: left; animation: spin 3s linear infinite, bg 6s step-end infinite; }
生成多個不同比率的靜態餅圖的辦法,可以通過上面的那個動畫的實現,需要設定動畫處於暫停狀態,然後設定負的動畫延時直接跳轉到動畫中的任意時間點, 最終實現的程式碼如下:
<div class="pie" style="animation-delay: -20s"> <span>20</span> </div> <div class="pie" style="animation-delay: -60s"> <span>60</span> </div>
.pie{ position: relative; width: 100px; height: 100px; line-height: 100px; border-radius: 50%; background: yellowgreen; background-image: linear-gradient(to right, transparent 50%, #655 0); color: #000; text-align: center; } @keyframes spin { to { transform: rotate(.5turn); } } @keyframes bg { 50% { background: #655; } } .pie::before { content: ''; position: absolute; top: 0; left: 50%; width: 50%; height: 100%; border-radius: 0 100% 100% 0 / 50%; background-color: inherit; transform-origin: left; animation: spin 50s linear infinite, bg 100s step-end infinite; animation-play-state: paused; animation-delay: inherit; } .pie span { position: relative; z-index: 10; }
效果如下:
用SVG 解決方案
<svg viewBox="0 0 32 32"> <circle r="16" cx="16" cy="16" /> </svg>
svg { width: 100px; height: 100px; transform: rotate(-90deg); background: yellowgreen; border-radius: 50%; } circle { fill: yellowgreen; stroke: #655; stroke-width: 32; stroke-dasharray: 38 100; /* 可得到比率為38%的扇區 */ }
讓餅圖的周長無限接近100,就可以直接把比率的百分比值指定為strokedasharray的長度,不需要做任何計算了。因為周長是2πr,半徑就是100/22π ≈ 15.915,最終把這個值取整為16。在SVG的viewBox屬性中指定其尺寸,而不再使用width和height屬性,這樣就可以讓它自動適應容器的大小了。
SVG的優點是增加第三種顏色是非常容易的,並且可以用內聯樣式來指定顏色。
相關文章
- CSS 繪製各種形狀CSS
- 用css繪製各種形狀CSS
- CSS繪製各種幾何形狀CSS
- CSS繪製各種幾何圖形形狀效果CSS
- CSS魔法系列:純CSS繪製圖形(各種形狀的鑽石)CSS
- CSS魔法系列:純CSS繪製各種圖形《系列六》CSS
- 純 CSS 建立各種不同的圖形形狀CSS
- 【前端幫幫忙】第3期 使用CSS的border屬性繪製各種幾何形狀前端CSS
- CSS 魔法系列:純 CSS 繪製三角形(各種角度)CSS
- 如何用純CSS繪製三角形--02CSS
- 如何用純CSS繪製三角形--03CSS
- Markdown繪製各種圖形———Mermaid語法AI
- 使用css繪製圖形CSS
- css繪製特殊圖形CSS
- 開始使用SmartDraw繪製開發中的各種圖形
- 如何使用 css 繪製心形CSS
- 好程式設計師web前端學習路線分享純css繪製各種圖形程式設計師Web前端CSS
- css3繪製柳樹葉形狀程式碼例項CSSS3
- OpenGL 學習系列---基本形狀的繪製
- css繪製圓形程式碼例項CSS
- CSS繪製三角形CSS
- 強大的CSS:圖形繪製合集,方便你我!CSS
- 純css繪製三角形CSS
- CSS3繪製圖形圖案效果CSSS3
- 如何用CSS製作一個圓形放大鏡CSS
- 安卓自定義View進階:繪製基本形狀安卓View
- Flutter 通過Clipper實現各種自定義形狀Flutter
- canvas 繪製圓形Canvas
- java:繪製圖形Java
- CSS魔法系列:純CSS繪製基本圖形(圓、橢圓等)CSS
- 史上最強大的40多個純CSS繪製的圖形CSS
- CSS 繪製圓環CSS
- CSS3繪製平行四邊形程式碼例項CSSS3
- css3繪製心形圖案程式碼例項CSSS3
- CSS & SVG 繪製寫作網格線的3種方式CSSSVG
- SVG <circle> 繪製圓形SVG
- CSS3各種方向三角形效果CSSS3
- CSS 繪製半圓CSS