梯形標(biāo)簽

2018-02-24 15:42 更新

原文出處:http://www.w3cplus.com/blog/1658.html

問題

梯形應(yīng)用得比平行四邊形更普遍:只有兩條邊是平行的。另外兩條可以是任何角度。以前,它們都是CSS中很難創(chuàng)建的形狀,盡管它們特別常用,特別是對(duì)于標(biāo)簽。作者要么是通過精心設(shè)計(jì)的背景圖像來模擬它們,要么是一個(gè)矩形旁邊帶兩個(gè)三角形來創(chuàng)建,或者是通過邊框來偽造一下。

梯形標(biāo)簽

圖注:通過偽元素邊框偽造的梯形(為清楚起見,用較暗的藍(lán)色表示偽元素)

盡管這種技術(shù)可以節(jié)省我們花費(fèi)在圖像上的額外的HTTP請(qǐng)求,也可以非常簡(jiǎn)單地調(diào)整寬度,但還是不理想。這既浪費(fèi)了可用的偽元素,在樣式上也非常不靈活。比如,要添加一個(gè)邊框,一個(gè)背景紋理,或一些標(biāo)簽周圍的東西的時(shí)候就悲劇了(>﹏<)。

梯形標(biāo)簽

Cloud9 IDE每個(gè)打開的文檔都有梯形的標(biāo)簽

梯形標(biāo)簽

csstricks.com早期的梯形便簽,盡管只傾斜了一個(gè)方向

因?yàn)閹缀跛杏糜谔菪卧O(shè)計(jì)的技術(shù)都非常混亂甚至難以維護(hù),我們?cè)赪eb上看到的大多不是傾斜的,盡管現(xiàn)實(shí)的標(biāo)簽是這樣的。是否有一個(gè)完整的靈活的方式來創(chuàng)建梯形標(biāo)簽?zāi)兀?/p>

解決方案

是否存在這樣的可以創(chuàng)建梯形的2D變換的組合,我們只需要應(yīng)用平行四邊形中的解決方案稍微轉(zhuǎn)變一下,就可以完成了??上В虑椴⒉皇沁@么簡(jiǎn)單。

想象在一個(gè)物理的三維世界里旋轉(zhuǎn)一個(gè)矩形。我們看到的二維圖像通常是一個(gè)梯形,因?yàn)榻嵌葐栴}!所以,我們可以通過使用一個(gè)3D旋轉(zhuǎn)來在CSS中模擬這個(gè)效果:

transform: perspective(.5em) rotateX(5deg);

梯形標(biāo)簽

圖注:通過3D旋轉(zhuǎn)創(chuàng)建一個(gè)梯形。上邊:變換前;下邊:變換后

你可以在上圖中看到它創(chuàng)建出的梯形。當(dāng)然,因?yàn)槲覀兘o一整個(gè)元素都應(yīng)用了3D變換,文本也失真了。3D變換不能像2D變換那樣,將內(nèi)部文本的變換抵消(因?yàn)?D可以通過一個(gè)相反方向的變換來抵消變換)。從技術(shù)上將內(nèi)部元素的變換取消是可行的,但是非常復(fù)雜。因此,唯一實(shí)用的方式就是利用3D變換來創(chuàng)建一個(gè)梯形,把這種變換應(yīng)用到偽元素上,類似于平行四邊形中的方法:

.tab {
    position: relative;
    display: inline-block;
    padding: .5em 1em .35em;
    color: white;
}
.tab::before {
    content: ''; /* To generate the box */
    position: absolute;
    top: 0; right: 0; bottom: 0; left: 0;
    z-index: -1;
    background: #58a;
    transform: perspective(.5em) rotateX(5deg);
}

梯形標(biāo)簽

圖注:給偽元素生成的盒子應(yīng)用3D變換,這樣我們的文本就不會(huì)受到影響

如上圖所示,這可以創(chuàng)建出一個(gè)基本的梯形。雖然還有一個(gè)問題,當(dāng)我們?cè)趹?yīng)用的變換沒有設(shè)置transform-origin,元素會(huì)圍繞其中心旋轉(zhuǎn)。因此,我們屏幕上的這個(gè)2D的投影會(huì)因?yàn)楹芏嘁蛩馗淖?,如下圖所示:

梯形標(biāo)簽

圖注:我們的梯形覆蓋在其預(yù)變換的版本上,以突出其指標(biāo)的改變

當(dāng)寬度增加時(shí),它會(huì)向上移動(dòng),在高度上稍微有點(diǎn)變小等,這使得它很難設(shè)計(jì)。

為了讓這個(gè)指標(biāo)更可控,我們指定了transform-origin: bottom;,這樣在旋轉(zhuǎn)的時(shí)候它的基本還是固定的。你可以在下圖中看到區(qū)別。

梯形標(biāo)簽

圖注:我們覆蓋在預(yù)變換版本上的梯形,當(dāng)使用transform-origin: bottom;時(shí)將尺寸變化高亮

現(xiàn)在它更可預(yù)見一些:只有高度減少了。但是,高度的減少是非常清晰的,因?yàn)檎麄€(gè)元素都旋轉(zhuǎn)到遠(yuǎn)離觀察者了,而在此之前,它有一半在屏幕之上,一半在屏幕之下,這樣整個(gè)元素在三維空間里離觀察者更近一些。為了解決這個(gè)問題,我們可能會(huì)想給它應(yīng)用額外的頂部?jī)?nèi)邊距。但是,瀏覽器中的顯示結(jié)果還是非常糟糕,因?yàn)闆]有支持3D變換(如下圖所示)。

梯形標(biāo)簽

圖注:使用額外的padding解決問題導(dǎo)致了一個(gè)非常奇怪的降級(jí)

相反,我們可以通過一個(gè)變換來增加它的尺寸,這樣當(dāng)不支持3D變換的時(shí)候,整個(gè)內(nèi)容都會(huì)失效。經(jīng)過幾個(gè)試驗(yàn),我們發(fā)現(xiàn)約130%的垂直縮放(如scaleY()變換)足以彌補(bǔ)失去的空間:

transform: scaleY(1.3) perspective(.5em) rotateX(5deg);
transform-origin: bottom;

梯形標(biāo)簽

圖注:使用scale()來彌補(bǔ)失去的高度,提供了一個(gè)非常好的降級(jí)(上方的圖)

你可以在上圖中看到結(jié)果和降級(jí)。這里,結(jié)果只是在視覺上等同于前面提到的基于border的技術(shù),只是這里的語法更簡(jiǎn)潔。但是,當(dāng)你開始給標(biāo)簽應(yīng)用一些樣式的時(shí)候,這種技術(shù)的優(yōu)勢(shì)開始出現(xiàn)。例如,看看下面的代碼:

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;
}

上面代碼的效果如下圖所示:

梯形標(biāo)簽

圖注:這種技術(shù)的優(yōu)勢(shì)在于它樣式方面的靈活性

如你所見,我們已經(jīng)應(yīng)用了背景、邊框、圓角,還有盒陰影——它們都是可行的,沒有任何問題!此外,只需要把transform-origin的值改為bottom?left?或?bottom?right,我們就可以得到向左或向右傾斜的標(biāo)簽,分別!

梯形標(biāo)簽

圖注:通過改變transform-origin的值生成的斜標(biāo)簽

盡管它有這么多的優(yōu)點(diǎn),這種技術(shù)還是不夠完美。它有一個(gè)非常重大的缺陷:側(cè)邊的角度取決于元素的寬度。因此,當(dāng)處理不同的內(nèi)容時(shí),用相同的角度來得到梯形是很棘手的。但是,對(duì)于寬度變化小的元素,它還是非常ok的,比如導(dǎo)航菜單。在這些情況中,差異是難以察覺的。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)