DEV Community

Cover image for Cool dashboard side menu using CSS and JavaScript
Pedro Romão
Pedro Romão

Posted on

Cool dashboard side menu using CSS and JavaScript

In this article, we will create a cool dashboard side menu that you can use in your web projects. Let's first look at what are we building:

Example gif

HTML

<div class="container">
  <div class="menu">

    <div class="main-menu">

      <div class="logo">
        <img src="your_image_url">
      </div>

      <div class="button-list">
        <div class="item" active>
          <i class="fas fa-home"></i>
        </div>
        <div class="item">
          <i class="fas fa-user"></i>
        </div>
        <div class="item">
          <i class="fas fa-briefcase"></i>
        </div>
        <div class="item">
          <i class="fas fa-chart-pie"></i>
        </div>
        <div class="item">
          <i class="fas fa-user-cog"></i>
        </div>
        <div class="item">
          <i class="fas fa-cog"></i>
        </div>
      </div>

    </div>

    <div class="secondary-menu" expand>
      <div class="content">

        <div class="title">
          <span>Settings</span>
        </div>

        <div class="button-list-title">
          <span>User admin</span>
        </div>

        <div class="button-list">
          <div class="item" active>
            <div class="border-left"></div>
            <span>My Profile</span>
          </div>
          <div class="item">
            <div class="border-left"></div>
            <span>Org</span>
          </div>
          <div class="item">
            <div class="border-left"></div>
            <span>Teams</span>
          </div>
          <div class="item">
            <div class="border-left"></div>
            <span>Roles</span>
          </div>
          <div class="item">
            <div class="border-left"></div>
            <span>Profiles</span>
          </div>
        </div>

        <div class="button-list-title">
          <span>System config.</span>
        </div>

        <div class="button-list">
          <div class="item">
            <div class="border-left"></div>
            <span>Rulesets</span>
          </div>
          <div class="item">
            <div class="border-left"></div>
            <span>Prospects</span>
          </div>
          <div class="item">
            <div class="border-left"></div>
            <span>Accounts</span>
          </div>
          <div class="item">
            <div class="border-left"></div>
            <span>Calls</span>
          </div>
          <div class="item">
            <div class="border-left"></div>
            <span>Triggers</span>
          </div>
          <div class="item">
            <div class="border-left"></div>
            <span>Phones</span>
          </div>
        </div>

      </div>
    </div>

  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

In the HTML code, the "main-menu" class is the main container with the icon buttons and "secondary-menu" class is the secondary container with the submenus.

Now let's look at the CSS:

CSS

@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@600;700&display=swap');

:root {
  --color-primary: #546de5;
  --color-secondary: #8395e9;
  --color-secondary-light: rgb(84, 109, 229, .05);
  --color-dark: #303952;
  --color-dark-light: #4f576c;
  --color-light: #ffffff;
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.container {
  display: flex;
  align-items: flex-start;
}

.menu {
  display: flex;
  align-items: flex-start;
  height: 100vh;
/*   overflow-y: hidden; */
}

.menu .main-menu {
  width: 60px;
  height: 100vh;
  background-color: var(--color-dark);
}

.menu .main-menu .logo {
  display: flex;
  padding: 10px;
}

.menu .main-menu .logo img {
  width: 40px;
  margin: 0px auto;
}

.menu .main-menu .button-list {
  margin-top: 30px;
}

.menu .main-menu .button-list .item {
  display: flex;
  padding: 15px 10px;
  cursor: pointer;
  transition: all .5s;
}

.menu .main-menu .button-list .item:hover {
  background-color: var(--color-dark-light);
}

.menu .main-menu .button-list .item[active] {
  background-color: var(--color-primary);
}

.menu .main-menu .button-list .item i {
  font-size: 16px;
  color: var(--color-light);
  margin: 0px auto;
  pointer-events: none;
}

.menu .secondary-menu {
  padding: 20px 0px;
  width: 0px;
  height: 100vh;
  background-color: var(--color-light);
  -webkit-box-shadow: 10px 0px 15px 0px rgba(48,57,82,0.1);
  -moz-box-shadow: 10px 0px 15px 0px rgba(48,57,82,0.1);
  box-shadow: 10px 0px 15px 0px rgba(48,57,82,0.1);
  transition: all .5s;
}

.menu .secondary-menu .content {
  opacity: 0;
}

.menu .secondary-menu[expand] {
  width: 200px;
}

.menu .secondary-menu[expand] .content {
  opacity: 1;
}

.menu .secondary-menu .content {
  max-height: calc(100vh - 40px);
  overflow-y: auto;
  transition: opacity .5s;

  /*  Firefox  */
  scrollbar-color: var(--color-secondary-light) var(--color-secondary-light) !important;
  scrollbar-width: thin !important;
}

.menu .secondary-menu .content::-webkit-scrollbar {
  width: 2px;
}

.menu .secondary-menu .content::-webkit-scrollbar-track {
  background: var(--color-secondary-light);
}

.menu .secondary-menu .content .title {
  padding: 0px 20px;
}

.menu .secondary-menu .title span {
  font-family: 'Open Sans', sans-serif;
  font-size: 18px;
}

.menu .secondary-menu .button-list-title {
  padding: 20px 20px 10px 20px;
}

.menu .secondary-menu .button-list-title span {
  font-family: 'Open Sans', sans-serif;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
}

.menu .secondary-menu .button-list {
  padding: 20px 0px;
}

.menu .secondary-menu .button-list .item {
  display: flex;
  align-items: center;
  height: 35px;
  padding: 0px 20px;
  cursor: pointer;
  transition: all .5s;
}

.menu .secondary-menu .button-list .item:hover {
  background-color: var(--color-secondary-light);
}

.menu .secondary-menu .button-list .item .border-left {
  height: 100%;
  border-left: 2px solid var(--color-dark-light);
  opacity: 0.1;
  margin-right: 15px;
  pointer-events: none;
}

.menu .secondary-menu .button-list .item span {
  font-family: 'Open Sans', sans-serif;
  font-size: 12px;
  color: var(--color-dark-light);
  opacity: 0.3;
  pointer-events: none;
}

.menu .secondary-menu .button-list .item[active] {
  background-color: var(--color-light);
}

.menu .secondary-menu .button-list .item[active] .border-left {
  border-left-color: var(--color-secondary);
  opacity: 1;
}

.menu .secondary-menu .button-list .item[active] span {
  color: var(--color-secondary);
  opacity: 1;
}
Enter fullscreen mode Exit fullscreen mode

JavaScript

const mainButtons = document.querySelectorAll('.main-menu .item')
const secondaryButtons = document.querySelectorAll('.secondary-menu .item')

const handleMainButtonClick = (event) => {
  const button = event.target
  if (!isActive(button)) {
    removeMainActive()
    addActive(button)
  }
}

const handleSecondaryButtonClick = (event) => {
  const button = event.target
  if (!isActive(button)) {
    removeSecondaryActive()
    addActive(button)
  }
}

mainButtons.forEach(button => {
  button.addEventListener('click', handleMainButtonClick)
})

secondaryButtons.forEach(button => {
  button.addEventListener('click', handleSecondaryButtonClick)
})

function isActive (button) {
  return button.hasAttribute('active')
}

function removeMainActive () {
  document.querySelectorAll('.main-menu .item[active]').forEach(item => {
    item.removeAttribute('active')
  })
}

function removeSecondaryActive () {
  document.querySelectorAll('.secondary-menu .item[active]').forEach(item => {
    item.removeAttribute('active')
  })
}

function addActive (button) {
  button.setAttribute('active', '')
}
Enter fullscreen mode Exit fullscreen mode

Codepen is here:

Top comments (6)

Collapse
 
jotajeff profile image
Jeferson Silva

great article, congratulations

Collapse
 
basekesamuel96 profile image
Samuel Baseke

Very beautiful... Thanks very much for sharing

Collapse
 
leodarpan profile image
DARPAN ANEJA

Superb action in there!!

Collapse
 
dev_geos profile image
Dev Geos

Nice, good work 👏

Collapse
 
romaopedro199 profile image
Pedro Romão

Thank you!!

Collapse
 
minhazhalim profile image
Minhaz Halim (Zim)

Nice work..