編寫CSS樣式時,其實有不少技巧能夠節省HTML
元素和讓CSS更加的DRY
,在這跟你們分享下。css
文章將分紅上、中、下三篇,難度也會從簡單到難,因此建議同窗們按順序閱讀起。html
文章將大量舉各類示例,讓同窗們能更加清楚CSS的魅力所在。前端
文章將持續輸出,增長一些新奇的或者惟美的示例。。。瀏覽器
半透明邊框相信不少前端小夥伴都常常遇到過,UI設計師
也常常性設計出這類樣式。而若是對CSS
不太熟悉的前端小夥伴人員來講,看似簡單的東西,其實有一個小坑在裏面。例:bash
...
<main class="wrapper">
<div class="border">我是邊框</div>
</main>
...
.wrapper {
background: black;
...
}
.border {
width: 100px;
height: 100px;
background: white;
border: 10px solid hsla(0, 0%, 100%, 0.3);
}
複製代碼
border
設置了0.3
的透明度,那是否是咱們要的半透明?讓咱們看看結果。app
很顯然不是的,background-clip
屬性的初始值爲border-box
,意味着背景默認狀況下,會侵入邊框的所在的範圍,當屬性值設置爲padding-box
。svg
.border {
background-clip: padding-box
}
複製代碼
box-shadow
咱們大多數人已經用過,不太爲人所知的是,它還接受第四個參數,經過設置正直或負值,可讓投影面積加大或者減少。函數
.border {
box-shadow: 0 0 0 10px red;
...
}
複製代碼
使用box-shadow
的好處在於,它接受逗號分隔語法,能夠建立任意數量的投影佈局
.border {
box-shadow: 0 0 0 10px red, 0 0 0 20px yellow;
...
}
複製代碼
box-shadow
是層層疊加的,前者會疊加在後者之上,上例中若是
yellow
須要寬度爲
10px
,那麼須要設置爲
20px
。
多重投影在大多數場合均可以很好的應用,但有一些注意事項。測試
投影行爲跟邊框不徹底一致,由於它不會影響佈局,並且也不會受
box-sizing
屬性的影響。投影部分並不會影響鼠標事件。
若是咱們只須要兩層邊框的話,outline
(全部瀏覽器都支持 outline 屬性)是一個不錯的選擇,它不會像box-shadow
只能模擬實現邊框。
.border {
border: 10px solid #655;
outline: 5px dashed deeppink;
...
}
複製代碼
outline-offset
屬性來控制它跟元素邊緣之間的間距,這個屬性甚至能夠接受負值。這對於某些效果來講很是有用。舉個例子
.border {
outline: 5px solid deeppink;
outline-offset: -79px;
}
複製代碼
使用
outline
也有一些須要注意的地方。
outline
並不能接受用逗號分隔的多個值。邊框不必定會貼合
border-radius
屬性產生的圓角,所以若是元素是圓角的,它的描邊可能仍是直角的。
背景圖片指定在容器某個區域,也是很常見。
.border {
background: url('https://cdn.renqilai.com/2019_10_16/15_35_42.jpg') no-repeat white;
background-size: 30px 30px;
background-position: 60px 60px;
}
複製代碼
background-position
擴展語法的瀏覽器上,背景圖片會緊貼在左上角,看起來很奇怪,並且它會干擾到文字的可讀性。提供一個回退方案也很簡單,就是把老套的
bottom right 定位值寫進 background
的簡寫屬性中:
.border {
background: url(code-pirate.svg) no-repeat bottom right #58a;
background-position: 60px 60px;
}
複製代碼
在給背景圖片設置距離某個角的偏移量時,有一種狀況極其常見:偏移量與容器的內邊距一致。若是採用上面提到的 background-position
的擴展語法方案,代碼看起來會是這樣的:
padding: 10px;
background: url(code-pirate.svg) no-repeat #58a;
background-position: 80px 80px; // 分別增長20px
複製代碼
咱們常用background-position:top left
,你是否有過疑惑,這個top left究竟是哪一個左上角?默認狀況下,默認是以padding box
。而咱們使用background-origin
默認狀況下是padding-box
。若是把它的 值改爲 content-box
(參見下面的代碼),咱們在 background-position
屬 性中使用的邊角關鍵字將會之內容區的邊緣做爲基準
background: url("code-pirate.svg") no-repeat #58a bottom right;
background-position: 70px 70px;
background-origin: content-box;
複製代碼
不管咱們怎樣更改padding
值,都不會去影響圖片的定位了。
從上述兩例得知,咱們無非是想獲得圖片距離白色右邊框10px
,距離白色下邊框10
px。使用calc
,它能夠完美地在background-position
屬性中使用:
background-origin: padding-box;
background-position: calc(100% - 20px) calc(100% - 10px);
複製代碼
請不要忘記在 calc() 函數內部的 - 和 + 運算符的兩側各加一個空白符,不然會產生解析錯誤!這個規則如此怪異,是爲了向前兼容:將來,在 calc() 內部可能會容許使用關鍵字,而這些關鍵字可能會包含連字符(即減號)
不管咱們怎樣更改padding
值,都不會去影響圖片的佈局了。
若是咱們要實現內側有圓角,外側邊框依舊保持着直角狀態,如圖:
咱們通常會使用兩個元素實現,若是咱們須要一個元素,有沒有方法實現?
在前面咱們提到過outline
描邊,它並不會隨border-radius
改變邊框,依舊保持着直角狀態。
outline: 5px solid deeppink;
border-radius: 10px;
box-shadow: 0 0 0 5px deeppink;
複製代碼
這裏box-shadow
第四個參數值爲5px
,那這個值是如何獲得的?是在某個瀏覽器測試的結果?事實上,指定一個等於描邊寬度的擴張值在某些瀏覽器中可能會獲得渲染異常,所以推薦一個稍小些的值。這裏直接給出一個公式( 根號2 - 1)r
,其中r
爲border-radis
的10px
,另外有一個限制,爲了讓這個效果得以達成,擴張半徑須要比描邊的寬度值小,但它同時又要比 (根號2 - 1)r
大。
線性漸變相信不少人都挺熟悉的,如何實現下圖這種效果?
background: linear-gradient(#fb3 50%, #58a 50%);
background-size: 100% 30px;
複製代碼
若是我想將黃色部分的寬度減小,我須要去修改兩個值,這種也不夠DRY。
background: linear-gradient(#fb3 50%, #58a 0);
background-size: 100% 30px;
複製代碼
將後者修改成0
,那它的位置就老是會被瀏覽器調整爲前一個色標的位置值,便可顯示出相同的效果。
在完成了水平以後,咱們來嘗試下傾斜漸變的效果。
background: linear-gradient(45deg,#fb3 50%, #58a 0);
background-size: 30px 30px;
複製代碼
貼片
內部漸變旋轉45度,而不是把整個重複的背景都旋轉了。實際上,若是想讓整個背景看起來都旋轉了45度,須要單個貼片包含了四條條紋,而不是兩條,只有這樣纔有可能作到無縫拼接。
background: linear-gradient(45deg,#fb3 25%, #58a 0,
#58a 50%,#fb3 0, #fb3 75%, #58a 0);
background-size: 30px 30px;
複製代碼
background: linear-gradient(60deg,#fb3 50%, #58a 0);
複製代碼
repeating-linear-gradient()
(
radial-gradient()
也有),色標是無限循環重複的,直到填滿整個背景。
background: repeating-linear-gradient(60deg,#fb3, #fb3 15px, #58a 0, #58a 30px);
// background-size: 30px 30px;
複製代碼
逗號分隔
,其實這種也是能夠簡化的,如:
background: white repeating-linear-gradient(60deg,
blue 0 15px,
hsla(0, 0%, 0%) 0 30px,
red 0 45px);
複製代碼
若是咱們將第一個參數不爲0
會是怎樣的狀態?
background: white repeating-linear-gradient(60deg,
blue 10px 15px,
black 20px 30px,
red 0 45px);
複製代碼
咱們將blue
第一個參數值爲10px
,black
第一個參數值爲20px
,red
保持不變。
咱們注意到,左下角再也不是以藍色開頭,而是紅色開頭。爲何?緣由在於blue
色標起始位置爲10px
,因此在左下角開始到10px
會被重複的漸變疊加到。
而色標blue
與black
之間有一層漸變的過程,由於blue
結束爲15px
,而black
開始爲20px
,他們之間存在着5px
的漸變過程。
大多數狀況下,若是咱們想要的條紋圖案色差不是差別極大的狀況下,只是明度有着輕微的差別。舉個例子,咱們來看看這個條紋圖案:
background: repeating-linear-gradient(30deg,
#79b, #79b 15px, #58a 0, #58a 30px);
複製代碼
幸運的是,還有一種更好的方法:再也不爲每種條紋單獨指定顏色,而是 把最深的顏色指定爲背景色,同時把半透明白色的條紋疊加在背景色之上來 獲得淺色條紋:
background: #58a;
background-image: repeating-linear-gradient(30deg,hsla(0,0%,100%,.1),
hsla(0,0%,100%,.1) 15px,transparent 0, transparent 30px);
複製代碼
前面咱們舉了各類簡單的例子,接下來咱們嘗試下稍微複雜點的狀況。
background-image:linear-gradient(white 1px, transparent 0),
linear-gradient(90deg, white 1px, transparent 0);
background-size: 30px 30px;
複製代碼
background-image: linear-gradient(white 2px, transparent 0),
linear-gradient(90deg, white 2px, transparent 0),
linear-gradient(hsla(0,0%,100%,.3) 1px,transparent 0),
linear-gradient(90deg, hsla(0,0%,100%,.3) 1px,transparent 0);
background-size: 75px 75px, 75px 75px,15px 15px, 15px 15px;
複製代碼
background: #655;
background-image: radial-gradient(tan 30%, transparent 0);
background-size: 30px 30px;
複製代碼
background: #655;
background-image: radial-gradient(tan 30%, transparent 0),
radial-gradient(tan 30%, transparent 0);
background-size: 30px 30px;
background-position: 0 0, 15px 15px;
複製代碼
background-image: linear-gradient(45deg,rgba(0,0,0,.25) 25%, transparent 0,transparent 75%, rgba(0,0,0,.25) 0),
linear-gradient(45deg,rgba(0,0,0,.25) 25%, transparent 0,transparent 75%, rgba(0,0,0,.25) 0);
background-position: 0 0, 15px 15px;
background-size: 30px 30px;
複製代碼
background-position
來偏移第二個漸變,使用交差的方式,實現。
天然界中,由於沒有規律而美,而平時咱們使用漸變老是能查到必定的規律,那如何增長隨機性?
background-image:
linear-gradient(90deg, #fb3 11px, transparent 0),
linear-gradient(90deg, #ab4 23px, transparent 0),
linear-gradient(90deg, #655 41px, transparent 0);
background-size: 41px 100%, 61px 100%, 83px 100%;
複製代碼
background-size
分別爲
41
,
61
,
83
若是細心的同窗可能會注意到它們都爲
質數
,由於咱們須要隨機性更加真實,咱們得把貼片的尺寸最大化,
爲了讓最小公倍數最大化,這些數字最好是「相對質數」 平鋪貼片的尺寸如今是 41×61×83=207 583 像素,比任何咱們所 能想像出的屏幕分辨率都要大!
請注意這個方法不只適用於背景,還能夠用於其餘涉及有規律重複的狀況。
在照片圖庫中,爲每幅圖片應用細微的僞隨機旋轉效果時,可使用多個 :nth-child(a) 選擇符,且讓 a 是質數。
若是要生成一個動畫,並且想讓它看起來不是按照明顯的規律在循環時,咱們能夠應用多個時長爲質數的動畫。
有時咱們想把一幅圖案或圖片應用爲邊框,而不是背景。可能會有人說使用border-image
,它的原理基本上就是九宮格伸縮法:把圖片切割成九塊,而後把它們應用到 元素邊框相應的邊和角。可是咱們但願出如今拐角出的圖片區域是隨着元素寬高和邊框厚度的變化而變化的。用border-image
是不可能作到的。
在前面,咱們使用了不少的漸變背景,那咱們能不能使用漸變來解決這個難題?
padding: 1em;
border: 1em solid transparent;
background: linear-gradient(white, white) padding-box, // 注意點
repeating-linear-gradient(-45deg, red 0, red 12.5%,
transparent 0, transparent 25%,
#58a 0, #58a 37.5%,
transparent 0, transparent 50%) 0 / 5em 5em;
複製代碼
background
第一個白色背景的
background-clip
是在
padding-box
上的,這樣防止白色背景覆蓋邊框和第二個背景。
螞蟻行軍,當鼠標點擊某個元素時,咱們能看到邊框能"行走",這是如何實現的?
@keyframes ants { to { background-position: 100% } }
...
padding: 1em;
border: 1px solid transparent;
background:
linear-gradient(white, white) padding-box,
repeating-linear-gradient(-45deg,
black 0, black 25%, white 0, white 50%
) 0 / .6em .6em;
animation: ants 12s linear infinite;
複製代碼
.voucher {
width: 150px;
height: 80px;
line-height: 5;
background: radial-gradient(circle at 100% 50%, transparent 9px, #fff 0) 0 0 / 100% 100% no-repeat;
filter: drop-shadow(3px 3px 2px rgba(0,0,0,.2));
}
複製代碼
...
width: 0;
height: 0;
border-width: 0 25px 40px 25px;
border-style: solid;
border-color: transparent transparent rgb(245, 129, 127) transparent;
複製代碼
這是利用什麼原理實現?
盒子有
margin
、border
、padding
、content
,下左下右邊框交界處出呈現平滑的斜線。咱們能夠利用這個特色, 經過設置不一樣的上下左右邊框寬度或者顏色能夠獲得小三角等。
調整寬度大小能夠調節三角形形狀。
利用這個特色,咱們來看看其餘的形狀
height:20px;
width:20px;
border-color: red blue yellow orange;
border-style:solid;
border-width:20px;
複製代碼
感興趣的同窗,能夠利用這個特色,去搗鼓其餘的形狀,這裏就再也不舉例啦。
場景:當咱們要實現一個根據內容區的大小,自動適應的橢圓。如:
當內容區寬高相等,則爲圓形。
當內容區寬度大於高度,則爲橢圓。
border-radius
能夠幫咱們實現這一點,可是若是咱們使用px
單位的話,並不能達到咱們想要的效果。而它能夠接受另外一個單位值,
%
百分比值。
border-radius
,有一個不爲人知的真相:它能夠單獨指定水平和垂直半徑,只要用一個斜槓( / )分隔這兩個值便可。
<main class="wrapper">
<div class="voucher">我是一個形狀</div>
</main>
.voucher {
border-radius: 50% / 50%;
padding: 10px;
background: orange;
}
複製代碼
因爲斜槓先後的兩個值如今是一致的,因此能夠簡化爲:
...
border-radius: 50%;
複製代碼
到這裏你們能發現,border-radius
實際上是一個簡寫屬性,在水平方向上,它能夠接受4
個值,垂直也是。這四個值分別從左上角開始以順時針順序應用到元素的拐角。說到這,咱們直接舉兩個例子來看看效果吧。
半橢圓
...
border-radius: 50% / 100% 100% 0 0;
background: orange;
複製代碼
...
border-radius: 100% 0 0 / 100% 0 0;
複製代碼
平時四邊形形狀,相信也是很經常使用的UI設計。而如何只用一個元素實現?可能咱們腦子立馬會想到一個skew()
變形,這個想法是對的。可是,若是你不作一些處理的話,內容也會跟着傾斜。那如何使內容不變化呢?
.voucher {
position: relative;
padding: 10px;
z-index: 0;
}
.voucher::after {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: -1;
background: orange;
transform: skew(-45deg);
}
複製代碼
菱形圖片的製做,咱們大概能想出,使用兩個元素,而後旋轉剪切啥的來實現。而咱們是利用clip-path
來實現咱們的功能。
注意 cli-path
有兼容性問題,若是項目考慮到兼容低版本的,須要注意。
<main class="wrapper">
<img src="https://cdn.renqilai.com/2020_05_27/11_58_26.png" alt="我失敗了">
</main>
img {
width: 100px;
height: 100px;
clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
transition: 1s clip-path;
}
img:hover {
clip-path: polygon(0 0, 100% 0,100% 100%, 0 100%);
}
複製代碼
咱們不只作出了棱形,順帶還讓它動起來,使得不會那麼枯燥。
clip-path
能夠繪製各類各樣的形狀,不過繪製點比較麻煩,快捷繪製出形狀點我。順帶的也給出一位牛人使用
clip-path
作出的各種好玩的東西點我。
(文章將持續中。。。)
親,分享不易額,喜歡的話必定別忘了點💖!!!
只關注不點💖的都是耍流氓,只收藏也不點💖的也同樣是耍流氓。