border屬性的多方位應用和實現自適應三角形

拉格沒有朗日發表於2017-11-23

border屬性是在實際的應用中使用頻率比較高的一個屬性,除了作為邊框使用,利用border屬性的一些特徵以及表現方式,可以在實現一些比較常見的效果(如等高佈局,上下固定內容滾動佈局和繪製CSS圖示等),利用css3新增的屬性值(如使用圖片填充邊框)可以實現一些更復雜的效果。

本文不介紹border的屬性的基本應用方法,將直接介紹如何通過border屬性實現一些常見的效果。

利用border畫三角形和梯形等多邊形

在CSS中,常見的平面圖形為矩形以及圓形。但是難免有些情景需要我們利用CSS去繪製三角形、梯形和平行四邊形等。此時我們可以利用border在渲染時的一些表現特點來實現這些功能。以下講解如何一步一步得到三角形。
首先我們寫一個div,樣式如下

 .border {
     width: 200px;   
     height: 100px;   
     margin: 0 auto;   
     border-top: 40px solid red;   
     border-bottom: 40px solid green;   
     border-left: 40px solid yellow;   
     border-right: 40px solid blue;   
 }複製程式碼

瀏覽器渲染後效果如下:

我們發現,通過給div的四個邊框設定不同的顏色,其渲染後的表現形式為四個梯形組成的邊框。
如果我們把高度定義為0,那麼渲染後如下:

如果我們再把寬度設定為0,結果如下:

到此為止,通過對比以上定義的不同的樣式,我們發現,在CSS中,邊框的表現實際上以梯形的形式來渲染的(這可能與groove等3D效果的屬性值有關,具體沒去深入研究)。當元素的寬高為0時就會變成擠在一起的四個三角形。因此,我們可以想到,如果把其中的三個邊框的顏色定義為透明色transparent,然後通過包裹在一個外層容器上,並給外層容器設定overflow:hidden,那麼我們將得到一個等腰梯形或者三角形。現在我們把css修改如下:

 .trapezoid {
     width: 200px;   
     height: 0;      
     border-top: none;   
     border-bottom: 60px solid #249ff1;   
     border-left: 40px solid transparent;   
     border-right: 40px solid transparen;   
 }複製程式碼

我們將得到以下梯形:

將樣式設定為如下:

 .triangle {
     width: 0;
     height: 0;
     border-top: 0 solid transparent;
     border-bottom: 100px solid #249ff1;
     border-left: 100px solid transparent;
     border-right: 100px solid transparent;
 }複製程式碼

我們將得到以下三角形:

由於所有的二維多邊形可以劃分為多個三角形組成,加上border這種表現形式的基礎,我們可以通過設定不同邊框寬度值、顏色以及借住偽元素或者多個元素的拼接可以實現更為複雜的一些圖形,理論上我們可以用CSS繪製任何的多邊形。比如多角星,菱形,以及我們常見的聊天氣泡等。如下為其中幾個例子

利用border實現左右兩欄等高佈局

在實際上專案中,我經常會有左右兩欄佈局的需求,比如後臺管理的左側選單欄區域和右側的內容區域以及類似京東分類導航的佈局,如下圖。

實現這種佈局有很多解決方案,比如利用padding和margin相互抵消的方法即可實現。但是如果利用border來實現的話,可能可以使CSS更加簡潔,適用性和相容性也會更高。比如針對第一張圖的效果,我們有如下html結構。

<div class="menu">
    <ul>
        <li>首頁</li>
        <li>商品管理</li>
        <li>營銷中心</li>
        <li>會員管理</li>
        <li>系統設定</li>
    </ul>
</div>
<div class="content">這裡是內容區域</div>複製程式碼

以及以下主要的CSS:

.menu {
    float: left;
    width: 200px;
    color:  #FFF;
}
.content {
    border-left:  200px solid #40403b;/*這裡是主要的樣式*/
    padding: 20px;
    height: 1000px; /* 這裡代表內容區域 */
}複製程式碼

由於border寬度不支援百分比值,所以這種實現方法的缺點是難以直接做到左右兩側寬度按比例自適應。

利用border實現移動端上下固定佈局

在移動端上的應用,頁面的頭部和底部固定,中間內容區域滾動是常見的佈局,如下圖。

實現這種佈局同樣是有多種實現方法,一般是利用上下fixed定位(fixed定位在移動端會有呼起鍵盤錯位和結合transform使用時的bug,這個另外寫文章分析),再借助margin,padding來實現。但是如果利用border來實現不僅程式碼簡潔,相容性也高。其核心的樣式為在內容區域增加透明的上下邊框,上邊框的寬度等於頭部高度,下邊框的寬度等於腳步高度。如下:

header,footer {
    position: fixed;
    width: 100%;
    line-height: 50px;
    color: #FFF;
    background: #249ff1;
    text-align: center;
}
header {
    top: 0;
    left: 0;
}
footer {
    bottom: 0;
    left: 0;
}
.container {
    padding: 20px;
    background: #f3f3f3;
    height: 1000px; /*這裡代表內容*/
    border-top: 50px solid transparent;/*上邊框寬度等於header高度*/
    border-bottom: 50px solid transparent;/*下邊框寬度等於footer高度*/
}複製程式碼

利用這種方法,我們同樣也可以實現背景的定位,比如為圖片新增水印時水印的右下角和左上角等定位。

border-color使用技巧

由於在border不指定顏色時其顏色值等於標籤的字型顏色值,我們可以利用此特點做一些效果。比如:具有邊框的a標籤,正常狀態下邊框和字型顏色為灰色,滑鼠經過時為藍色,如下:

一般情況下,我們會用偽元素來寫裡面的加號,當滑鼠經過時要同時改變邊框色值,字型色值和偽元素的背景色值,但是利用這屬性,我們只需要改變a標籤的字型色值。程式碼如下。

a {
    position: relative;
    display: inline-block;
    padding: 30px 20px;
    color: #a7a7a7;
    border: 1px solid;
}
a:hover {
    color: #249ff1;
}
a:before,a:after {
    content: '';
    display: block;
}
a:after {
    border-top: 2px solid;
    width: 20px;
}
a:before {
    position: absolute;
    top:  20px;
    left:  29px;
    border-left: 2px solid;
    height: 20px;
}複製程式碼

實現一個自適應三角形

有時候我們會有做自適應三角形效果的需求,比如下圖。這是一個註冊頁面,設計需求為:在註冊頁面頂部的兩個身份的選擇為兩個灰色背景的矩形,寬度自適應。當選中其中一個身份時變為藍色背景的五邊形。

實現這個需求可以用SVG或者CSS3的clip-path 屬性來實現,但假如我們要藉助border來實現,該怎麼做呢?

我們對UI元素進行拆分,有多種拆分方法很自然的是把啟用狀態下的形狀拆分為頂部的矩形和底部的等腰三角形。這樣可以藉助偽元素以及邊框畫三角形的方法進行CSS樣式的定義。但問題來了,因為兩個標籤的寬度是自適應的,那麼邊框寬度的值也需要自適應,然而邊框的寬度值是不支援百分比的。??怎麼辦?這時我們第一個想到的方法自然會是用js動態計算,但是不是不借助js動態計算就沒有辦法了呢?我們可以畫個圖進行分析。

假設分割後的三角形形成的矩形區域為父級元素(圖中藍色部分),實際的三角形為相對於該元素定位的子元素或者偽元素(這裡選用偽元素,圖中的紅藍交叉部分),那麼我們的標籤只需要一個div
當我們要讓三角形隨著矩形自適應,其理想狀態應該為圖中紅色和藍色交叉部分(上邊框+透明的左右邊框實現的三角形)。由border-width不支援百分比值,我們姑且先給邊框寬度一個足夠大的值,通過定位後,就成了圖中紅色三角形的部分。溢位的部分,我們在父級進行overflow:hidden即可,這樣一個自適應的三角形就實現了。剩下的就是如何去定位和如何設定這個值。
我們假設父級的寬度為a,高度為b,三角形的border-top為y,border-left和border-right為x。在未進行定位之前,A點應該與B點重合,通過定位後,A點與B點相對位置為(-(x-0.5a) , -(y-b))。此時我們又遇到一個問題,就是x和y為一個固定的大值,a和b為一個百分比值,那麼CSS就要進行計算才能定位,用CSS3的calc屬性可以解決,但是可能會有相容性問題。我們通過思考,換個角度,如果能夠讓A點相對於C和D的中點定位,那相對位置就變為(-x,-y),問題就好辦了。我們把圖片做一下改變,如下圖:

如果我們把父級的高度設定為0,利用padding-top來撐開高度,把寬度設定為0.5a,利用padding-left來撐開另外的0.5a,那麼A點就相對於P點定位(P點此時為內容區域的左上角)了。此時,A相對於P的位置為(-x,-y)。至此,通過以下樣式即可實現一個響應式三角形。(注意border-left和border-top的比例,根據相似三角形特徵計算即可)

<div></div>複製程式碼
div {
    width: 40%;
    padding-top: 8%;
    padding-left: 40%;/*寬高比為10:1*/
    overflow: hidden;
    border: 1px solid red;/*為方便觀察顯示*/
}
div:after {
    content:  '';
    display: block;
    width: 0;
    height: 0;
    border-left: 1500px solid transparent;/*足夠大的邊框寬度*/
    border-right: 1500px solid transparent;/*足夠大的邊框寬度*/
    border-top: 300px solid #249ff1;/*寬高比為10:1,即(1500+1500): 300*/
    /*定位(-x,-y)*/
    margin-top: -300px;
    margin-left: -1500px;
}複製程式碼

效果如下:

有了這個方法,就可以實現上面的註冊頁Tab標籤的設計。同時通過調整各個引數,一樣可以實現各種型別的三角形。設要定義的等腰三角形底為2x,高為y,父級需要的寬為2a,高為b。那麼各個值滿足的關係如下:

 border-left = border-right = x = -margin-left;
 border-top / padding-top = x / a;
 margin-top = -border-top;
 至於border-left的取值則根據實際需要設定一個大值即可,
 而border-top與三角形的形狀有關,即與a和b比例有關複製程式碼

以上為border屬性的一些特點和實際應用,後期將會繼續更新更多的特點和使用場景。暫且先寫這些。

相關文章