CSS样式——霓虹灯开关按钮

整体效果

效果展示

💎知识点:

1️⃣ 使用 display: gridplace-items: center 来实现居中对齐,使整个页面的内容在视口中居中显示。

2️⃣ 结合使用 linear-gradientradial-gradient 来创建复杂的背景效果。使用多个渐变可以让背景具有层次感。

3️⃣ 使用 @property 定义自定义属性 --x--c,以便在组件中灵活地控制角度和颜色。这种方式可以提高代码的可维护性和可读性。

4️⃣ 通过 ::before::after 创建额外的视觉效果,比如内阴影和边框效果。这种方法常用于增加元素的装饰性,而不需要额外的HTML结构。

5️⃣ 定义 :hover:checked 状态的样式,提供用户交互反馈。这些效果可以使按钮或其他元素在用户操作时表现出明显的变化,提升用户体验。

6️⃣ 使用 @media 查询来处理不同的媒体类型,如打印和减少运动效果的偏好。这使得在不同环境下,页面能够以适当的方式展示。

7️⃣ 使用 transition 属性来实现平滑的过渡效果,提升视觉效果的流畅性。通过设置不同的过渡时长,可以控制元素状态改变的速度。

🔑思路:

定义好按钮通用样式,通过使用网格布局和渐变背景,结合自定义属性和伪元素,创建了一个美观且具有交互性的UI组件。实现了平滑的过渡效果,并在用户悬停或选中时提供明显的视觉反馈,同时通过媒体查询确保在不同环境下的适应性,整体设计注重视觉层次感和用户体验。


核心代码部分,简要说明写法思路;完整代码在最后,可直接复制到本地运行。

核心代码

html 代码

1
<input type="checkbox" role="switch" class="neon" />

input 主体。

css 部分代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
body {
display: grid; /* 使用网格布局 */
place-items: center; /* 网格项居中对齐 */
overflow: hidden; /* 隐藏溢出内容 */
margin: 0; /* 去掉默认外边距 */
height: 100vh; /* 设置高度为视口高度 */
background-image: linear-gradient(45deg, #223, #112); /* 线性渐变背景 */
background: radial-gradient(at 100% 0, #fff2, #fff0 50%), /* 第一个径向渐变 */
radial-gradient(at 0% 100%, #0002, #0000 50%), /* 第二个径向渐变 */
#545153; /* 固定背景颜色 */
}

@property --x {
syntax: '<angle>'; /* 定义属性的语法为角度 */
inherits: true; /* 继承父元素的属性 */
initial-value: 1deg; /* 初始值为1度 */
}

@property --c {
syntax: '<color>'; /* 定义属性的语法为颜色 */
inherits: true; /* 继承父元素的属性 */
initial-value: #0000; /* 初始值为透明 */
}

.neon {
--x: 1deg; /* 定义变量x */
--c: #0000; /* 定义变量c */
font-size: 3rem; /* 字体大小 */
appearance: none; /* 去掉默认样式 */
position: relative; /* 设置相对定位 */
aspect-ratio: 2; /* 设置纵横比为2 */
border-radius: 100em; /* 圆角 */
background: linear-gradient(to bottom right, #0001, #0000), #444143; /* 渐变背景 */
width: 3em; /* 宽度 */
box-shadow: inset 0 0 0.25em -0.25em #0008, /* 内阴影效果 */
inset 0.05em 0.05em 0.2em #000811,
inset -0.05em -0.05em 0.15em 0.05em #ccc1,
0 0 0 0.11em #545153; /* 外阴影效果 */
transition: --x 0.5s, --c 0.35s, box-shadow 0.5s; /* 过渡效果 */
filter: drop-shadow(0 0 0.2em var(--c)); /* 投影效果 */
cursor: pointer; /* 鼠标悬停时为手型光标 */
}

.neon::before {
content: ""; /* 伪元素内容为空 */
position: absolute; /* 设置绝对定位 */
height: 80%; /* 高度为80% */
aspect-ratio: 1; /* 设置纵横比为1 */
top: 50%; /* 垂直居中 */
left: 25%; /* 左边距25% */
transform: translate(-50%, -50%); /* 位置偏移,居中对齐 */
background: #545153; /* 背景颜色 */
box-shadow: inset -0.05em -0.05em 0.1em #0008, /* 内阴影效果 */
inset 0.05em 0.05em 0.1em #ffffff22,
inset 0.05em 0em 0.1em -0.065em var(--c),
0.1em 0.1em 0.15em #000c; /* 外阴影效果 */
border-radius: 50%; /* 圆形边框 */
transition: left 0.5s, box-shadow 0.15s; /* 过渡效果 */
}

.neon::after {
content: ""; /* 伪元素内容为空 */
position: absolute; /* 设置绝对定位 */
top: 50%; /* 垂直居中 */
left: 50%; /* 水平居中 */
transform: translate(-50%, -50%); /* 位置偏移,居中对齐 */
width: calc(100% + 0.25em); /* 宽度略大于100% */
height: calc(100% + 0.25em); /* 高度略大于100% */
border: 0.1em solid #0ff; /* 边框样式 */
border-radius: 100em; /* 圆形边框 */
-webkit-mask: conic-gradient(from calc(270deg - var(--x)), #000 calc(2 * var(--x)), #0001 0); /* 使用圆锥渐变作为遮罩 */
box-shadow: 0 0 0 2em #0000; /* 透明阴影效果 */
}

.neon:hover {
--x: 3deg; /* 悬停时x的值变为3度 */
--c: #0ff5; /* 悬停时c的颜色变为明亮的青色 */
box-shadow: inset 0 0 0.25em -0.25em #0008, /* 内阴影效果 */
inset 0.05em 0.05em 0.2em #000811,
inset -0.05em -0.05em 0.15em 0.05em #ccc1,
0 0 0.05em 0.075em #545153; /* 外阴影效果 */
}

.neon:checked {
--x: 180deg; /* 选中时x的值变为180度 */
--c: #0fff; /* 选中时c的颜色变为白色 */
box-shadow: inset 0 0 0.25em -0.25em #0008, /* 内阴影效果 */
inset 0.05em 0.05em 0.2em #000811,
inset -0.05em -0.05em 0.15em 0.05em #ccc1,
0 0 0.1em 0.05em #545153; /* 外阴影效果 */
}

.neon:checked::before {
left: 75%; /* 选中时伪元素位置移动到75% */
box-shadow: inset -0.05em -0.05em 0.1em #0008, /* 内阴影效果 */
inset 0.05em 0.05em 0.1em #ffffff22,
inset -0.05em 0em 0.1em -0.035em var(--c),
0.1em 0.1em 0.15em #000c; /* 外阴影效果 */
}

.neon[disabled] {
opacity: 0.25; /* 禁用时透明度为25% */
}

@media print {
.neon {
background: none; /* 打印时背景不显示 */
}

.neon,
.neon::before,
.neon::after {
-webkit-print-color-adjust: exact; /* 打印时颜色调整为精确值 */
print-color-adjust: exact; /* 打印时颜色调整为精确值 */
}
}

@media (prefers-reduced-motion) {
.neon,
.neon::before,
.neom::after {
transition: none !important; /* 禁用过渡效果 */
animation: none !important; /* 禁用动画效果 */
}
}
  1. body样式设置了整个页面的布局,使用CSS Grid将内容居中显示,并设置了全屏高度和渐变背景色。
  1. 接下来定义了两个自定义CSS属性(也称为CSS变量)--x--c,分别用于控制旋转角度和颜色。这些变量可以在整个样式表中重复使用,并且可以被继承。
  1. .neon类定义了按钮的基本样式,包括字体大小、无外观(appearance)、相对定位、宽高比、圆角边框、背景渐变、阴影效果、过渡动画、滤镜效果以及鼠标悬停时的指针样式。
  1. .neon::before和.neon::after是伪元素,用于创建按钮内部的额外视觉效果。::before伪元素创建了一个绝对定位的背景块,而::after伪元素则创建了一个带有边框和遮罩效果的圆形。
  1. .neon:hover.neon:checked定义了按钮在鼠标悬停和被选中时的样式变化,包括旋转角度、颜色和阴影的变化。
  1. .neon[disabled]样式用于定义当按钮被禁用时的样式,即降低其不透明度。
  1. @media print媒体查询用于定义打印时的样式,这里移除了背景并确保颜色能够准确打印。
  1. 最后一个媒体查询@media (prefers-reduced-motion)用于响应那些偏好减少动画的用户,它会禁用所有的过渡和动画效果。

完整html代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>霓虹灯</title>
<link rel="stylesheet" href="neon.css">
</head>

<body>
<input type="checkbox" role="switch" class="neon" />
</body>

</html>