记录--纯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;
}
本文转载于:
https://juejin.cn/post/7288178532861345832
如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。
记录--纯CSS实现骚气红丝带的更多相关文章
- 摘记 史上最强大的40多个纯CSS绘制的图形(一)
今天在国外的网站上看到了很多看似简单却又非常强大的纯CSS绘制的图形,里面有最简单的矩形.圆形和三角形,也有各种常见的多边形,甚至是阴阳太极和网站小图标,真的非常强大,分享给大家. Square(正方 ...
- 史上最强大的40多个纯CSS绘制的图形
Square(正方形) #square { width: 100px; height: 100px; background: red; } Rectangle(矩形) #rectangle { wid ...
- 40多个纯CSS绘制的图形
本文由码农网 – 陈少华原创,转载请看清文末的转载要求. 今天在国外的网站上看到了很多看似简单却又非常强大的纯CSS绘制的图形,里面有最简单的矩形.圆形和三角形,也有各种常见的多边形,甚至是阴阳太极和 ...
- CSS之纯CSS画的基本图形(矩形、圆形、三角形、多边形、爱心、八卦等)
图形包括基本的矩形.圆形.椭圆.三角形.多边形,也包括稍微复杂一点的爱心.钻石.阴阳八卦等.当然有一些需要用到CSS3的属性,所以在你打开这篇文章的时候,我希望你用的是firefox或者chrome, ...
- 纯css实现京东导航菜单
纯CSS代码实现导航菜单,推荐在chrome预览! 预览请点击这里:mygithub <!doctype html> <html lang="en"> &l ...
- 详解纯css实现瀑布流(multi-column多列及flex布局)
瀑布流的布局自我感觉还是很吸引人的,最近又看到实现瀑布流这个做法,在这里记录下,特别的,感觉flex布局实现瀑布流还是有点懵的样子,不过现在就可以明白它的原理了 1.multi-column多列布局实 ...
- 纯css实现打字效果
概述 很早以前就在别人的博客上面看到打字动画了,觉得非常炫酷,以为是用js做的,找了半天也没找到js在哪里.今天看<css揭秘>,碰巧看到书上打字动画的实现了,而且是纯css实现的!我参考 ...
- 史上最强大的40多个纯CSS绘制的图形[转]
今天在国外的网站上看到了很多看似简单却又非常强大的纯CSS绘制的图形,里面有最简单的矩形.圆形和三角形,也有各种常见的多边形,甚至是阴阳太极和网站小图标,真的非常强大,分享给大家. Square(正方 ...
- 纯CSS画的基本图形
图形包括基本的矩形.圆形.椭圆.三角形.多边形,也包括稍微复杂一点的爱心.钻石.阴阳八卦等.当然有一些需要用到CSS3的属性,所以在你打开这篇文章的时候,我希望你用的是firefox或者chrome, ...
- 纯css实现Magicline Navigation(下划线动画导航菜单)
看别人网站的时候,看到一种导航菜单的动画,觉得很有意思,就仔细研究起来. 目前见过的动画有三种:水平下划线动画导航.水平背景动画导航.垂直动画导航,他们实现思路都是一样的,都是依赖 css3的同级通用 ...
随机推荐
- MySQL-正则表达式规范
MySQL中的正则表达式采用的是PCRE的规范,匹配时按字符进行. RLIKE 您可以使用RLIKE语句匹配正则表达式,支持的元字符如下表所示. 元字符 说明 ^ 行首. $ 行尾. . 任意字符. ...
- Skywalking-Aop Docker单机环境搭建
1.OAP-SERVER和UI环境搭建 本次搭建是基于MySQL进行持久化,因此需要提前准备好一个MySQL容器 (MySQL容器部署略过).如有错误还请指正. 1.1 OAP服务搭建 拉取skywa ...
- ES6学习 第三章 字符串的扩展
前言 本章主要是内容为是 ES6 对字符串的改造和增强. 本章记录字符串的扩展常用重点部分,不常用知识稍作记录. 本章原文链接: 字符串的扩展 模板字符串(template string) ES6字符 ...
- C++ 多线程的错误和如何避免(5)
要记得对加锁的临界区解锁 前提:在多个线程共享一块资源或者数据时,我们需要加上互斥锁来保护临界区(否则出现数据未定义的行为) 问题:我们往往在写了很多代码之后忘记 unlock 互斥锁,那么等待该资源 ...
- 硬件开发笔记(三):硬件开发基本流程,制作一个USB转RS232的模块(二):设计原理图库
前言 上一篇了解了基本的过程,选型了相关的芯片,本篇描述原理图的设计过程,在原理图设计之前或者过程中需要不断新增原理图元器件. Allegro.OrCad Cadence公司针对PCB方面 ...
- Ubuntu 安装 Python3.6.7
注意: 不要卸载ubuntu自带的python版本: ubuntu下不同版本的python可以共存,可直接安装python3.6. 1.升级包索引和软件 sudo apt update sudo ap ...
- 解读平台工程,DevOps真的死了吗?不,它只是换了个马甲而已,弥补了DevOps空心理论,让DevOps继续发展壮大
最**台工程这个概念越来越火爆,Gartner 的预测,到 2026 年,80% 的软件工程组织将拥有*台工程团队,来提供内部服务.组件和应用程序交付工具,作为可重复使用的资源.本篇文章将带你走进*台 ...
- 【LeetCode回溯算法#09】全排列,排列问题以及其中涉及的去重操作
全排列 力扣题目链接 给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 .你可以 按任意顺序 返回答案. 示例 1: 输入:nums = [1,2,3] 输出:[[1,2,3],[1, ...
- 04、RS232 协议介绍
从之前的学习,我们知道了 SECS-I 使用的 RS232 来进行数据的传输,那我们也初略的了解下 RS232. 这一篇不用看也可以. 这是最低的协议层.它定义了设备上的物理接口.它是基于RS-232 ...
- redis-cluster 性能调优
关闭RDB防止fork进程的内存溢出问题 save "" appendonly=yes 防止某个节点挂掉,整个cluster挂掉的问题 cluster-require-full-c ...