這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 在本文中,我們將探討如何使用 CSS 以最少的代碼創造出精美的 CSS 絲帶形狀,並最終實現下麵這個效果: 下麵我們使用html和css來實現這個效果。我們使用內容自適應方式佈局,不用擔心裡面的文字長度。本文介紹兩種絲帶:左側的絲帶稱為“ ...
這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助
在本文中,我們將探討如何使用 CSS 以最少的代碼創造出精美的 CSS 絲帶形狀,並最終實現下麵這個效果:
下麵我們使用html和css來實現這個效果。我們使用內容自適應方式佈局,不用擔心裡面的文字長度。本文介紹兩種絲帶:左側的絲帶稱為“摺疊絲帶”,右側的絲帶稱為“旋轉絲帶”。
通過CSS創建摺疊絲帶形狀
首先要實現摺疊 CSS 絲帶,先定義形狀的變數。
.ribbon { --r: 20px; /* 控制絲帶的切割效果 */ --s: 20px; /* 摺疊部分的尺寸 */ --c: #d81a14; /* 顏色控制 */ }
--r
和--s
這兩個變數控制形狀,--c
控制顏色。
如果要在CSS中實現多邊形,我們可以使用css的 clip-path
屬性。我們提前在圖形上添加一些填充內容避免文本被切割,然後使用clip-path
:
.ribbon { --r: 20px; /* 控制絲帶的切割效果 */ --s: 20px; /* 摺疊部分的尺寸 */ --c: #d81a14; /* 顏色控制 */ line-height: 1.6; /* 控制高度 */ padding-inline: 1.2lh calc(var(--r) + .2lh); background: var(--c); clip-path: polygon(1lh 0, 100% 0, calc(100% - var(--r)) 50%, 100% 100%, 100% 100%, 0 100%, 0 100%); }
使用 CSS lh 單位
很多同學可能不知道 lh
單位是什麼,它是與 line-height
值相對應的新單位。由於這裡使用了一行文本,所以設置 line-height
來控制元素的高度,因此 1lh
就等於元素的高度。所以在 clip-path
中,我們使用這個高度來切割等腰三角形的形狀。如下圖:
接著我們需要創建摺疊部分,需要使用 clip-path
更新上面的多邊形。 clip-path
可以切割元素邊界的外部區域,包括盒子陰影、輪廓、偽元素等。
在下麵示例中,利用 box-shadow
配合clip-path
來實現切割。通過更新 Xi
和 Yi
來切割多邊形的四個新點,其中三個點位於元素的外部區域。因為我們要切割的部分在外部,但是它是不可見的,這裡我們添加了大的 box-shadow
讓元素變得可見。代碼如下:
.ribbon { --r: 20px; /* 控制絲帶的切割效果 */ --s: 20px; /* 摺疊部分的尺寸 */ --c: #d81a14; /* 顏色控制 */ line-height: 1.6; /* 控制高度 */ padding-inline: 1.2lh calc(var(--r) + .2lh); background: var(--c); clip-path: polygon(1lh 0, 100% 0, calc(100% - var(--r)) 50%, 100% 100%, 1lh 100%, 1lh calc(100% + var(--s)), .5lh calc(100% + var(--s) + var(--r)), 0 calc(100% + var(--s)), 0 100%); box-shadow: 0 0 0 999px var(--c); /* 較大的陰影擴散半徑 */ }
最後通過引入漸變和另一個框陰影,就實現了陰影效果。到這裡我們的 CSS 絲帶形狀已經成型了。
現在介紹如何創建第二種形狀(綠色絲帶)。這裡使用相同的方法,用第一個多邊形並將其反轉一下。
這樣寫:
clip-path: polygon(X1 Y1, X2 Y2, ..., Xn Yn)
要獲得相反的形狀,我們將所有 Xi
更改為 100% - Xi
!在查看代碼之前,大家嘗試單獨使用第一個形狀的多邊形來實現這一點。
在上面的動畫中,當滑鼠懸停在形狀上時,可以看到漂亮的展開收起動畫。為了實現這一點,需要通過偏移一些點來更新懸停時的多邊形。這裡不需要重新編寫整個多邊形,可以重新定義一個 CSS 變數來控制偏移。
如果大家關註動畫部分,就會註意到有三個點向左移動,同時有三個點向下和向左移動。
修改 Xi
的點向左移動,修改 Yi
的點向下和向左移動來實現這一點。然後再修改 d
以控制這一運動:
.ribbon { --d: 0px; /* 這將控制偏移量 */ clip-path: polygon(calc(1lh + var(--d)) 0, 100% 0, calc(100% - var(--r)) 50%, 100% 100%, calc(1lh + var(--d)) 100%, calc(1lh + var(--d)) calc(100% + var(--s) + var(--d)), calc(.5lh + var(--d)) calc(100% + var(--s) + var(--r) + var(--d)), var(--d) calc(100% + var(--s) + var(--d)), var(--d) 100%); } .ribbon:hover { --d: .2lh; }
部分同學第一次看到這種多邊形,可能會感到困惑,因為它看起來有些複雜。我們從一個簡單的多邊形開始,然後逐步添加更多點和計算,最終得到這個複雜的多邊形。
創建旋轉的 CSS 絲帶形狀
現在讓我們處理第二種形狀。對於這種形狀,我們將使用新的三角函數以及 CSS 變數和 calc()
,方法與前一個形狀類似。為了理解這個形狀背後的邏輯,讓我們旋轉它並確保文本保持在一條直線上。
下麵添加了一些透明度以查看主要元素背後的部分,然後使用偽元素來創建這些部分。這裡添加了藍色輪廓來說明元素的區域。該形狀將由兩個變數控制:
.ribbon { --r: 30px; /* 控制絲帶的切割效果 */ --a: 15deg; /* 控制旋轉角度 */ }
其中 r
的作用與前一個形狀相同。a
將控制主要元素的旋轉。
下麵我們從主要元素開始說。從圖中我們可以看到,我們需要從每一面切割它,但是這次不能使用 clip-path
,我們將使用漸變顏色,其中需要切割的部分需要使用透明的顏色:
.ribbon { --r: 30px; /* 控制絲帶的切割效果 */ --a: 15deg; /* 控制旋轉角度 */ background: linear-gradient(calc(90deg + var(--a)), #0000 calc(1lh*sin(var(--a))), var(--c) 0 calc(100% - 1lh*sin(var(--a))), #0000 0 ); }效果如圖:
這裡的高度等於 1lh/cos(a)
。寬度等於 (100% - x)*cos(a)
,其中 100%
是主要元素的寬度,x
是我們帶有透明度的那一小部分,它等於 1lh*tan(a)
。
兩個偽元素具有相同的尺寸,代碼如下:
.ribbon:before, .ribbon:after { content: ""; position: absolute; height: calc(1lh/cos(var(--a))); width: calc(100%*cos(var(--a)) - 1lh*sin(var(--a))); }
在確定尺寸後,我們需要正確定位每個偽元素,並對其進行旋轉和切割:
.ribbon:before, .ribbon:after { content: ""; position: absolute; transform: translate3d(0,0,-1px); rotate: var(--a); height: calc(1lh/cos(var(--a))); width: calc(100%*cos(var(--a)) - 1lh*sin(var(--a))); background: color-mix (in srgb,var(--c),#000 40%); } h1:before { right: 0; top: 0; transform-origin: top right; clip-path: polygon(0 0,100% 0,100% 100%,0 100%,var(--r) 50%); } h1:after { left: 0; bottom: 0; transform-origin: bottom left; clip-path: polygon(0 0,100% 0,calc(100% - var(--r)) 50%,100% 100%,0 100%); }
這裡代碼應該比較清晰易懂,clip-path
的值應該也容易理解。要註意的是,我們使用了 color-mix()
函數,這個屬性允許創建主顏色的深色版本。現在如果我們將元素旋轉相反的方向,就會得到旋轉的 CSS 絲帶形狀。
完整代碼
<h1>I am a ribbon</h1> <h1 class="alt">I am a ribbon</h1>
@property --a { syntax: "<angle>"; initial-value: 0deg; inherits: true; } h1 { --r: 30px; /* control the cutout of the ribbon */ --a: 15deg; /* control the rotation (only positive values) */ --c: #d81a14; line-height: 1.6; /* this will control the height */ padding-inline: .5lh; /* OR calc(tan(var(--a))*1.5lh) */ color: #fff; background: linear-gradient(calc(90deg + var(--a)), #0000 calc(1lh*sin(var(--a)) - 1px), var(--c) calc(1lh*sin(var(--a))) calc(100% - 1lh*sin(var(--a))), #0000 calc(100% - 1lh*sin(var(--a)) + 1px) ); position: relative; rotate: calc(-1*var(--a)); transform-style: preserve-3d; transition: --a .5s; cursor: pointer; white-space: nowrap; } h1.alt { --c: #8FBE00; rotate: var(--a); background: linear-gradient(calc(90deg - var(--a)), #0000 calc(1lh*sin(var(--a)) - 1px), var(--c) calc(1lh*sin(var(--a))) calc(100% - 1lh*sin(var(--a))), #0000 calc(100% - 1lh*sin(var(--a)) + 1px) ); } h1:before, h1:after{ content: ""; position: absolute; transform: translate3d(0,0,-1px); rotate: var(--a); height: calc(1lh/cos(var(--a))); width: calc(100%*cos(var(--a)) - 1lh*sin(var(--a))) ; background: color-mix(in srgb,var(--c),#000 40%); pointer-events: none; } h1.alt:before, h1.alt:after { rotate: calc(-1*var(--a)); } h1:before { right: 0; top: 0; transform-origin: top right; clip-path: polygon(0 0,100% 0,100% 100%,0 100%,var(--r) 50%); } h1.alt:before { bottom: 0; top: auto; transform-origin: bottom right; } h1:after { left: 0; bottom: 0; transform-origin: bottom left; clip-path: polygon(0 0,100% 0,calc(100% - var(--r)) 50%,100% 100%,0 100%); } h1.alt:after { top: 0; bottom: auto; transform-origin: top left; } h1:hover { --a: 0deg; } /* we fallback to something else if lh is not supported 1lh = 1.6em (the line-height value) */ @supports not (height:1lh) { h1 { padding-inline: .8em; background: linear-gradient(calc(90deg + var(--a)), #0000 calc(1.6em*sin(var(--a)) - 1px), var(--c) calc(1.6em*sin(var(--a))) calc(100% - 1.6em*sin(var(--a))), #0000 calc(100% - 1.6em*sin(var(--a)) + 1px) ); } h1.alt { background: linear-gradient(calc(90deg - var(--a)), #0000 calc(1.6em*sin(var(--a)) - 1px), var(--c) calc(1.6em*sin(var(--a))) calc(100% - 1.6em*sin(var(--a))), #0000 calc(100% - 1.6em*sin(var(--a)) + 1px) ); } h1:before, h1:after{ height: calc(1.6em/cos(var(--a))); width: calc(100%*cos(var(--a)) - 1.6em*sin(var(--a))) ; } } body { margin: 0; min-height: 100vh; display: grid; place-content: center; grid-auto-flow: column; gap: 50px; } h1 { font-family: sans-serif; text-transform: uppercase; font-size: 2.5rem; }