CSS斜切角

来源:https://www.cnblogs.com/lan1974/archive/2018/06/06/9144260.html
-Advertisement-
Play Games

問題 斜切角在Web設計和印刷中是相當受歡迎的樣式。它通常是在一個或多個元素的角落切一個45°的角(也就是所謂的斜切角)。特別是最近,扁平化設計的勢頭壓過了擬真設計,也使這種效果更加流行。當斜切角只存在元素的一側,並且每個都占據元素的50%高度的時候,一個箭頭的形狀產生了,這在按鈕和麵包屑導航中非常 ...


 

問題

斜切角在Web設計和印刷中是相當受歡迎的樣式。它通常是在一個或多個元素的角落切一個45°的角(也就是所謂的斜切角)。特別是最近,扁平化設計的勢頭壓過了擬真設計,也使這種效果更加流行。當斜切角只存在元素的一側,並且每個都占據元素的50%高度的時候,一個箭頭的形狀產生了,這在按鈕和麵包屑導航中非常受歡迎。

圖註:帶斜切角的按鈕,創建了箭頭形狀強調其意義

 

但是,要用CSS來創建這個效果並不是那麼容易,這不是一行代碼就可以搞定的效果。這導致很多作者傾向於直接使用背景圖像完成,而不是結合三角形來完成斜切角(當背景是純色),也不會去使用一個或多個角落已經被切的圖像來作為整個背景。

圖註:應用了斜切角的網站示例(半透明的“Find & Book”盒子的左下角)

 

這種方法顯然是不靈活的,而且難以維護,還增加了延遲,因為增加了HTTP請求和網站的總文件大小。有沒有什麼更好的方法呢?

解決方案

第一個解決方案是萬能的CSS漸變。我們假設我們暫時只完成一個斜切角——右下角那個。其訣竅在於漸變可以接受一個角度值作為參數(如45deg),色標位置是絕對長度,這兩個都不會因為元素和背景尺寸的改變受到影響。

綜上所述,我們只需要一個線性漸變就ok了。它需要一個透明的色標作為斜切角,還有另一個相同位置的帶有我們想要作為背景顏色的色標。CSS代碼如下(如一個15px大小的切角):

background: #58a;
background: linear-gradient(-45deg, transparent 15px, #58a 0);

 

很簡單,對不對?你可以看到結果。

圖註:右下角斜切的元素,通過一個簡單的CSS漸變完成

 

從技術上說,我們甚至不需要第一條聲明。我們只是把它作為一個降級引入:當CSS漸變不被支持時,也就是第二條聲明失效的時候。所以我們還是需要一個純色背景。

為方便調試,我們使用不同的顏色(#58a#655)。在應用中,兩個漸變應該是相同的顏色。

現在,假設我們需要兩個斜切角,左右下角分別一個。只用一個漸變是沒辦法搞定的,所以兩個漸變上場。我們首先想到的可能是:

background: #58a;
background: linear-gradient(-45deg, transparent 15px, #58a 0),
            linear-gradient(45deg, transparent 15px, #655 0);

 

但是,如下圖所示,這是不ok的。

圖註:給底部兩個角都應用斜切角效果的失敗嘗試

 

預設情況下,兩個漸變被應用於同一個元素,它們會相愛相殺(彼此掩蓋)。我們需要把它們變小,通過使用background-size來讓每個漸變都只應用於元素的一半:

background: #58a;
background: linear-gradient(-45deg, transparent 15px, #58a 0) right,
            linear-gradient(45deg, transparent 15px, #655 0) left;
background-size: 50% 100%;

 

你可以在下圖中看到結果。

圖註:只一條background-size是不夠噠~

 

即使應用了background-size,這倆漸變還是會把對方蓋住。因為我們忘了把background-repeat關掉了,所以我們的背景就都重覆了兩次。因此,我們的背景還是在相愛相殺——這次是因為背景重覆。新修改的代碼如下:

background: #58a;
background: linear-gradient(-45deg, transparent 15px, #58a 0) right,
            linear-gradient(45deg, transparent 15px, #655 0) left;
background-size: 50% 100%;
background-repeat: no-repeat;

 

你可以在下圖中看到結果。

圖註:我們的左下和右下斜切角終於ok了

 

它終!於!通過驗證了!現在,你應該知道要如何把這個效果應用到其它四個角了吧。一共需要四個漸變,代碼如下:

background: #58a;
background: linear-gradient(135deg, transparent 15px, #58a 0) top left,
            linear-gradient(-135deg, transparent 15px, #655 0) top right,
            linear-gradient(-45deg, transparent 15px, #58a 0) bottom right,
            linear-gradient(45deg, transparent 15px, #655 0) bottom left;
background-size: 50% 50%;
background-repeat: no-repeat;

 

你可以在下圖中看到結果。

圖註:使用四個漸變,給四個角都應用了效果

 

前面的代碼有個問題是,它不是特別可維護的。要改變背景顏色還有四個角的大小,需要五次編輯。加入預處理器mixin有助於減少重覆。這是SCSS代碼:

@mixin beveled-corners($bg, $tl:0, $tr:$tl, $br:$tl, $bl:$tr) {
    background: $bg;
    background: linear-gradient(135deg, transparent $tl, $bg 0) top left,
                linear-gradient(225deg, transparent $tr, $bg 0) top right,
                linear-gradient(-45deg, transparent $br, $bg 0) bottom right,
                linear-gradient(45deg, transparent $bl, $bg 0) bottom left;
    background-size: 50% 50%;
    background-repeat: no-repeat;
}

 

然後,在需要的時候,它可以像這樣被使用,使用2-5個參數:

@include beveled-corners(#58a, 15px, 5px);

 

在這個示例中,我們將會得到在左上角和右下角得到15px斜切角,在左下角和右上角得到5px斜切角,和border-radius的原理相似。這是因為我們為SCSS的mixin的參數提供了預設值,還有,這些預設值也可以引用其它的參數。

 

曲線切口角

有很多漸變的方法可以用來創建曲線切口角,大家常常把這個效果稱之為“內圓角”,因為它看起來就是圓角的反相版本。和斜切角唯一的不同是它使用了徑向漸變,而不是線性漸變:

 

g2geogeske.com上使用曲線切口角的非常棒的例子;設計師已經把它們變成核心設計元素,因為它們存在於導航、內容、甚至頁腳中。

background: #58a;
background: radial-gradient(circle at top left,
            transparent 15px, #58a 0) top left,
            radial-gradient(circle at top right,
            transparent 15px, #58a 0) top right,
            radial-gradient(circle at bottom right,
            transparent 15px, #58a 0) bottom right,
            radial-gradient(circle at bottom left,
            transparent 15px, #58a 0) bottom left;
background-size: 50% 50%;
background-repeat: no-repeat;

 

你可以在下圖中看到結果。

圖註:使用徑向漸變完成的曲線切口角

 

和前面的技術一樣,切口角的大小可以通過色標的位置進行控制,使用mixin可以讓代碼更易於維護。

內聯SVG、border-image的解決方案

雖然基於漸變的解決方案是可行的,但是它有幾個問題:

  • 代碼非常長,而且重覆。在通常情況下,我們希望在四個角都有相同尺寸的切口角,這樣我們就需要重覆四次編輯。相似的,要修改背景顏色我們也需要四次編輯,五個計算降級。
  • 在不同尺寸的切口角之間設置動畫是完全不可能的(依賴於瀏覽器)。

幸好,根據我們的需求,還有幾個我們可以採用的方法。一個是在內聯SVG中使用border-image生成圓角。根據border-image的工作原理,你可以想象一下我們的SVG會如何嗎?

因為尺寸並不重要(border-image可以縮放,而且SVG縮放是完美的,不需要擔心尺寸——這就是矢量圖的好處!),單位可以是1,或者更直接的,直接是數字。拐角長度可以是長度1,直邊長度也為1。結果(縮放)如下圖所示。

圖註:基於SVG的border-image,及其切片

 

代碼如下:

border: 15px solid transparent;
border-image: 1 url('data:image/svg+xml,\<svg xmlns="http://www.w3.org/2000/svg" width="3" height="3" fill="%2358a">\<polygon points="0,1 1,0 2,0 3,1 3,2 2,3 1,3 0,2"/>\</svg>');

 

註意我們使用了大小為1的切片。這不是1像素的意思,它指的是SVG文件的坐標系(因此預設單位)。如果我們指定了它的百分比,我們需要的就是1/3圖像的近似值,如33.34%。近似值是有風險的,因此不是所有的瀏覽器都使用相同的精確度。但是,通過使用SVG文件的坐標系統的單位,我們就不需要糾結精確值的問題了。

圖註:給border-image屬性應用SVG

 

結果如上圖所示。我們的切口角有了,但是沒有背景。你可以通過兩個方法解決:指定一個背景,或者給我們的border-image聲明添加一個關鍵字fill,這樣它就不會丟棄中間的切片。這裡,我們選擇指定一個背景,因為這樣也可以作為一個降級。

另外,我們的切口角比前面創建的切口角要小,有點奇怪。我們明明指定了一個15px的邊框寬度!這是漸變造成的,15px沿著漸變方向的,而方向垂直於梯度。同時邊框的寬度不是對角線測量的,而是水平/垂直方向的。所以你找到原因了嗎?對,我們要再次使用勾股定理,我們在前面也講過。

圖註:指定border-width15px,得到結果為15 / 根號(2) ≈ 10.606601718的拐角尺寸,這也是為什麼我們的拐角看起來小很多

 

上圖有助於我們理解。總而言之,為了得到相同的尺寸,我們使用的邊框應該是我們用漸變方法的尺寸的根號(2)倍。這裡,應該是15 * 根號(2) ≈ 21.213203436像素,也就是約等於20px,除非我們真的需要對角線儘可能地接近於15px

border: 20px solid transparent;
border-image: 1 url('data:image/svg+xml,\<svg xmlns="http://www.w3.org/2000/svg" width="3" height="3" fill="%2358a">\<polygon points="0,1 1,0 2,0 3,1 3,2 2,3 1,3 0,2"/>\</svg>');
background: #58a;

 


圖註:我們的切口角哪去了?!

 

但是,上圖的效果並不是我們期待的效果。我們辛辛苦苦創建的切口角躲到哪裡去了?年輕人,不要擔心!切口角還在那裡。如果你把背景設置成其它的顏色,如#655,你就會知道是怎麼回事了。

圖註:把我們的background換成其它顏色,就可以發現神秘消失的切口角了

 

上圖所示,我們的切口角消失的原因是我們指定的背景把它們擋住了。我們需要做的是使用background-clip來阻止背景擴展到覆蓋了我們的邊框:

border: 20px solid transparent;
border-image: 1 url('data:image/svg+xml,\<svg xmlns="http://www.w3.org/2000/svg"\ width="3" height="3" fill="%2358a">\<polygon points="0,1 1,0 2,0 3,1 3,2 2,3 1,3 0,2"/>\</svg>');
background: #58a;
background-clip: padding-box;

 

這個問題已經解決,我們現在的盒子如下圖所示。

 

但是,我們可以只在一個地方很容易地改變拐角的尺寸:我們只需要修改邊框的寬度。我們甚至可以給它添加動畫,因為border-width是可添加動畫的!我們還可以只通過兩次編輯就改變背景。另外,因為我們的背景現在是獨立於拐角效果的,我們甚至可以給它指定一個漸變,或其它的紋理,只要它在邊緣處的顏色還是#58a就好。例如,看看下圖,使用了一個從hsla(0,0%,100%,.2)transparent的徑向漸變。

圖註:帶有徑向漸變背景的切口角

 

只剩下一個小問題了。如果border-image不被支持,降級不僅沒有拐角。因為背景裁剪,它看起來還像是盒子邊緣和內容之間沒有任何填充空間。為瞭解決這個問題,我們可以給我們的邊框添加一個和背景相同的顏色:

border: 20px solid #58a;
border-image: 1 url('data:image/svg+xml,\<svg xmlns="http://www.w3.org/2000/svg"\ width="3" height="3" fill="%2358a">\<polygon points="0,1 1,0 2,0 3,1 3,2 2,3 1,3 0,2"/>\</svg>');
background: #58a;
background-clip: padding-box;

 

border-image應用的時候,顏色會被忽略,這可以提供一個更優雅的降級,看起來如圖所示。

 

 

因為這個缺陷,使得我們想要改變背景顏色的時候,需要的編輯次數從2變成了3

 

clip-path的解決方案

因為border-image的解決方案非常緊湊而且相對DRY,它仍然有其局限性。例如,我們仍然需要有一個純色背景,或一個在邊緣處帶有純色的背景。如果我們想要一種不同的背景呢,例如紋理、圖案,或一個線性漸變?

有一個方法可以使我們不受所有的這些限制,儘管它也有自己的局限性。還記得clip-path屬性嗎?一件非常令人驚嘆的事情是,CSS的clip-path可以結合百分比(這裡指的是元件尺寸)以及絕對長度使用,給了我們極大的靈活性。

例如,clip-path裁剪一個帶20px(水平方向)切角的矩形元素的代碼如下所示:

background: #58a;
clip-path: polygon( 20px 0, calc(100% - 20px) 0, 100% 20px,
                    100% calc(100% - 20px), calc(100% - 20px) 100%,
                    20px 100%, 0 calc(100% - 20px), 0 20px
);

 

儘管代碼很短,也不意味著它是DRY的,這就是它本身最大的問題之一,如果你不使用預處理器的話。事實上,這是我們提出的最WET的CSS解決方案,要改變拐角尺寸需要8次編輯!但是,我們只需要在一處位置改變背景。

它的優勢是我們可以使用任何我們想要的背景,甚至是裁剪像圖片這樣的替換元素。如下圖帶有切角的圖像。

圖註:通過clip-path製作的帶有切角的圖片

前面的幾種方法都不能完成。另外,clip-path是可動畫的,即使斜切角的大小不同,形狀也不同。我們需要做的只是使用一個不同的裁剪路徑。

除了WET,它的瀏覽器支持也不夠,它還有個缺點是:如果沒有提供足夠的padding,它還會裁剪文本,因為它只裁剪元素,而不區分都是哪些部分。與此相反,漸變的方法只是讓文本在超出拐角(因為它們只是背景),這樣border-image方法只是扮演邊框的角色,來包裹文本。

將來的拐角

將來我們不需要再通過CSS漸變、裁剪或SVG來完成這種效果了。一個新屬性,corner-shape即將加入到CSS Backgrounds & Borders Level 4中,可以幫我們節省很多精力。它可以和border-radius結合使用,用於產生不同切口角效果,在border-radius中定義尺寸即可。如,在所有角落指定15px的切口角將會很簡單:

border-radius: 15px;
corner-shape: bevel;

 

轉載自:http://www.w3cplus.com/css3/css-secrets/cutout-corners.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一款瀏覽器仿EXCEL純JS表格控制項,純國產化,支持雙擊編輯、設置公式、設置顯示小數精度、下拉框、自定義單元格、複製粘貼、不連續選定、合併單元格、隱藏列、鍵盤操作等。 ...
  • 請你設計出以下圖片里的這個樣式的表格 步驟: 2.將table里的cellspacing設置成0 外邊距是不見了,但是和我們想要完成的圖片有一定的差距,我們發現這樣做出來的圖片好像是兩條線合併到了一起一樣,實際上確實是兩條線合併到了一起的,它是將每個單元格的邊距和表格的邊距重疊到了一起才有的這個圖形 ...
  • 1.什麼是列表標簽? 列表標簽的作用:給一堆數據添加列表語義,也就是告訴搜索引擎,告訴瀏覽器這一堆數據是一個整體 2.HTML列表標簽的分類 2.1無序列表(企業開發中用到最多)(unordered list) 2.2有序列表 (企業開發中用的最少) (ordered list) 2.3定義列表 ( ...
  • github源碼地址 https://github.com/ghshuo/webpack demo webpack介紹 webpack 是一個現代 JavaScript 應用程式的靜態模塊打包器(module bundler)。當 webpack 處理應用程式時,它會遞歸地構建一個依賴關係圖(dep ...
  • 單選按鈕: 加checked=checked屬性 覆選框 加checked=checked屬性 select下拉框 加selected=selected屬性 date日期: value='2018-06-06' 普通文本框: value="你要預設展示的值" textarea: 沒有value屬性, ...
  • 實驗目的:按照一定規律生成類地行星地表地形區塊,並用合理的方式將地形塊顯示出來 涉及知識:Babylon.js引擎應用、著色器編程、正態分佈、數據處理、canvas像素操作 github地址:https://github.com/ljzc002/ljzc002.github.io/tree/mast ...
  • 2.左側盒子: 左浮動; 右側盒子: 左浮動,再通過calc計算寬度 3.左側盒子: float: left; 右側盒子: margin-left 理解: 浮動會使得元素脫離文檔流,後面元素進行佈局時,前面的浮動元素就像不存在一樣 4.包含左右盒子的大盒子: display: table; 寬度為1 ...
  • window.onload= function(){ /* 表單提交是預設行為 * preventDefault() * returnValue = false; var btnCheck = document.getElementById('btnCheck'); btnCheck.onclick ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...