HTML&CSS:超好看的收缩展开菜单

这个页面实现了一个具有动画效果的菜单选择框,用户可以通过点击按钮选择不同的菜单选项。页面使用了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:定义了选项展开时的样式,包括旋转和透明度效果。

---各位互联网搭子,要是这篇文章成功引起了你的注意,别犹豫,关注、点赞、评论、分享走一波,让我们把这份默契延续下去,一起在知识的海洋里乘风破浪!

相关推荐
烛阴9 分钟前
从零到RESTful API:Express路由设计速成手册
javascript·后端·express
ElasticPDF-新国产PDF编辑器25 分钟前
Vue PDF Annotation plugin library online API examples
javascript·vue.js·pdf
鱼樱前端27 分钟前
Vite 工程化深度解析与最佳实践
前端·javascript
鱼樱前端34 分钟前
Webpack 在前端工程化中的核心应用解析-构建老大
前端·javascript
Moment34 分钟前
多人协同编辑算法 —— CRDT 算法 🐂🐂🐂
前端·javascript·面试
小付同学呀40 分钟前
前端快速入门学习4——CSS盒子模型、浮动、定位
前端·css·学习
ElasticPDF-新国产PDF编辑器2 小时前
Vue 项目使用 pdf.js 及 Elasticpdf 教程
javascript·vue.js·pdf
勘察加熊人3 小时前
vue记忆卡牌游戏
javascript·vue.js·游戏
yanyu-yaya4 小时前
第三章 react redux的学习之redux和react-redux,@reduxjs/toolkit依赖结合使用
javascript·学习·react.js
江城开朗的豌豆4 小时前
使用Plotly.js创建炫酷红外轮廓热力图 - Vue组件封装实战
前端·javascript·vue.js