CSS揭祕筆記(2):背景與邊框

weixin_33968104發表於2019-02-08

第2章:背景與邊框

1.半透明邊框

  • 背景知識:RGBA/HSLA顏色
    -給一個容器設定白色背景和一道半透明白色邊框,body的背景會從他的半透明框上透上去
background:white;
border: 10px solid hsla(0,0,100%,0.5)
4020994-7382456244f9df91.png
image.png

結果卻不是我們想要的。為什麼呢
因為背景色滲透到邊框下的區域了。需要更改一下預設值(預設是border-box)

background:white;
border: 10px solid hsla(0,0,100%,0.5);
background-clip:padding-box;
4020994-4249034afed7d886.png
image.png

2. 多重邊框

  • box-shadow的基本用法

box-shadow方案

box-shadow方案還能接受第四個引數(稱作擴張半徑),通過指定正值或者負值,可以讓投影面積加大或者減少。一個正確的擴充套件半徑加上倆個為0的偏移量以及0 的模糊值,得到的投影其實就像是一道實線邊框。

background:yellowgreen;
box-shadow:0 0 10px #655;
4020994-e69b36bc1d2ea459.png
image.png

另外,他還支援逗號,我們可以建立任何數量的投影。

background:yellowgreen;
box-shadow:0 0 0 10px #655, 0 0 0 15px deeplink;
4020994-11c8de8827b2c587.png
image.png

唯一需要注意的就是,box-shadow是層層疊加的,第一層投影位於頂層,以此類推。因此你需要按照這個規律來調整擴充套件半徑。

-注意事項:

  • 1:投影的行為跟邊框不一致,因為他不會影響佈局,而且也不會收到box-sizing的影響
  • 2:上述方法建立的假的邊框出現在元素的外圈。他們並不會響應滑鼠事件,比如懸停或者點選。如果這一點非常重要,你可以給box-shadow屬性加上inset關鍵字,來使投影繪製在元素的內圈,請注意,此時你需要增加額外的內邊距來騰出足夠的空隙。

3:outline方案

在某些情況下,你可能只需要兩層邊框,那就可以先設定一層常規邊框,再加上outline(描邊)屬性來產生外層的邊框。這種方式一大優點就是在於邊框樣式十分靈活,不像box-shadow只能模擬實現邊距。(假如我們需要產生虛線邊距效果,box-shadow就沒轍了)如果想得到上圖2-6的效果,程式碼可以這樣寫;

background:yellowgreen;
border: 10px solid #655;
outline: 5px solid deeppink;

描邊的另外一個好處就是你可以通過outline-offset屬性來控制他跟元素邊緣之間的間距,這個屬性甚至可以接受負值。


4020994-7b30c5b79366cd01.png
image.png

注意事項:

  • 他只適用於雙層邊框的場景,因為outline並不能接受逗號分割的多個值,如果我們需要獲取更多層的邊框,前一種方案是我們唯一的選擇。
  • 邊框不一定會貼合border-radius屬性產生的圓角,如果此元素是圓角的,他的描邊可能還是直角的(這種行為唄css工作組認為是一個bug,因此未來可能會改為貼合border-radius圓角)
4020994-eaf03f80b5540ccc.png
image.png
  • 根據css基本ui特性規範所述,“描邊可以不是矩形”,但如果你想適應這個方法,請切記最好在不同瀏覽器中完整的測試最終效果。

3:靈活的背景定位

1: background-position的擴充套件語法方案

background-position已經得到擴充套件,它允許我們指定背景圖片距離任意角的偏移量,只要我們在偏移量前面指定關鍵字。舉個例子,如果想讓背景圖片跟右邊距保持20px的偏移量,同時跟底邊保持10px的偏移量,可以這樣做。

background:url(code-priate.svg) no-repeat #58a;
background-pistion: right 20px bottom 10px;
4020994-14f89a38f8e58139.png
image.png

但是,在不支援background-position擴充套件語法的瀏覽器中,背景圖片會緊貼左上角,如圖所示。


4020994-d684123ec7a89f75.png
image.png

提供一個會退方案,就是把老套的bottom right 定位值寫進background的簡寫屬性中。

background: url(code-private.svg) no-repeat bottom right #58a;
background-position: right 20px bottom 10px;

2:background-origin方案

在給背景圖片設定距離某個角的偏移量時候,有一種情況及其常見:偏移量與容器的內邊距一致,如果採用上面提到的background-position的擴充套件語法方案,程式碼看起來是這樣的:

padding: 10px;
background:url(code-private.svg) no-repeat #58a;
background-position: right 10px bottom 10px;
4020994-30c8199b1edea5cd.png
image.png

這樣就可以看到,他雖然起作用了,但是程式碼不夠DRY, 每次改動內邊距的值時,我們都需要在其他三個地方更新這個值。
所以還有一個更簡單的辦法實現這個需求:
題外話---預設情況下,background-position是以padding box 為準的,這樣邊距才不會遮住背景圖片,因此top left 預設指的就是padding box 的左上角。background-position屬性預設值也是padding-box,如果把他的屬性改為content-box,我們在background-postion屬性中使用的邊角關鍵字將會以內容區的邊緣作為基準(也就是說,此時背景圖片距離邊角的偏移量就跟內邊距保持一致了)

padding: 10px;
backgroung: url("code-private.svg") no-repeat #58a bottom right ; /*或100%100%*/
backgroung-origin: content-box;

他的效果同上。另外如果你想讓偏移量與內邊距稍微有些不同,那麼可以使用background-origin: content-box的同時,再通過background-position的擴充套件語法來設定這些額外的偏移量

3: calc()方案

上述問題我們可以通過這個函式輕而易舉的解決:

background:url('code-private.svg') no-repeat;
background-position: calc(100% - 20px) calc(100% - 10px)

注意:兩邊各有一個空白符

4: 邊框內圓角

  • 背景知識: box-shadow, outline“多重邊框”
    要實現如下效果,我們通常用兩個元素來實現


    4020994-c1fc37265ca3b274.png
    image.png
4020994-ecb32af487002367.png
image.png

但是我們如果只使用一個元素可以達到嗎?

解決方案

background:tan;
border-radius: .8em;
padding: 1em;
box-shadow: 0 0 0 .6em #655;
outline: .6em solid #655;

5: 條紋背景

  • 背景知識:css線性漸變,background-size
width:100px;
height:100px;
background: linear-gradient(#fb3 40%, #58a 80%);

效果如圖:


4020994-44779961e14d6ec3.png
image.png

如果兩個距離過近甚至相等,漸變就會越來越小。直至沒有。
例如

width:100px;
height:100px;
background: linear-gradient(#fb3 450%, #58a 50%);
4020994-77c61938311f754d.png
image.png

i因為漸變是一種由程式碼生成的影像,所以我們可以像對待其他背景一樣的方式對待他們,而且還可以通過background-size來調整他的尺寸。

background: linear-gradient(#fb3 50%, #58a 50%);
width: 100px;
height: 100px;
background-size: 100% 20px;

效果如下:


4020994-6167b894d678e20a.png
image.png

由於背景方式預設是重複的,所以效果如上圖,如果要建立不等寬的條紋,只需要調整色標的位置值即可。

background: linear-gradient(#fb3 30%, #58a 30%);
width: 100px;
height: 100px;
background-size: 100% 30px;

效果圖如下


4020994-127cd95f24eea36f.png
image.png

注意:如果某個色標的位置值比整個列表中他之前的色標的位置值都要小,則該色標的位置值將會被設定為它前面所有色標的位置值的最大值。這意味著,如果我們把第二個色標的位置值設定為0,那它的位置就總會被瀏覽器調整為前一個色標的位置值,這個結果正是我們想要的。

background: linear-gradient(#fb3 30%, #58a 0);
width: 100px;
height: 100px;
background-size: 100% 30px;

效果如圖:


4020994-fae897848094bd6e.png
image.png

如果要建立超過兩種的條紋也是很容易的舉例子

background: linear-gradient(#fb3 30%, #58a 0, #58a 66.6%, yellow 0);
width: 100px;
height: 100px;
background-size: 100% 30px;

如圖:


4020994-de311ecf43dea91a.png
image.png

垂直條紋

和水平條紋程式碼基本一致,差別在於我們需要在開頭新增一個額外引數來指定漸變的方向。

background: linear-gradient(to right, #fb3 30%, #58a 0, #58a 66.6%, yellow 0);
width: 100px;
height: 100px;
background-size: 30px 100%;

效果如下:


4020994-3b1d144809b64037.png
image.png

斜向條紋

 background: linear-gradient(45deg, #fb3 30%, #58a 0, #58a 66.6%, yellow 0);
 width: 100px;
 height: 100px;
 background-size: 30px 30px;

結果如圖,並不是我們想要的效果:


4020994-32fd37d741dda033.png
image.png

為什麼,因為背景是重複的,相當於我們把每一個貼片的內部漸變旋轉了45度,而不是把整個重複的背景都旋轉了。
思考一下,一個小貼片中包含了四種顏色,如下圖


4020994-7e03a383ae07c79d.png
image.png

只有這樣才能做到無縫貼合。
因此程式碼需要更改為如下程式碼:
    background: linear-gradient(45deg, #fb3 25%, #58a 0, #58a 50%, #fb3 0, #fb3 75%, #58a 0);
    width: 100px;
    height: 100px;
    background-size: 30px 30px;

如圖:


4020994-2945c9f1f42a2505.png
image.png

根據勾股定理,如果想要產生等寬的漸變效果,需要做如下計算


4020994-983141be4e146da0.png
image.png

4020994-8dffabf6db947a65.png
image.png
    background: linear-gradient(45deg, #fb3 25%, #58a 0, #58a 50%, #fb3 0, #fb3 75%, #58a 0);
    width: 100px;
    height: 100px;
    background-size: 42.42px 42.42px;
4020994-f0fce325dae5b075.png
image.png

更好的斜向條紋

4020994-7124c66947b087c5.png
image.png

做一個對比,上述斜條紋可以通過如下程式碼進行實現

    width: 100px;
    height: 100px;
    background-size: 42.42px 42.42px;
    background: repeating-linear-gradient(45deg, #fb3 0, #fb3 14px, #58a 0, #58a 28px)

效果如下:


4020994-0bfc719a0cfc0b51.png
image.png

這種方式的好處就是修改顏色時候只需要修改兩處而不是原來的三處,最大的好處就是可以隨意指定角度了。需要注意的是,這裡在建立雙條紋時候,仍然需要指定四個色標值,意味著我們最好用前面的方法實現水平或者垂直條紋,而用這種方式來實現斜條紋。

靈活的同色繫條紋

日常應用中,我們想要的條紋圖案並不是由差異極大的幾種顏色組成的,這些顏色往往屬於同一個色系。只是在明度方面有著輕微的差異,這樣在實際應用中對於這樣的案例,可以通過程式碼體現出主色調和副色調之間的關係還可以在修改時候只用修改一處。程式碼如下

    width: 100px;
    height: 100px;
    background-size: 42.42px 42.42px;
    background: #58a;
    background-image: repeating-linear-gradient(30deg, hsla(0, 0%, 100%, 0.1), hsla(0, 0%, 100%, 0.1) 14px, transparent 0, transparent 28px)

效果如下圖:


4020994-26d0e6c5e36bd31d.png
image.png

6:複雜的背景圖案,

  • 漸變知識:css漸變,條紋背景

7:偽隨機背景

8:連續的影像邊框

9:自適應的橢圓

border-radius是用空格分開多個值,四個值是從左上角開始以順時針順序應用到元素的各個拐角。另外他也提供了完全不同的水平和垂直半徑。通過斜扛 / 來區分的。

四分之一橢圓

  • 無非就是一個角的水平和垂直半徑都需要是100%,而其他三個角都不能設定為圓角。
border-radius: 100% 0 0 0 ;

10平行四邊形

-背景知識:基本的CSS變形

    margin: 0 auto;
    width: 200px;
    height: 200px;
    background: #58a;
    transform: skewX(45deg)

注意:這個屬性對屬性為行內的元素是不生效的,所以最好更改為其他的屬性


4020994-9764974b7f2eced9.png
image.png

你會發現,文字內容也發生變化了,顯然這是我們不想要的,解決方法如下

1. 巢狀元素方案

  • 我們可以對容器在進行一次反向的skew變形,從而抵消容器的變形效果。

2. 偽元素方案

另一種思路就是把所有的樣式(背景,邊框等)應用到偽元素上面,然後在對偽元素進行變形

  .btn {
    position: relative;
    background: none;
    border: none;
  }
  .btn::before {
    content: '';
    position: absolute;
    background: #58a;
    transform: skewX(45deg);
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: -1;
  }

這個思路適用於其他任何樣式,當我們想變形一個元素而不變形他的內容的時候就可以用到他。

11 菱形圖片

基於變形的方案

<div class="outer">
   <div class="inner">菱形文字</div>
</div>
 .outer {
    margin: 100px auto;
    width: 100px;
    height: 100px;
    border: 1px solid green;
    transform: rotate(45deg);
    overflow: hidden;
  }

  .inner {
    max-width: 100%;
    height: 100%;
    background: gray;
    transform: rotate(-45deg);
    line-height: 100px;
    text-align: center;
  }

效果如圖:


4020994-8371dfaaacb98708.png
image.png

但是我們想讓圖片的寬度於外框對角線的長度相等,而不是與邊長相等。這裡又要用到勾股定理了。邊長 * 1.414。如果用sale放大1.414倍會更改合理,因為寬度變寬是以左上角為中心點,而scale等預設是以中心點進行縮放的,前者需要在變換位移,後者不用,所以程式碼改為如此,

 .outer {
    margin: 100px auto;
    width: 100px;
    height: 100px;
    border: 1px solid green;
    transform: rotate(45deg);
    overflow: hidden;
  }

  .inner {
    max-width: 100%;
    height: 100%;
    background: gray;
    transform: rotate(-45deg) scale(1.42);
    line-height: 100px;
    text-align: center;
  }

效果如下:


4020994-741016cc7f1a30f9.png
image.png

裁切路徑方案

上述方法對圖片寬高有要求,假如圖片不符合要求,上述方案就會出現bug,可見這種方式是由一種hack處理方式------------不夠簡潔,不夠直觀,也不夠健壯。
clip-path: polygon(...) // 多邊形

<img class="img" src="https://upload.jianshu.io/admin_banners/web_images/4609/5c252cdb56c9924a035c052cf56753f096a1d6e8.jpg"
      alt="">
.img {
    width: 200px;
    height: 200px;
    clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%)
  }

效果如圖:


4020994-df93c9f6a4910707.png
image.png

還可以參與動畫實現

  .img {
    width: 200px;
    height: 200px;
    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%)
  }

12. 切角效果

解決方案

  1. css背景漸變
 .third {
    width: 100px;
    height: 100px;
    background: #58a;
    background: linear-gradient(-45deg, transparent 15px, #58a 0);
    margin: 0 auto;
  }

效果如圖:


4020994-5ce32c9d1401162b.png
image.png

如果想要兩個角被切掉的效果,最初的想法是這樣的

 .third {
    width: 100px;
    height: 100px;
    background: #58a;
    background: linear-gradient(-45deg, transparent 15px, #58a 0), linear-gradient(45deg transparent 15px, #655, 0);
    margin: 0 auto;
  }

發現行不通,原因:預設情況下,這兩層漸變都會調填滿整個元素,因此他們會相互覆蓋。需要讓他們都縮小一半,於時我們用background-size來讓每個漸變只佔元素背景的一般

弧形切角

13 梯形標籤頁

生成梯形

.thirteen {
    transform: perspective(.5rem) rotateX(5deg);
    width: 100px;
    height: 100px;
    margin: 0 auto;
    background: #58a;
  }

效果如下


4020994-a3897fc0731e4cc5.png
image.png

由於這裡我們是對整個元素進行3d變形的,因此上面的文字也是變形的。並且對元素採用3d變形以後,元素的內部變形是“不可逆轉”的。所以我們可以採用利用偽類的方式來實現生成梯形。有些類似於上面的平行四邊形。

.thirteen {
    position: relative;
    color: white;
    padding: 0.5em 1em .35em;
    display: inline-block;
  }

  .thirteen::before {
    content: '';
    background: #58a;
    top: 0;
    right: 0;
    left: 0;
    bottom: 0;
    z-index: -1;
    position: absolute;
    transform: perspective(.5rem) rotateX(5deg);
  }

效果如圖


4020994-687df5a5a92d0ce1.png
image.png

這樣可以實現,但是有一個問題,如果我們沒有設定transform-origin的屬性時候,應用變形效果會讓這個元素以自身的中心線為軸進行空間上的旋轉。因此,元素投射到2d螢幕上的尺寸會發生多種變化。
。。。。

14簡單的餅圖

1:基於transform的解決方案

  • 這個方案在結構上是最佳解決方法:它只需要一個元素作為選擇器,而其他部分由偽元素/變形元素/和css漸變來實現。




相關文章