Try this beautiful expandable sidebar navigation to your next project
HTML
<div class="navigation-container" id="js_navigation-container"> <div class="navigation-collapse-trigger"> <span class="navigation-collapse-trigger__orb" id="js_navigation-collapse-trigger"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-left"> <polyline points="15 18 9 12 15 6"></polyline> </svg> </span> </div> <div class="navigation"> <!-- LOGO --> <a class="navigation-logo" href="#"> <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="feather feather-box navigation-logo__icon"> <path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path> <polyline points="3.27 6.96 12 12.01 20.73 6.96"></polyline> <line x1="12" y1="22.08" x2="12" y2="12"></line> </svg> <span class="navigation-logo__name js_navigation-item-name"> Productname </span> </a> <!-- SEARCH --> <div class="navigation-search"> <input type="search" placeholder="search" class="navigation-search__input" /> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="navigation-search__icon"> <circle cx="11" cy="11" r="8"></circle> <line x1="21" y1="21" x2="16.65" y2="16.65"></line> </svg> </div> <!-- NAVIGATION --> <nav role="navigation"> <ul> <li> <a class="navigation-link" href="#"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="navigation-link__icon feather feather-grid"> <rect x="3" y="3" width="7" height="7"></rect> <rect x="14" y="3" width="7" height="7"></rect> <rect x="14" y="14" width="7" height="7"></rect> <rect x="3" y="14" width="7" height="7"></rect> </svg> <span class="navigation-link__name js_navigation-item-name"> Dashboard </span> </a> </li> <li> <a class="navigation-link" href="#"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="navigation-link__icon feather feather-activity"> <polyline points="22 12 18 12 15 21 9 3 6 12 2 12"></polyline> </svg> <span class="navigation-link__name js_navigation-item-name"> Analytics </span> </a> </li> <li> <a class="navigation-link" href="#"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="navigation-link__icon feather feather-users"> <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path> <circle cx="9" cy="7" r="4"></circle> <path d="M23 21v-2a4 4 0 0 0-3-3.87"></path> <path d="M16 3.13a4 4 0 0 1 0 7.75"></path> </svg> <span class="navigation-link__name js_navigation-item-name"> Accounts </span> </a> </li> <li> <a class="navigation-link" href="#"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="navigation-link__icon feather feather-calendar"> <rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect> <line x1="16" y1="2" x2="16" y2="6"></line> <line x1="8" y1="2" x2="8" y2="6"></line> <line x1="3" y1="10" x2="21" y2="10"></line> </svg> <span class="navigation-link__name js_navigation-item-name"> Calendar </span> </a> </li> <li> <a class="navigation-link" href="#"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="navigation-link__icon feather feather-file-text"> <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path> <polyline points="14 2 14 8 20 8"></polyline> <line x1="16" y1="13" x2="8" y2="13"></line> <line x1="16" y1="17" x2="8" y2="17"></line> <polyline points="10 9 9 9 8 9"></polyline> </svg> <span class="navigation-link__name js_navigation-item-name"> Documents </span> </a> </li> </ul> </nav> <!-- LOGOUT --> <a class="navigation-link logout" href="#"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="navigation-link__icon feather feather-power"> <path d="M18.36 6.64a9 9 0 1 1-12.73 0"></path> <line x1="12" y1="2" x2="12" y2="12"></line> </svg> <span class="navigation-link__name js_navigation-item-name"> Logout </span> </a> </div> </div>
CSS
@import url("https://fonts.googleapis.com/css2?family=Noto+Sans+TC:[email protected];500&display=swap"); $white: #ffffff; $body-background-color: #f4f4f8; $navigation-background-color: #030303; $navigation-link-color: #9e9fa4; $navigation-link-hover-background-color: #313239; $navigation-item-height: 45px; $navigation-item-border-radius: 5px; $navigation-item-tooltip-color: #6b6b6b; $navigation-search-background-color: #2c2a30; $navigation-search-background-focus-color: #313239; $navigation-search-color: $white; $navigation-search-icon-size: 25px; $navigation-collapse-trigger-color: #408bff; html { box-sizing: border-box; } *, *:before, *:after { box-sizing: inherit; } html, body { height: 100%; width: 100%; } body { background-color: $body-background-color; font-family: "Noto Sans TC", sans-serif; font-weight: 400; display: flex; align-items: center; justify-content: center; line-height: 1.5; font-size: 16px; min-height: 700px; } // -------------- NAVIGATION CONTAINER .navigation-container { position: relative; width: 275px; } // -------------- NAVIGATION COLLAPSE TRIGGER .navigation-collapse-trigger { bottom: 0; position: absolute; right: -10px; top: 0; width: 20px; $this: &; $navigation-collapse-trigger-orb-size: 25px; // -------------- ORB &__orb { position: absolute; width: $navigation-collapse-trigger-orb-size; height: $navigation-collapse-trigger-orb-size; border-radius: $navigation-collapse-trigger-orb-size; background-color: $navigation-collapse-trigger-color; z-index: 1; display: flex; justify-content: center; align-items: center; left: 50%; transform: translate(calc(-50% + 2px), 100px) scale(0); transition: all 0.2s ease-out; transition-delay: 0.1s; &:hover { cursor: pointer; } > svg { stroke: $white; width: 80%; height: auto; transition: transform 0.2s ease-out; [class$="--collapsed"] & { transform: rotate(180deg); } } } // -------------- HOVER &:hover { #{$this}__orb { transform: translate(calc(-50% + 2px), 100px) scale(1); } ~ .navigation::before { opacity: 1; } } } // -------------- NAVIGATION .navigation { background-color: $navigation-background-color; color: $white; height: 90vh; min-height: 650px; padding: 16px; display: flex; flex-direction: column; border-radius: 10px; &::before { background: linear-gradient( 180deg, rgba($navigation-collapse-trigger-color, 0) 0%, rgba($navigation-collapse-trigger-color, 1) 5%, rgba($navigation-collapse-trigger-color, 1) 95%, rgba($navigation-collapse-trigger-color, 0) 100% ); bottom: 0; pointer-events: none; position: absolute; right: -3px; top: 0; width: 2px; content: ""; opacity: 0; transition: opacity 0.2s ease-out; transition-delay: 0.1s; } .logout { margin-top: auto; } } // -------------- NAVIGATION LOGO .navigation-logo { color: $white; text-decoration: none; font-size: 24px; font-weight: 500; display: flex; align-items: center; margin: 8px; margin-bottom: 30px; &__icon { min-width: 32px; } svg { margin-right: 8px; } } // -------------- NAVIGATION SEARCH .navigation-search { $offset: ($navigation-item-height - $navigation-search-icon-size) / 2; margin-bottom: 24px; position: relative; $this: &; // -------------- ICON &__icon { height: $navigation-search-icon-size; left: $offset; opacity: 1; pointer-events: none; position: absolute; top: $offset; transition: all 0.1s ease-out; width: $navigation-search-icon-size; z-index: 1; [class$="--collapsed"] & { left: 12px; } } // -------------- INPUT &__input { background-color: $navigation-search-background-color; border-radius: $navigation-item-border-radius; border: 0; color: $navigation-search-color; font-family: inherit; font-size: inherit; height: $navigation-item-height; line-height: $navigation-item-height; outline: none; padding-left: $navigation-search-icon-size * 2; transition: all 0.2s ease-out; width: 100%; position: relative; z-index: 1; // -------------- CANCEL BUTTON &::-webkit-search-cancel-button { -webkit-appearance: none; background: url("data:image/svg+xml, %3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class='feather feather-x' %3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E") no-repeat center center/cover; cursor: pointer; height: 20px; position: relative; right: $offset; width: 20px; } [class$="--collapsed"] &:not(:focus)::-webkit-search-cancel-button { display: none; } // -------------- FOCUS STYLES &:focus { padding-left: $offset; background-color: $navigation-search-background-focus-color; border-radius: $navigation-item-border-radius; [class$="--collapsed"] & { width: 250px; box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); } + svg { opacity: 0; transform: translateX(-20%); z-index: 2; } } } } // -------------- NAVIGATION LINK .navigation-link { display: block; color: $navigation-link-color; display: flex; align-items: center; padding: 0 8px; height: $navigation-item-height; line-height: $navigation-item-height; border-radius: $navigation-item-border-radius; text-decoration: none; transition: all 0.2s ease-out; white-space: nowrap; $this: &; &__icon { min-width: 32px; } &__name { margin-left: 12px; // Collapsed state tooltip [class$="--collapsed"] & { padding: 0.5em; line-height: 1; border-radius: ceil($navigation-item-border-radius / 2); color: $navigation-item-tooltip-color; transition: transform 0.2s ease-out; box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); pointer-events: none; position: absolute; left: 48px; &::before { width: 0; height: 0; border-top: 5px solid transparent; border-right: 7px solid $white; border-bottom: 5px solid transparent; left: -7px; position: absolute; top: 50%; transform: translateY(-50%); } } } &:hover { background-color: $navigation-link-hover-background-color; color: $white; [class$="--collapsed"] & #{$this}__name { position: absolute; opacity: 1 !important; font-size: 0.875rem; transform: translateX(4px); background: $white; left: 60px; &::before { content: ""; } } } }
JS
const trigger = document.getElementById("js_navigation-collapse-trigger"); const navigationContainer = document.getElementById("js_navigation-container"); const navigationModifierClass = "navigation-container--collapsed"; const animationDuration = 400; const widthChange = anime.timeline({ autoplay: false, easing: "easeInOutBack", }); widthChange .add({ targets: navigationContainer, width: 80, duration: animationDuration, }) .add( { targets: ".js_navigation-item-name", opacity: [1, 0], duration: animationDuration / 2, }, `-=${animationDuration}` ); let navigationIsCollapsed = false; trigger.addEventListener("click", function () { navigationIsCollapsed = !navigationIsCollapsed; if (navigationIsCollapsed) { navigationContainer.classList.add(navigationModifierClass); } else { navigationContainer.classList.remove(navigationModifierClass); } if (widthChange.began) { widthChange.reverse(); if (widthChange.progress === 100 && widthChange.direction === "reverse") { widthChange.completed = false; } } if (widthChange.paused) { widthChange.play(); } });