你不知道的CSS(上)

編寫CSS樣式時,其實有不少技巧能夠節省HTML元素和讓CSS更加的DRY,在這跟你們分享下。css

文章將分紅上、中、下三篇,難度也會從簡單到難,因此建議同窗們按順序閱讀起。html

文章將大量舉各類示例,讓同窗們能更加清楚CSS的魅力所在。前端

文章將持續輸出,增長一些新奇的或者惟美的示例。。。瀏覽器

1. 背景與邊框

1.1 半透明邊框


半透明邊框相信不少前端小夥伴都常常遇到過,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-boxsvg

.border {
  background-clip: padding-box
}
複製代碼

這樣就獲得咱們想要的效果圖了。

1.2 多重邊框


box-shadow

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(全部瀏覽器都支持 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屬性產生的圓角,所以若是元素是圓角的,它的描邊可能仍是直角的。

1.3 靈活的背景定位


背景圖片指定在容器某個區域,也是很常見。

background-position

.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-origin

在給背景圖片設置距離某個角的偏移量時,有一種狀況極其常見:偏移量與容器的內邊距一致。若是採用上面提到的 background-position 的擴展語法方案,代碼看起來會是這樣的:

padding: 10px;
background: url(code-pirate.svg) no-repeat #58a;
background-position: 80px 80px; // 分別增長20px
複製代碼

如你所見,它起做用了,但代碼不夠 DRY:每次改動內邊距的值時,咱們都須要在三個地方更新這個值!

咱們常用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值,都不會去影響圖片的定位了。

calc()

從上述兩例得知,咱們無非是想獲得圖片距離白色右邊框10px,距離白色下邊框10px。使用calc,它能夠完美地在background-position 屬性中使用:

background-origin: padding-box;
background-position: calc(100% - 20px) calc(100% - 10px);
複製代碼

請不要忘記在 calc() 函數內部的 - 和 + 運算符的兩側各加一個空白符,不然會產生解析錯誤!這個規則如此怪異,是爲了向前兼容:將來,在 calc() 內部可能會容許使用關鍵字,而這些關鍵字可能會包含連字符(即減號)

不管咱們怎樣更改padding值,都不會去影響圖片的佈局了。

1.4 邊框內圓角


若是咱們要實現內側有圓角,外側邊框依舊保持着直角狀態,如圖:

咱們通常會使用兩個元素實現,若是咱們須要一個元素,有沒有方法實現?

在前面咱們提到過outline描邊,它並不會隨border-radius改變邊框,依舊保持着直角狀態。

outline: 5px solid deeppink;
border-radius: 10px;
box-shadow: 0 0 0 5px deeppink;
複製代碼

這裏box-shadow第四個參數值爲5px,那這個值是如何獲得的?是在某個瀏覽器測試的結果?事實上,指定一個等於描邊寬度的擴張值在某些瀏覽器中可能會獲得渲染異常,所以推薦一個稍小些的值。這裏直接給出一個公式( 根號2 - 1)r,其中rborder-radis10px,另外有一個限制,爲了讓這個效果得以達成,擴張半徑須要比描邊的寬度值小,但它同時又要比 (根號2 - 1)r大。

1.5 條紋背景


線性漸變相信不少人都挺熟悉的,如何實現下圖這種效果?

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;
複製代碼

效果出來了,而且是正確的,那若是我想要60度的?會是怎樣?

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第一個參數值爲10pxblack第一個參數值爲20pxred保持不變。

咱們注意到,左下角再也不是以藍色開頭,而是紅色開頭。爲何?緣由在於blue色標起始位置爲10px,因此在左下角開始到10px會被重複的漸變疊加到。

而色標blueblack之間有一層漸變的過程,由於blue結束爲15px,而black開始爲20px,他們之間存在着5px的漸變過程。

靈活的同色繫條紋

大多數狀況下,若是咱們想要的條紋圖案色差不是差別極大的狀況下,只是明度有着輕微的差別。舉個例子,咱們來看看這個條紋圖案:

background: repeating-linear-gradient(30deg,
#79b, #79b 15px, #58a 0, #58a 30px);
複製代碼

條紋是由一個主色調( #58a)和它的淺色變體所組成的。可是,這兩種顏色之間的關係在代碼中並無體現出來。此外,若是咱們想要改變這個條紋的主色調,甚至須要修改四處!

幸運的是,還有一種更好的方法:再也不爲每種條紋單獨指定顏色,而是 把最深的顏色指定爲背景色,同時把半透明白色的條紋疊加在背景色之上來 獲得淺色條紋:

background: #58a;
background-image: repeating-linear-gradient(30deg,hsla(0,0%,100%,.1),
  hsla(0,0%,100%,.1) 15px,transparent 0, transparent 30px);
複製代碼

1.6 複雜的背景圖案


前面咱們舉了各類簡單的例子,接下來咱們嘗試下稍微複雜點的狀況。

網格

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;
複製代碼

這是利用什麼原理實現?

盒子有marginborderpaddingcontent,下左下右邊框交界處出呈現平滑的斜線。

咱們能夠利用這個特色, 經過設置不一樣的上下左右邊框寬度或者顏色能夠獲得小三角等。

調整寬度大小能夠調節三角形形狀。

利用這個特色,咱們來看看其餘的形狀

height:20px;
width:20px;
border-color: red blue yellow orange;
border-style:solid;
border-width:20px;
複製代碼

感興趣的同窗,能夠利用這個特色,去搗鼓其餘的形狀,這裏就再也不舉例啦。

2. 形狀

2.1 自適應的橢圓

場景:當咱們要實現一個根據內容區的大小,自動適應的橢圓。如:

當內容區寬高相等,則爲圓形。

當內容區寬度大於高度,則爲橢圓。

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;
複製代碼

2.2 平行四邊形

平時四邊形形狀,相信也是很經常使用的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);
}
複製代碼

這一實例,巧用 僞元素,來實現咱們想要的效果。

2.3 菱形圖片

菱形圖片的製做,咱們大概能想出,使用兩個元素,而後旋轉剪切啥的來實現。而咱們是利用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作出的各種好玩的東西點我

(文章將持續中。。。)

2.3 菱形圖片


親,分享不易額,喜歡的話必定別忘了點💖!!!

只關注不點💖的都是耍流氓,只收藏也不點💖的也同樣是耍流氓。

相關文章
相關標籤/搜索