一,效果
二,代码
1,搭个框架
主题是一个圆角矩形,其中有垂直、水平居中的文字。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>霓虹灯卡片 - 步骤1</title>
<style>
.card {
width: 200px;
height: 300px;
background-color: #191c29;
display: flex;
justify-content: center;
align-items: center;
color: white;
font-family: sans-serif;
}
</style>
</head>
<body>
<div class="card">Magic Card</div>
</body>
</html>
- 卡片尺寸设置为固定的200x300像素。
- 使用
display: flex
和justify-content
、align-items
使文字元素在弹性盒子中沿水平主轴和垂直主轴上剧中。
效果:
2,实现交互效果
鼠标悬停效果增加交互性,为用户提供视觉反馈。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>霓虹灯卡片 - 步骤2</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #212534;
}
.card {
width: 200px;
height: 300px;
background-color: #191c29;
display: flex;
justify-content: center;
align-items: center;
color: rgba(88, 199, 250, 0);
font-family: cursive;
border-radius: 6px;
cursor: pointer;
transition: color 0.5s;
}
.card:hover {
color: rgba(88, 199, 250, 1);
}
</style>
</head>
<body>
<div class="card">Magic Card</div>
</body>
</html>
- 为body添加了样式,使卡片在页面中居中。
- 给 .card 添加了
border-radius
来创建圆角。 - 设置
cursor: pointer
,提示用户卡片是可点击的。 - 初始文字颜色设置为透明,添加
transition
指定过度效果。 - 在
:hover
状态下改变文字颜色,结合过渡效果实现从字体透明到不透明的变化。
效果:
3,添加基本的霓虹边框效果
添加一个标色的边框不太好实现,,但用一个为元素来添加一个被遮住的变色元素确实相对容易的。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>霓虹灯卡片 - 步骤3</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #212534;
}
.card {
width: 200px;
height: 300px;
background-color: #191c29;
display: flex;
justify-content: center;
align-items: center;
color: rgba(88, 199, 250, 0);
font-family: cursive;
border-radius: 6px;
cursor: pointer;
transition: color 0.5s;
position: relative;
}
.card:hover {
color: rgba(88, 199, 250, 1);
}
.card::before {
content: "";
position: absolute;
top: -2px;
left: -2px;
right: -2px;
bottom: -2px;
background: linear-gradient(45deg, #5ddcff, #3c67e3, #4e00c2);
z-index: -1;
border-radius: 8px;
}
</style>
</head>
<body>
<div class="card">Magic Card</div>
</body>
</html>
- 给.card添加了
position: relative
,为绝对定位的伪元素做准备。 - 伪元素
::before
被用作卡片的装饰性边框。通过background: linear-gradient(45deg, #5ddcff, #3c67e3, #4e00c2);
,这个伪元素创建了一个带有渐变色的背景。 - 伪元素用
position: absolute;
和四个方向的top: -2px; left: -2px; right: -2px; bottom: -2px;
设置,让这个伪元素略微超出了卡片的边界,形成了一个围绕卡片的视觉边框效果。 - 伪元素设置了
z-index: -1;
,使其背景在主卡片内容(文字)下方显示,从而增强了卡片的层次感和立体感。
伪元素的作用总结:
- 视觉效果: 通过伪元素实现了卡片周围的动态渐变边框和发光效果,增强了视觉吸引力。
- 分离内容与装饰: 使用伪元素可以将装饰性元素与实际内容分离,避免在 HTML 中添加冗余的结构元素。
- 简化代码: 不需要在 HTML 中额外添加元素就能实现复杂的效果,使代码更简洁、更易维护。
效果:
4,添加旋转动画
既然卡片元素后面是一个伪元素,那么就可以通过转动这个伪元素来实现灯光流转。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>霓虹灯卡片 - 步骤4</title>
<style>
@property --rotate {
syntax: "<angle>";
initial-value: 132deg;
inherits: false;
}
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #212534;
}
.card {
width: 200px;
height: 300px;
background-color: #191c29;
display: flex;
justify-content: center;
align-items: center;
color: rgba(88, 199, 250, 0);
font-family: cursive;
border-radius: 6px;
cursor: pointer;
transition: color 0.5s;
position: relative;
}
.card:hover {
color: rgba(88, 199, 250, 1);
}
.card::before {
content: "";
position: absolute;
top: -2px;
left: -2px;
right: -2px;
bottom: -2px;
background: linear-gradient(var(--rotate), #5ddcff, #3c67e3 43%, #4e00c2);
z-index: -1;
border-radius: 8px;
animation: spin 2.5s linear infinite;
}
@keyframes spin {
0% {
--rotate: 0deg;
}
100% {
--rotate: 360deg;
}
}
</style>
</head>
<body>
<div class="card">Magic Card</div>
</body>
</html>
- 我们定义了一个新的CSS属性
--rotate
,使用@property
规则。这允许我们在动画中平滑地过渡角度值。 - 在 .card::before 伪元素中,我们将
linear-gradient
的第一个参数改为var(--rotate)
。这意味着渐变的角度现在由--rotate
变量控制。 - 我们为 .card::before 添加了
animation: spin 2.5s linear infinite;
。这开启了一个名为 “spin” 的动画,持续2.5秒,线性变化,无限循环。 - 定义了
@keyframes spin
,它在动画过程中将--rotate
从 0 度变化到 360 度。
@property --rotate
是一种用于定义自定义 CSS 属性(也称为 CSS 变量)的声明。这是一个较新的 CSS 特性,称为 CSS Properties and Values API,它允许你为自定义属性定义类型、安全值、继承行为和初始值等信息。
这里详细解释一下:
@property --rotate {
syntax: "<angle>";
initial-value: 132deg;
inherits: false;
}
syntax:
- 定义了这个自定义属性所接受的值的类型。这里的 <angle> 指定 --rotate 变量应该接受一个角度值(如 45deg、90deg 等)。
- 这种类型约束可以防止错误的值被赋给该变量。
initial-value:
- 定义了 --rotate 变量的初始值。如果该变量在某个元素中没有被设置,那么它将默认使用这个初始值。
- 在这个例子中,--rotate 的初始值是 132deg。
inherits:
- 决定这个自定义属性是否应该从父元素继承。默认情况下,CSS 自定义属性是继承的。
- 这里设置为 false,意味着子元素不会自动继承这个变量的值。
@keyframes spin {
0% {
--rotate: 0deg;
}
100% {
--rotate: 360deg;
}
}
定义动画: @keyframes spin 定义了名为 spin 的动画,描述了从动画开始 (0%) 到动画结束 (100%) 的变化过程。
关键帧的定义:
- 0% 表示动画的起点。
- 100% 表示动画的终点。
- 在这个动画中,--rotate 变量从 0deg 增加到 360deg,也就是说,整个动画会让线性渐变旋转一整圈。
5,添加发光效果
通过添加一个发光效果来进一步增强霓虹灯的视觉冲击力。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>霓虹灯卡片 - 步骤5</title>
<style>
@property --rotate {
syntax: "<angle>";
initial-value: 132deg;
inherits: false;
}
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #212534;
}
.card {
width: 200px;
height: 300px;
background-color: #191c29;
display: flex;
justify-content: center;
align-items: center;
color: rgba(88, 199, 250, 0);
font-family: cursive;
border-radius: 6px;
cursor: pointer;
transition: color 0.5s;
position: relative;
}
.card:hover {
color: rgba(88, 199, 250, 1);
}
.card::before,
.card::after {
content: "";
position: absolute;
top: -2px;
left: -2px;
right: -2px;
bottom: -2px;
background: linear-gradient(var(--rotate), #5ddcff, #3c67e3 43%, #4e00c2);
z-index: -1;
border-radius: 8px;
animation: spin 2.5s linear infinite;
}
.card::after {
filter: blur(50px);
}
@keyframes spin {
0% {
--rotate: 0deg;
}
100% {
--rotate: 360deg;
}
}
</style>
</head>
<body>
<div class="card">Magic Card</div>
</body>
</html>
- 我们添加了一个新的伪元素 .card::after,它与 .card::before 具有相同的基本样式。
- 在 .card::after 中,我们添加了
filter: blur(50px);
,将模糊或颜色偏移等图形效果应用于元素,这创建了一个模糊效果,模拟霓虹灯的发光。 - 两个伪元素都使用相同的动画,创造出同步旋转的效果。
伪元素 ::before
和 ::after
都是用于在 HTML 元素内容之前或之后插入内容的 CSS 工具。它们在功能和用法上非常相似,但有一些关键的区别。
1. 插入内容的位置
::before:
- ::before 用于在元素内容的前面插入内容。
- 插入的内容位于元素内容的最前面,也就是元素的实际内容之前。
::after:
- ::after 用于在元素内容的后面插入内容。
- 插入的内容位于元素内容的最后面,也就是元素的实际内容之后。
2. 使用场景
::before:
- 通常用于在元素之前添加装饰性内容、图标、引号等。例如,可以用来添加项目符号、引导符号等。
- 例如,给一个段落添加一个引号:
p::before {
content: "“";
}
::after:
- 常用于在元素后添加内容,或者与 ::before 一起配合创建更复杂的效果,如在元素前后添加装饰性线条、边框等。
- 例如,给一个段落添加一个引号结束符号:
p::after {
content: "”";
}
3. 显示优先级
- 层叠顺序:
- 通常,::before 和 ::after 伪元素的层叠顺序由其定义的位置决定。
- ::before 在 ::after 之前显示。如果 ::before 和 ::after 的内容有重叠,::before 的内容会在 ::after 的内容下方显示。
4. 典型用法示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Before and After Example</title>
<style>
.box {
position: relative;
padding: 20px;
background-color: #f0f0f0;
border: 2px solid #000;
width: 200px;
text-align: center;
}
.box::before {
content: "Before: ";
color: red;
}
.box::after {
content: " :After";
color: blue;
}
</style>
</head>
<body>
<div class="box">Content</div>
</body>
</html>
- 效果:
- 在 Content 前面会显示红色的文本 Before: ,在 Content 后面会显示蓝色的文本 :After。
5. 共同点
- 内容插入: ::before 和 ::after 都可以通过 content 属性插入文本、图像或其他内容。
- 样式控制: 两者都可以像普通元素一样应用样式,例如设置颜色、背景、边框等。
- 定位: 通常,它们和原始元素一起使用 position: relative;,而 ::before 和 ::after 通常设置为 position: absolute; 来进行精确定位。
总结:
- ::before 用于在元素内容的前面插入内容。
- ::after 用于在元素内容的后面插入内容。
- 它们通常配合使用来在元素的前后插入装饰性或功能性内容,但顺序不同:::before 的内容在元素内容前显示,::after 的内容在元素内容后显示。
三,继续优化
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>霓虹灯卡片 - 最终版</title>
<style>
@property --rotate {
syntax: "<angle>";
initial-value: 132deg;
inherits: false;
}
:root {
--card-height: 65vh;
--card-width: calc(var(--card-height) / 1.5);
}
body {
min-height: 100vh;
background: #212534;
display: flex;
align-items: center;
flex-direction: column;
padding-top: 2rem;
padding-bottom: 2rem;
box-sizing: border-box;
}
.card {
background: #191c29;
width: var(--card-width);
height: var(--card-height);
padding: 3px;
position: relative;
border-radius: 6px;
justify-content: center;
align-items: center;
text-align: center;
display: flex;
font-size: 1.5em;
color: rgb(88 199 250 / 0%);
cursor: pointer;
font-family: cursive;
}
.card:hover {
color: rgb(88 199 250 / 100%);
transition: color 1s;
}
.card:hover:before, .card:hover:after {
animation: none;
opacity: 0;
}
.card::before {
content: "";
width: 104%;
height: 102%;
border-radius: 8px;
background-image: linear-gradient(
var(--rotate), #5ddcff, #3c67e3 43%, #4e00c2);
position: absolute;
z-index: -1;
top: -1%;
left: -2%;
animation: spin 2.5s linear infinite;
}
.card::after {
position: absolute;
content: "";
top: calc(var(--card-height) / 6);
left: 0;
right: 0;
z-index: -1;
height: 100%;
width: 100%;
margin: 0 auto;
transform: scale(0.8);
filter: blur(calc(var(--card-height) / 6));
background-image: linear-gradient(
var(--rotate), #5ddcff, #3c67e3 43%, #4e00c2);
opacity: 1;
transition: opacity .5s;
animation: spin 2.5s linear infinite;
}
@keyframes spin {
0% {
--rotate: 0deg;
}
100% {
--rotate: 360deg;
}
}
@media screen and (max-width: 600px) {
:root {
--card-height: 50vh;
}
}
</style>
</head>
<body>
<div class="card">Magic Card</div>
</body>
</html>
-
添加了
<meta name="viewport">
标签,确保页面在移动设备上正确显示。 -
使用 CSS 变量(
:root
)定义卡片尺寸,使其相对于视口高度。这样可以在不同大小的屏幕上保持合适的比例。 -
将固定的像素值替换为相对单位(如 vh 和 %)。
-
添加了媒体查询,在小屏幕设备上调整卡片大小。
@media screen and (max-width: 600px) { :root { --card-height: 50vh; } }
-
优化了悬停效果,使动画在悬停时停止,减少不必要的 CPU 使用。
.card:hover:before, .card:hover:after { animation: none; opacity: 0; } 1,animation: none; - 当鼠标悬停在卡片上时,这行代码会停止伪元素(:before 和 :after)的动画。 - 原本这些伪元素有一个持续运行的旋转动画(spin 2.5s linear infinite)。 - 停止动画可以减少 CPU 的使用,因为浏览器不需要继续计算和渲染动画帧。 2,opacity: 0; - 这行代码在鼠标悬停时使伪元素变为完全透明。 - 虽然这不直接关联到 CPU 使用,但它确实减少了需要渲染的内容,可能会略微提高性能。
效果: