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