gsap实现左侧弹出式多级菜单栏效果代码
代码语言:html
所属分类:菜单导航
代码描述:gsap实现左侧弹出式多级菜单栏效果代码
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8"> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Gloria+Hallelujah&family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap" rel="stylesheet"> <style> @import url('https://unpkg.com/normalize.css') layer(normalize); @layer normalize, base, demo, tree, layout, transitions, mobile, scroller-mask, debug; @layer { [data-show="true"] .safety-triangle { opacity: 1; } [data-triangle="false"] .safety-triangle { pointer-events: none; background: repeating-linear-gradient(45deg, #0000 0 4px, var(--tree-focus-color) 4px 5px); opacity: 0.5; } [data-show="false"] .safety-triangle { opacity: 0; } } @layer scroller-mask { @supports(animation-timeline: scroll()) { sidebar-tree .tree-group-container + .tree-group-container { --size: 4; -webkit-mask-image: linear-gradient(#fff, #0000), linear-gradient(#fff 0 100%), linear-gradient(#0000, #fff); mask-image: linear-gradient(#fff, #0000), linear-gradient(#fff 0 100%), linear-gradient(#0000, #fff); -webkit-mask-size: 100% calc(var(--size) * 1ch), 100% 100%, 100% calc(var(--size) * 1ch); mask-size: 100% calc(var(--size) * 1ch), 100% 100%, 100% calc(var(--size) * 1ch); -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat; -webkit-mask-composite: xor; mask-composite: exclude; -webkit-animation-timing-function: linear; animation-timing-function: linear; animation-timeline: scroll(self); animation-range: 0 calc(var(--size) * 1ch), calc(100% - (var(--size) * 1ch)) 100%; -webkit-mask-position: 0 0, 0 0, 0 100%; mask-position: 0 0, 0 0, 0 100%; -webkit-mask-size: 100% 0, 100% 100%, 100% calc(var(--size) * 1ch); mask-size: 100% 0, 100% 100%, 100% calc(var(--size) * 1ch); -webkit-animation-name: size-up, size-down; animation-name: size-up, size-down; -webkit-animation-fill-mode: both; animation-fill-mode: both; } } @-webkit-keyframes size-up { to { -webkit-mask-size: 100% calc(var(--size) * 1ch), 100% 100%, 100% calc(var(--size) * 1ch); mask-size: 100% calc(var(--size) * 1ch), 100% 100%, 100% calc(var(--size) * 1ch); } } @keyframes size-up { to { -webkit-mask-size: 100% calc(var(--size) * 1ch), 100% 100%, 100% calc(var(--size) * 1ch); mask-size: 100% calc(var(--size) * 1ch), 100% 100%, 100% calc(var(--size) * 1ch); } } @-webkit-keyframes size-down { to { -webkit-mask-size: 100% calc(var(--size) * 1ch), 100% 100%, 100% 0; mask-size: 100% calc(var(--size) * 1ch), 100% 100%, 100% 0; } } @keyframes size-down { to { -webkit-mask-size: 100% calc(var(--size) * 1ch), 100% 100%, 100% 0; mask-size: 100% calc(var(--size) * 1ch), 100% 100%, 100% 0; } } } @layer mobile { .mobile-items { align-items: center; display: none; } .menu-button { width: 40px; aspect-ratio: 1; background: #0000; border: 0; display: grid; place-items: center; padding: 0; position: relative; border-radius: 6px; cursor: pointer; &:is(:hover, :focus-visible)::after { opacity: 1; } &::after { content: ''; position: absolute; inset: 0; border-radius: inherit; opacity: 0; background: light-dark(hsl(0 0% 30% / 0.1), hsl(0 0% 90% / .15)); } } aside footer .user { display: none; } aside header .button-link { display: none; position: absolute; top: 0; left: 0; color: canvasText; svg { translate: -2px 0; } } .closer { width: 40px; aspect-ratio: 1; position: absolute; z-index: 2; top: 0; right: 0; background: #0000; border: 0; cursor: pointer; display: grid; display: none; place-items: center; padding: 0; border-radius: 6px; &:is(:hover, :focus-visible)::after { opacity: 1; } &::after { content: ''; position: absolute; inset: 6px; border-radius: inherit; opacity: 0; background: light-dark(hsl(0 0% 30% / 0.1), hsl(0 0% 90% / .15)); } svg { rotate: 45deg; width: 22px; border-radius: 6px; background: #0000; } } @media(max-width: 768px) { aside footer .user { display: flex; } aside header .button-link, .closer { display: grid; } aside footer { padding: .5rem; } aside header { padding: .5rem; padding-top: 44px; } sidebar-tree [role="treeitem"] { padding-right: .5rem; } kbd { display: none; } header .user, .user-slash { display: none; } .toggle { display: none; } .mobile-items { display: flex; } aside { position: fixed; background: light-dark(#fff, #000); translate: -100% 0; height: 100vh; top: 0; border-radius: 0; display: none; transition-property: display, overlay, translate; transition-duration: var(--speed); transition-timing-function: var(--timing); transition-behavior: allow-discrete; &::after { inset: -2px; } &::before, &::after { opacity: 1; filter: blur(0); border-radius: 0; border-top: 0; border-bottom: 0; } &:popover-open { display: grid; translate: 0 0; } &::-webkit-backdrop { background: light-dark(hsl(0 0% 0% / 0.6), hsl(0 0% 10% / 0.8)); opacity: 0; transition-behavior: allow-discrete; -webkit-transition-property: display, overlay, opacity; transition-property: display, overlay, opacity; transition-timing-function: var(--timing); transition-duration: var(--speed); } &::backdrop { background: light-dark(hsl(0 0% 0% / 0.6), hsl(0 0% 10% / 0.8)); opacity: 0; transition-behavior: allow-discrete; transition-property: display, overlay, opacity; transition-timing-function: var(--timing); transition-duration: var(--speed); } &:popover-open::-webkit-backdrop { opacity: 1; } &:popover-open::backdrop { opacity: 1; } } @starting-style { aside:popover-open { translate: -100% 0; } aside:popover-open::-webkit-backdrop { opacity: 0; } aside:popover-open::backdrop { opacity: 0; } } } } @layer transitions { /* layout transitions */ .layout { display: grid; grid-template-columns: 0 1fr; transition: grid-template-columns var(--speed) var(--timing); transition: grid-template-columns var(--speed) var(--timing), -ms-grid-columns var(--speed) var(--timing); } @media(min-width: 768px) { .layout:has(:popover-open) { grid-template-columns: var(--sidebar-width) 1fr; } } /* toggle transitions */ .toggle { &:hover::after { opacity: 1; } &::after { opacity: 0; transition: opacity 0.12s ease-out; } .icon-bar { scale: 0.3 1; transition: scale var(--speed) var(--timing); } &:hover .safety-triangle { pointer-events: all; } .hover-set, .safety-triangle { transition: scale var(--speed) var(--speed) var(--timing); opacity: 0; pointer-events: none; } .hover-set { pointer-events: all; } } /* sidebar aside */ aside { translate: -100% 0; transition-property: translate, height; transition-duration: var(--speed); transition-timing-function: var(--timing); height: calc(100vh - (var(--header-height) + 44px + 1rem)); &::before { transition: opacity var(--speed) var(--timing); } &::after { transition-property: opacity, filter; transition-duration: var(--speed); transition-timing-function: var(--timing); } &:popover-open { translate: 0 calc(-44px - 0.25rem); height: calc(100vh - (var(--header-height) + .5rem - .25rem)); } } /* states */ .toggle:has(+ :popover-open) .hover-set, .toggle:has(+ :popover-open) .safety-triangle { scale: 0; transition-delay: 0s; } .toggle:is(:hover, :focus-visible) .icon-bar, .toggle:has(+ :popover-open) .icon-bar { scale: 1 1; } .toggle:has(+ :popover-open):is(:hover, :focus-visible) .icon-bar { scale: 0.3 1; } [data-delay=true] { aside:popover-open sidebar-tree [role="treeitem"], aside:popover-open header, aside:popover-open::after, aside:popover-open::before { transition-duration: calc(var(--speed) * 1); /* transition-delay: calc(var(--speed) * 0.5); */ } .toggle:focus-visible:has( + :not(:popover-open)) + aside:before { transition-delay: 0s; transition-duration: calc(var(--speed) * 0.25); } .toggle:focus-visible + aside:popover-open::before, aside:popover-open::before { transition-duration: calc(var(--speed) * 0.25); transition-delay: calc(var(--speed) * 0.75); } .toggle .icon-bar, .toggle:is(:hover, :focus-visible)::after, .toggle:has(:is(.safety-triangle:hover, .hover-set:hover)) + aside:not(:popover-open) { transition-delay: 0.16s; } } .toggle:focus-visible:has(+ :not(:popover-open)) + aside::before { transition: opacity var(--speed) var(--timing); } aside footer, aside sidebar-tree [role="treeitem"], aside header { transition: padding var(--speed) var(--timing); } aside:popover-open sidebar-tree [role="treeitem"] { padding-right: 0.25rem; } aside:popover-open header { padding: .5rem 0 .5rem .5rem; } aside:popover-open footer { padding: .5rem 0 0 .5rem; } aside:popover-open::after { filter: blur(2px); } aside:popover-open::after, aside:popover-open::before { opacity: 0; } @media(min-width: 768px) { aside:popover-open sidebar-tree .tree-group-container:first-of-type::after, aside:popover-open footer::after { right: 0; } } .toggle:has(:is(.safety-triangle:hover, .hover-set:hover)) + aside:not(:popover-open), .toggle:is(:focus-visible) + aside:not(:popover-open), aside:is(:focus-within, :hover):not(:popover-open) { translate: 0 0; } } @layer layout { :root { --tree-focus-color: hsl(0 90% 66%); --text: light-dark(hsl(0 0% 45%), hsl(0 0% 54%)); --header-height: 60px; --sidebar-width: 260px; --panel-color: light-dark(color-mix(in hsl, canvas, canvasText 4%), color-mix(in hsl, #000, canvasText 8%)); --border-color: color-mix(in hsl, canvas, canvasText 30%); --speed: calc(var(--layout-speed, 0.16) * 1s); --timing: cubic-bezier(0.0, 0.0, 0.58, 1.0); } body { display: grid; grid-template-rows: auto 1fr; padding-bottom: .5rem; } .arrow { opacity: .4; font-family: Gloria Hallelujah, cursive; font-size: .875rem; transition: opacity .26s ease-out; display: inline-block; position: absolute; top: 0; left: 0; translate: 60% 130%; rotate: 14deg; svg { width: 60%; position: absolute; top: 130%; left: 0; translate: -40% 60%; rotate: 330deg; scale: -1 1; } span { display: inline-block; .........完整代码请登录后点击上方下载按钮下载查看
网友评论0