Beautiful Expandable Sidebar Navigation

Beautiful Expandable Sidebar Navigation

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&amp;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: &amp;;
  $navigation-collapse-trigger-orb-size: 25px;

  // -------------- ORB

  &amp;__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;

    &amp;:hover {
      cursor: pointer;
    }

    > svg {
      stroke: $white;
      width: 80%;
      height: auto;
      transition: transform 0.2s ease-out;

      [class$="--collapsed"] &amp; {
        transform: rotate(180deg);
      }
    }
  }

  // -------------- HOVER

  &amp;: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;

  &amp;::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;

  &amp;__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: &amp;;

  // -------------- ICON

  &amp;__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"] &amp; {
      left: 12px;
    }
  }

  // -------------- INPUT

  &amp;__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

    &amp;::-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"] &amp;:not(:focus)::-webkit-search-cancel-button {
      display: none;
    }

    // -------------- FOCUS STYLES

    &amp;:focus {
      padding-left: $offset;
      background-color: $navigation-search-background-focus-color;
      border-radius: $navigation-item-border-radius;

      [class$="--collapsed"] &amp; {
        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: &amp;;

  &amp;__icon {
    min-width: 32px;
  }

  &amp;__name {
    margin-left: 12px;

    // Collapsed state tooltip

    [class$="--collapsed"] &amp; {
      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;

      &amp;::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%);
      }
    }
  }

  &amp;:hover {
    background-color: $navigation-link-hover-background-color;
    color: $white;

    [class$="--collapsed"] &amp; #{$this}__name {
      position: absolute;
      opacity: 1 !important;
      font-size: 0.875rem;
      transform: translateX(4px);
      background: $white;
      left: 60px;

      &amp;::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 &amp;&amp; widthChange.direction === "reverse") {
      widthChange.completed = false;
    }
  }

  if (widthChange.paused) {
    widthChange.play();
  }
});

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: