这个页面实现了一个具有动画效果的菜单选择框,用户可以通过点击按钮选择不同的菜单选项。页面使用了SVG图标和CSS动画来增强视觉效果,整体设计风格现代且具有视觉吸引力。
大家复制代码时,可能会因格式转换出现错乱,导致样式失效。建议先少量复制代码进行测试,若未能解决问题,私信回复源码两字,我会发送完整的压缩包给你。
演示效果

HTML&CSS
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>公众号关注:前端Hardy</title>
<style>
@import "https://unpkg.com/normalize.css";
@import url("https://fonts.googleapis.com/css2?family=Fondamento&display=swap");
:root {
--color-space-dark: #191d32;
--color-space-support: #351e29;
--color-space: #282f44;
--color-dark-liver: #453a49;
--color-liver: #634570;
--color-catawba: #6d3b47;
--color-catawba-light: #8c516c;
--color-magenta: #ba2c73;
--color-lightest: #fafafa;
--orb-size: 110px;
--option-size: 80px;
--circle-size: 320px;
}
/* basic styling */
.potion-select {
background: none;
border: 0;
padding: 0;
&::picker-icon {
display: none;
}
}
select,
::picker(select) {
appearance: base-select;
box-shadow: none;
}
.potion-equipped {
anchor-name: --selectmenu;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
position: relative;
background: var(--color-dark-liver);
border: 4px dashed var(--color-space);
width: var(--orb-size);
aspect-ratio: 1;
border-radius: 50%;
cursor: pointer;
z-index: 10;
font-family: "Fondamento", cursive;
box-shadow: inset 0 1px 1px #ccc, inset 0 -1px 1px #aaa, 0 2px 4px -3px #666;
transition: box-shadow 0.3s ease-out, color 0.3s ease-out;
}
.potion-equipped:is(:hover, :focus) {
background: var(--color-liver);
box-shadow: rgba(50, 50, 93, 0.25) 0px 30px 60px -12px inset,
rgba(0, 0, 0, 0.3) 0px 18px 36px -18px inset;
}
.selected-value {
display: flex;
justify-content: center;
flex-direction: column;
color: var(--color-lightest);
}
.icon {
width: 30px;
height: 50px;
transform: rotate(20deg);
transition: transform 0.15s;
}
/* style options */
option {
--half-circle: calc(var(--circle-size) / -2);
display: flex;
align-items: center;
justify-content: center;
position: absolute;
top: 50%;
left: 50%;
width: var(--option-size);
height: var(--option-size);
margin: calc(var(--option-size) / -2);
background: var(--color-catawba);
border-radius: 50%;
cursor: grab;
opacity: 0;
z-index: 1;
font-family: "Fondamento", cursive;
box-shadow: inset 0 1px 1px #ccc, inset 0 -1px 1px #aaa, 0 2px 4px -3px #666;
transition: opacity 0.5s, box-shadow 0.3s, transform 0.5s;
pointer-events: all;
&::checkmark {
display: none;
}
&:checked {
background: var(--color-catawba-light);
}
&::before,
&::check {
display: none;
}
}
option:is(:hover, :focus) {
box-shadow: rgba(50, 50, 93, 0.25) 0px 30px 60px -12px inset,
rgba(0, 0, 0, 0.3) 0px 18px 36px -18px inset;
}
option:is(:hover, :focus, :checked) .icon {
transform: rotate(0);
}
option span {
position: absolute;
bottom: -30px;
left: 50%;
transform: translateX(-50%);
font-size: 1.1rem;
color: var(--color-lightest);
opacity: 0;
}
/* popover states */
::picker(select) {
--rotation-divide: calc(180deg / 2);
margin: 0;
padding: 0;
background: transparent;
border: none;
display: block;
position: fixed;
position-anchor: --selectmenu;
top: anchor(center);
left: anchor(center);
min-inline-size: var(--circle-size);
min-block-size: var(--circle-size);
transform: translate(-50%, -50%);
overflow: visible;
transition: overlay 0.5s, display 0.5s;
transition-behavior: allow-discrete;
}
select:open option span {
animation: fade-in 0.4s ease-out forwards 0.1s;
}
/* count circle placement */
.items:has(option:nth-child(2)) {
--rotation-divide: calc(360deg / 2);
}
.items:has(option:nth-child(3)) {
--rotation-divide: calc(360deg / 3);
}
.items:has(option:nth-child(4)) {
--rotation-divide: calc(360deg / 4);
}
.items:has(option:nth-child(5)) {
--rotation-divide: calc(360deg / 5);
}
.items:has(option:nth-child(6)) {
--rotation-divide: calc(360deg / 6);
}
option:nth-child(1) {
--deg: var(--rotation-divide);
--negative: calc(var(--deg) / -1);
}
option:nth-child(2) {
--deg: calc(var(--rotation-divide) * 2);
--negative: calc(var(--deg) / -1);
animation-delay: 0.05s;
}
option:nth-child(3) {
--deg: calc(var(--rotation-divide) * 3);
--negative: calc(var(--deg) / -1);
animation-delay: 0.1s;
}
option:nth-child(4) {
--deg: calc(var(--rotation-divide) * 4);
--negative: calc(var(--deg) / -1);
animation-delay: 0.15s;
}
option:nth-child(5) {
--deg: calc(var(--rotation-divide) * 5);
--negative: calc(var(--deg) / -1);
animation-delay: 0.2s;
}
option:nth-child(6) {
--deg: calc(var(--rotation-divide) * 6);
--negative: calc(var(--deg) / -1);
animation-delay: 0.25s;
}
/* thats enough potions for you! */
option:nth-child(1n + 7) {
display: none;
}
select:open option {
transform: rotate(var(--deg)) translate(var(--half-circle)) rotate(var(--negative));
opacity: 1;
}
@keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/* potion colors */
.icon-health {
--potion-color: red;
--support-color: darkred;
}
.icon-mana {
--potion-color: blue;
--support-color: darkblue;
}
.icon-stamina {
--potion-color: yellow;
--support-color: orange;
}
.icon-strength {
--potion-color: purple;
--support-color: indigo;
}
.icon-fortify {
--potion-color: lime;
--support-color: green;
}
.icon-frenzy {
--potion-color: hotpink;
--support-color: orchid;
}
/* general styles */
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
padding: 5vh 5vw;
font-family: "Fondamento", cursive;
background-image: radial-gradient(circle,
var(--color-space-dark),
var(--color-space-support));
}
</style>
</head>
<body>
<select class="potion-select" id="potion-select">
<button class="potion-equipped">
<selectedcontent class="selected-value"></selectedcontent>
</button>
<div class="items">
<div class="listwrapper">
<option value="health">
<div class="potion-holder">
<svg class="icon icon-health" aria-hidden="true">
<use xlink:href="#potion" />
</svg>
</div>
<span>Health</span>
</option>
<option value="mana">
<div class="potion-holder">
<svg class="icon icon-mana" aria-hidden="true">
<use xlink:href="#potion" />
</svg>
</div>
<span>Mana</span>
</option>
<option value="stamina">
<div class="potion-holder">
<svg class="icon icon-stamina" aria-hidden="true">
<use xlink:href="#potion" />
</svg>
</div>
<span>Stamina</span>
</option>
<option value="strength" selected>
<div class="potion-holder">
<svg class="icon icon-strength" aria-hidden="true">
<use xlink:href="#enhancement" />
</svg>
</div>
<span>Strength</span>
</option>
<option value="fortify">
<div class="potion-holder">
<svg class="icon icon-fortify" aria-hidden="true">
<use xlink:href="#enhancement" />
</svg>
</div>
<span>Fortify</span>
</option>
<option value="frenzy">
<div class="potion-holder">
<svg class="icon icon-frenzy" aria-hidden="true">
<use xlink:href="#enhancement" />
</svg>
</div>
<span>Frenzy</span>
</option>
</div>
</div>
</select>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
style="width: 0; height: 0; visibility: hidden; position: absolute;" aria-hidden="true">
<symbol id="potion" viewBox="0 0 18 30">
<g>
<path fill="#e0e1e0"
d="M15.6 15.96h-.07c-.18-.02-.35-.04-.51-.05-.04 0-.08 0-.12-.01l-.43-.03c-.16-.01-.31-.02-.45-.02h-.28c-1.79-.09-3.58.3-5.16 1.15-1.48.71-3 1.44-7 1.1l-.36-.03-.21-.03c.85-2.24 2.63-4 4.89-4.82.05-.02.09-.07.09-.12V6.03c0-.07-.05-.13-.12-.13-.77 0-1.39-.63-1.38-1.39 0-.76.62-1.38 1.38-1.38h6.06c.77 0 1.39.63 1.38 1.39 0 .76-.62 1.38-1.38 1.38-.07 0-.13.05-.13.12v7.07c0 .05.03.1.09.12 1.48.53 2.78 1.48 3.73 2.74Z" />
<path fill="#cac8c7"
d="M12 13.21s-.08-.07-.08-.12V6.03c0-.07.05-.12.12-.13.36 0 .7-.15.94-.41.25-.26.39-.61.39-.98a1.37 1.37 0 0 0-1.34-1.39L10.99 3c.46.22 0 .44 0 1 0 .37.25-.26 0 0s-.15 0-.5 0c-.07 0-.5-.07-.5 0v8.97c0 .05.03.1.08.12 1.44.54 2.69 1.49 3.59 2.74h-.07c-.17-.02 1.41.17.19.01-.09-.01.17 0 .27 0 .14 0 .29.01.44.02.14 0 .28.02.42.03.04 0 .08 0 .12.01.16.02.33.03.5.05h.07c-.9-1.25-2.15-2.2-3.59-2.74Z" />
<path fill="var(--potion-color)"
d="M17.33 21.17c0 4.67-3.77 8.46-8.44 8.47S.43 25.87.42 21.2v-.03c0-.98.16-1.96.48-2.89.12.02.24.03.36.04l.28.03.35.03c.78.06 1.45.07 2.06.06.32-.01.61-.03.88-.06.62-.05 1.24-.17 1.84-.34.18-.05.35-.11.51-.16.51-.19 1-.41 1.48-.65.38-.18.75-.36 1.16-.52.16-.07.33-.13.5-.18 1.46-.42 2.98-.55 4.49-.38.31.03.64.06.98.1 1 1.45 1.54 3.17 1.53 4.94Z" />
<path fill="var(--support-color)"
d="M15.8 16.23c-.34-.04-.67-.07-.98-.1-.23-.02-.44-.03-.65-.04a8.559 8.559 0 0 1 1.24 4.49 8.412 8.412 0 0 1-9.94 8.31c4.26 1.89 9.25-.04 11.14-4.31.48-1.08.72-2.25.72-3.43 0-1.76-.52-3.49-1.53-4.94Z" />
<path fill="#616262" d="M12 .5H6L7 4h4l1-3.5z" />
<path fill="#4d4d4d" d="M10.71.5 10 3H6.71L7 4h4l1-3.5h-1.29z" />
<path
d="M2.74 23.5c-.23 0-.43-.16-.49-.38C2.08 22.43 2 21.72 2 21c0-.35.02-.71.06-1.06.03-.27.28-.47.55-.44.27.03.47.28.44.55-.03.31-.05.63-.05.94 0 .63.07 1.27.22 1.88.06.27-.1.54-.37.6-.04 0-.08.01-.12.01ZM5 26.5a.46.46 0 0 1-.33-.13c-.37-.32-.71-.68-1.01-1.06-.17-.22-.14-.53.08-.7s.53-.14.7.08c.27.34.57.65.9.94.21.18.23.5.04.71a.48.48 0 0 1-.37.17Z"
class="cls-5" />
</g>
<path fill="#010101"
d="M12.5 12.66V6.44A2.012 2.012 0 0 0 13.94 4c-.23-.88-1.02-1.5-1.94-1.5h-.05l.53-1.86a.501.501 0 0 0-.34-.62C12.09 0 12.05 0 12 0H6c-.28 0-.5.22-.5.5 0 .05 0 .09.02.14l.53 1.86H6c-1.1 0-2 .9-2 2 0 .91.62 1.71 1.5 1.94v6.22A8.845 8.845 0 0 0 0 21a9 9 0 0 0 18 0 8.845 8.845 0 0 0-5.5-8.34ZM11.34 1l-.71 2.5H7.38L6.67 1h4.67ZM6.17 13.47c.2-.07.33-.26.33-.47V6c0-.28-.22-.5-.5-.5-.55 0-1-.45-1-1s.45-1 1-1h.34l.18.64c.06.21.26.36.48.36h4c.22 0 .42-.15.48-.36l.18-.64H12c.55 0 1 .45 1 1s-.45 1-1 1c-.28 0-.5.22-.5.5v7c0 .21.13.4.33.47 1.12.4 2.14 1.06 2.96 1.92-3.41-.23-4.86.46-6.27 1.14-1.49.72-2.91 1.39-6.79 1.05a7.736 7.736 0 0 1 4.43-4.1ZM9 29c-4.42 0-7.99-3.58-8-8 0-.83.12-1.66.36-2.46.86.08 1.61.12 2.28.12 1.85.06 3.68-.37 5.31-1.24 1.47-.7 2.87-1.37 6.7-.96a8.116 8.116 0 0 1 1.34 4.53c0 4.42-3.58 7.99-8 8Z" />
</symbol>
<symbol id="enhancement" viewBox="0 0 19 30.11">
<g>
<path fill="#e0e1e0"
d="M14.11 15.55c-2.7-.19-3.53.38-4.4.99-.89.61-1.81 1.25-5.04 1.06l2.63-6.23.02-.11V5.72c0-.13-.11-.21-.24-.22-.62 0-1.13-.56-1.13-1.25S6.46 3 7.09 3h4.81s.06 0 .09-.02c.03.01.06.02.1.02h.45c.63 0 1.14.56 1.14 1.25s-.51 1.25-1.14 1.25c-.12 0-.23.11-.23.25v5.5l.02.11 1.76 4.18Z" />
<path fill="#cac8c7"
d="M12.01 2.98s-.06.02-.09.02h-1.38c.65.04 1.14.6 1.1 1.25.04.65-.46 1.21-1.1 1.25-.13 0-.23.12-.22.25v5.5l.02.12 1.71 4.18c1.33-.3-.62-.19 2 0l-1.71-4.18-.02-.12v-5.5c0-.13.09-.24.22-.25.65-.04 1.14-.6 1.1-1.25.04-.65-.46-1.21-1.1-1.25" />
<path fill="var(--potion-color)"
d="M17.94 26.49c-1.63 1.99-4.22 2.87-8.39 2.87s-6.76-.89-8.39-2.87c-.41-.52-.49-1.23-.21-1.83l2.89-6.36c.5.03.96.05 1.38.05 2.62 0 3.52-.58 4.41-1.15.91-.58 1.77-1.14 4.72-.92l3.81 8.38c.28.6.2 1.31-.21 1.83Z" />
<path fill="var(--support-color)"
d="m18.15 24.67-3.66-8.38c-.68-.06-1.35-.06-2.03-.01l3.34 7.64c.27.6.19 1.3-.2 1.83-1.57 1.98-4.06 2.87-8.07 2.87-1.14.01-2.28-.08-3.41-.28 1.45.7 3.32 1.03 5.76 1.03 4.02 0 6.51-.89 8.07-2.87.39-.52.47-1.23.2-1.83Z" />
<path fill="#616262" d="M12.44 0H6.56l.98 4h3.92l.98-4z" />
<path fill="#4d4d4d" d="m11.18 0-.7 3H7.26l.28 1h3.92l.98-4h-1.26z" />
<path
d="M2.65 25.61c-.27 0-.49-.22-.49-.5 0-.07.01-.14.04-.2l.65-1.5c.11-.25.4-.37.65-.25.25.11.36.41.25.66l-.65 1.5c-.08.18-.25.3-.45.3ZM4.17 22.11c-.27 0-.49-.22-.49-.5 0-.07.01-.14.04-.2l.43-1c.11-.25.4-.37.65-.25.25.11.36.41.25.66l-.43 1c-.08.18-.25.3-.45.3Z"
class="cls-8" />
</g>
<path fill="#010101"
d="M18.77 24.35 13.33 11.5V6.55c.64-.28 1.27-1.37 1-2.44-.22-.88-1-1.5-1.9-2.11h-.05L12.9.75a.51.51 0 0 0-.34-.62c-.04-.01-.09-.02-.13-.13H6.56c-.27.11-.49.34-.49.61 0 .05 0 .09.02.14L6.61 2h-.05C5.48 2.61 4.6 3.51 4.6 4.61c0 .91.6 1.71 1.72 1.94v4.95L.23 24.35c-.4.86-.28 1.88.31 2.62 1.78 2.17 4.54 3.14 8.96 3.14s7.17-.97 8.96-3.14c.59-.74.71-1.76.31-2.62ZM11.79 1l-.7 3H7.91l-.7-3h4.58ZM7.28 12.21l.05-.21V6.5c0-.28-.22-.5-.5-.5-.55 0-1-.45-1-1s.45-1 1-1h.34l.18.64c.06.21.26.36.48.36h4c.22 0 .42-.15.48-.36l.18-.64h.34c.55 0 1 .45 1 1s-.45 1-1 1c-.28 0-.5.22-.5.5V12l.05.21 1.74 3.75c-2.72-.11-3.67.48-4.58 1.06-.9.56-1.83 1.15-4.96 1.02l2.7-5.83ZM17.7 26.33c-1.58 1.92-4.11 2.78-8.21 2.78s-6.63-.86-8.21-2.78c-.35-.44-.41-1.05-.17-1.56l2.79-6.15c.44.02.85.04 1.22.04 2.74 0 3.72-.63 4.6-1.19.89-.57 1.68-1.07 4.43-.88l3.72 8.18c.24.51.17 1.11-.17 1.55Z" />
</g>
</g>
</symbol>
</svg>
</body>
</html>
HTML 结构
- potion-select potion-select:定义了一个选择框,用于选择不同的图标选项。
- potion-equipped:定义了一个按钮,显示当前选中的药水。
- selected-value:用于显示选中的药水名称。
- items:包含所有可选项。
- listwrapper:用于包裹所有选项。
- health:定义了一个选项,值为"health"。
- potion-holder:包含药水的图标。
- icon icon-health:使用SVG图标表示药水。
- 其他选项(mana、stamina、strength、fortify、frenzy)类似。
- svg:定义了一个隐藏的SVG元素,用于存储SVG符号。
CSS 样式
全局样式
- @import:引入了normalize.css和Google字体(Fondamento)。
- :root:定义了全局变量,如颜色、尺寸等。
- *:设置全局盒模型为border-box。
- body:设置页面的布局,居中显示内容,背景为径向渐变。
选择框样式
- .potion-select:定义了选择框的基本样式,无背景、无边框。
- .potion-equipped:定义了按钮的样式,包括背景颜色、边框、圆角、阴影等。
- .selected-value:定义了选中值的样式,居中显示。
- .icon:定义了SVG图标的样式,包括大小、旋转效果。
选项样式
- option:定义了选项的基本样式,包括背景颜色、圆角、阴影等。
- option:hover, option:focus:定义了选项悬停或聚焦时的样式,包括阴影效果。
- option span:定义了选项文本的样式,包括位置、字体颜色、透明度等。
- option:nth-child(n):根据选项的顺序,动态调整旋转角度和动画延迟。
SVG样式
- .icon-health, .icon-mana, .icon-stamina, .icon-strength, .icon-fortify, .icon-frenzy:定义了不同药水图标的颜色。
- svg:隐藏的SVG元素,用于存储SVG符号。
动画样式
- @keyframes fade-in:定义了淡入动画,用于选项文本的显示。
- select:open option:定义了选项展开时的样式,包括旋转和透明度效果。
---各位互联网搭子,要是这篇文章成功引起了你的注意,别犹豫,关注、点赞、评论、分享走一波,让我们把这份默契延续下去,一起在知识的海洋里乘风破浪!