7 days of unlimited WordPress themes, plugins & graphics - for free!* Unlimited asset downloads! Start 7-Day Free Trial
  1. Web Design
  2. Dashboard

Building an Admin Dashboard Layout With CSS and a Touch of JavaScript

Scroll to top
Read Time: 20 mins

In this updated tutorial, we’ll create a responsive admin dashboard layout with CSS and a touch of JavaScript. To build it, we’ll borrow some ideas from the WordPress dashboard, such as its collapsible sidebar menu.

Throughout the tutorial, we’ll face plenty of challenges, but ones that will give us good practice for enhancing our front-end skills.

Admin Dashboard Demo

Without further ado, let’s have a look at the final admin dashboard demo. Pay attention to the following things:

  • Hit the Collapse button at the foot of the sidebar to see the collapsible nav in action.
  • Hit the toggle switch at the foot of the sidebar to reveal the light and dark admin themes.
  • Check out the full-screen version to play with its responsiveness.

Envato Elements: Unlimited Web Design Downloads

Before we get into the meat of the tutorial, I wanted to mention a great source for web designers looking for ready-made templates and other digital assets to download. Envato Elements offers unlimited CSS templates, as well as fonts, photos, mockups, and more.

For example, the TailStack CSS Admin Dashboard Template lets you implement exactly the kind of CSS admin dashboard we're creating in today's tutorial, without writing a single line of code. Just download it and put it to use.

TailStack CSS Admin DashboardTailStack CSS Admin DashboardTailStack CSS Admin Dashboard

Or, if you want to code your own dashboard in JavaScript and CSS, read on for the tutorial.

1. Begin With the Page Markup

To kick off the markup we’ll need an SVG, a header, and a section:

SVG Sprites

As you might imagine with any admin dashboard we’re going to need a bunch of icons. Thankfully, Envato Elements provides an ever-expanding collection of useful vector icons, so let’s take advantage of that library and download these Trade and Dashboard Icons.

Trade and Dashboard IconsTrade and Dashboard IconsTrade and Dashboard Icons
Trade and Dashboard Icons on Envato Elements

Rather than including them directly on the page via an img or svg tag, let’s go one step further and create an SVG sprite. To do this, we’ll wrap all the icons in an SVG container. The container should be hidden, so we’ll apply display: none to it. If we don’t hide it, a big empty area will appear at the top of the page.

Each icon will be placed inside a symbol element with a unique ID and a viewBox attribute which will depend on the icon size. We can then render the target icon whenever we need it by calling the use element (I’ll show you how in a minute). 

Additionally, we’ll put our logo within this container. 

Later, we’ll examine how the colors of these SVGs will change depending on the theme mode, but for now let’s just become familiar with the markup needed for the SVG sprite:

And really, that’s all we need to create our inline SVG sprite.


Moving on with our admin dashboard layout, let’s look at the page header. 

Within it, we’ll define a nav element that will serve as the wrapper for the following elements:

  • The logo.
  • The Collapse button that will toggle the menu on mobile screens.
  • The menu itself. This will contain the menu links, two headings, a light/dark mode switch, and the collapse/expand button. It might be more semantically correct to have two individual menus and place the headings outside them, but you can approach things differently if you prefer.

Here’s how it’ll look like on wide screens (>767px):

The header layout

The header structure:

Notice two things in the code above:

  • How we use the use element to reference the target elements.
  • The ARIA attributes (aria-expanded, aria-label, aria-hidden) that we add to the toggle buttons. These attributes will help us make the component a bit more accessible. Later, we’ll discuss how their values will be updated based on the button’s state.


The section will contain two nested sections.

Section #1

Inside the first section, we’ll place the search form and some info (name, avatar, and notifications) about the current logged-in user.

Here’s its appearance on wide screens (>767px):

The layout of the first sectionThe layout of the first sectionThe layout of the first section

The section structure:

Again, notice that we add some ARIA attributes to the submit button.

Section #2

Inside the second section, just for enriching the demo with some dummy content, we’ll place a bunch of article placeholders. These might typically contain tabular data, charts, or feeds of some kind.

“Use a maximum of 5–7 different widgets to create a view. Otherwise, it will be hard for a user to focus and get a clear overview.” – Taras Bakusevych

Here’s its appearance on wide screens (>767px):

The layout of the second sectionThe layout of the second sectionThe layout of the second section
In accordance with UX best practices, you may not need this many sections

The section structure:

2. Define Some Basic Styles

With the markup for our admin dashboard ready, we’ll forge on with the CSS. The first step, as always, is to specify some CSS variables and common reset styles:

Note: for simplicity, I won’t walk through all the CSS rules in the tutorial. There are almost 550 lines of CSS here. If you want to, you can check them all by clicking the CSS tab of the demo project. Besides that, if you are building a production site, it might be more manageable to use a CSS preprocessor like Sass for organizing these styles.

3. Define the Main Dashboard Styles

At this point, we’re ready to concentrate on the page styles.

Style the Header

The header will be a fixed position element. Its width will be 220px, and its height equal to the viewport height. In case its contents exceed the viewport height, a vertical scrollbar will appear.

The nav element will behave as a flex container with a minimum height of 100%. Remember that its direct children are three: 

  1. The logo
  2. The mobile menu toggle button
  3. The menu

The toggle button will be visible only on small screens (<768px).  Here are the styles we need:

Tip: in case you prefer an absolutely positioned header that covers the full page height, add the following styles:

Menu Styles

The menu will serve as a flex container, and we’ll give it flex: 1, so it’ll expand and cover the full parent height.

The last menu item will be given a margin-top: auto because it should be positioned at the very bottom of the menu. This behavior will be clearer when the header scrollbar doesn’t appear. To test it, try to remove some menu items or check the demo on a tall screen.

The links and button inside the menu will also act as flex containers and their contents (text and icons) should be vertically aligned.

The menu headings will be a bit smaller compared to the other menu elements. Also, we’ll increase the spacing between their characters.

Here’s a part of the menu styles:

Toggling Dark and Light Themes

To build the switch, we’ll borrow quite a lot of styles from another tutorial which explains how to create a toggle switch. Be sure to have a look and learn how we implement it with the CSS checkbox hack technique.

Our dashboard will support two theme options: the light option and the dark one. By default, the dark will be active and look like this:

The dark mode enabled

When we click on the switch its appearance will change as follows:

The light mode enabled

Here are the associated styles:

Page Content Styles

Remember that the .page-content section contains two sub-sections.

This section will be placed 220px away from the left side of the viewport. Plus, we’ll give it width: calc(100% - 220px). Note that its left property value is equal to the header width.

Its styles:

Search and User Styles

Also, remember that the .search-and-user section contains two elements: the search form and the .admin-profile.

To lay it out, we’ll use CSS Grid. The search form will cover the full available space, and there will be a 50px gap between it and its sibling. Both siblings will be vertically aligned.

The submit button inside the form will be absolutely positioned. It will only contain a decorative icon, and we’ll therefore need an ARIA attribute to allow screenreaders to interpret it and thereby make it accessible.

The .admin-profile, which contains two elements, will behave as a flex container with vertically centered content. The badge (counter) element will be absolutely positioned inside its parent with horizontally and vertically centered content.

Here’s a part of the required styles for this section:

Grid Styles

To lay out the articles on our admin dashboard, we’ll take advantage of CSS Grid. We’ll give all articles a fixed height of 300px. Apart from the first and last articles which will cover the full parent width, all the others will be part of a two-column layout.

The associated styles:

4. Toggle Header

Each time we click on the collapse/expand button, the header state will change. If it’s expanded, it will collapse (leaving just icon variants of the menu items), and vice versa. 

collapsing menu with icons

Keep in mind that this functionality will be available only on screens greater than 767px. For smaller screens, our header will have a different layout, which we’ll get to shortly.

During the collapsed state of the header, the body element receives the collapsed class. At that point, the following things happen:

  • The header shrinks. Its width changes from 220px to 40px.
  • In response to this, the .page-content section grows. Specifically, its width changes from width: calc(100% - 220px) to width: calc(100% - 40px). In addition, its left property value becomes 40px instead of 220px.
  • The logo, the menu headings, the menu links text, the light/dark theme switcher, and the menu button text disappear.
  • The aria-expanded and aria-label attribute values of the toggle button are updated. Plus, its icon is rotated 180 degrees, so it looks like an expand icon.

Here’s the JavaScript code that implements this functionality:

And all the associated styles:

5. Toggle Theme Switch

Each time we click on the toggle switch, the dashboard colors will change.

light and dark toggle switchlight and dark toggle switchlight and dark toggle switch

Remember that initially the dark mode will be enabled. But, as soon as the light mode becomes active, the html element will receive the light-mode class.

The html light mode classThe html light mode classThe html light mode class

This class will update/override the values of many of the predefined CSS variables (especially the color ones) and hence change the theme appearance.

Here’s the required JavaScript code:

And the associated styles:

Persist Selected Mode on Page Load

But we haven’t finished yet! It would be really nice if we could store the user’s theme preference and enable it each time they revisit the admin. We can achieve this by taking advantage of local storage.

Store the preferred theme mode in local storageStore the preferred theme mode in local storageStore the preferred theme mode in local storage

Let’s look at the JavaScript code that will handle this logic:

From here, you can go deeper and make even more complex assumptions by using the prefers-color-scheme CSS media feature. For example, if the user hasn’t selected any mode, you can display the one that respects their operating system preference. But for now, let’s keep things simple.

6. Show Tooltip on Admin Menu Items

At this point, let’s add another new feature to the collapsible header.

As we discussed in the previous section, when the header becomes collapsed, the text of the menu links will disappear. This means, at that point, only the SVG icons will be visible. So, let’s display a tooltip that will give users a better understanding of what each link does.

To do so, each time a menu link (icon) is being hovered over, we’ll add the title attribute to it, with the value being its span’s text. But again, that should happen only when the header is collapsed and the window width is at least 768px.

collapsed menu icon tooltips

Here’s the corresponding JavaScript: 

7. Going Responsive

On screens up to 767px wide, our page will look like this:

The mobile layoutThe mobile layoutThe mobile layout

That’s a big difference from our sidebar arrangement, right? Let’s highlight the most important differences compared to the desktop version:

  • Both the header and .page-content have position: static and width: 100%.
  • The flex direction of the nav element changes from column to row.
  • The mobile menu toggle button becomes visible.
  • The menu is absolutely positioned right underneath the header and initially hidden. It will become visible each time we click on the toggle button. 
  • The collapse/expand button and the .greeting element are hidden.
  • The .search-and-user section is absolutely positioned and placed right next to the mobile menu toggle button. 

Below you can see a part of the responsive styles:

8. Toggle Mobile Menu

Each time we click on the toggle button, the menu state will change. If it’s expanded, it will collapse, and vice versa.

mobile menu toggle

During the expanded state of the menu, the body element receives the mob-menu-opened class. At that point, the following things happen:

  • The menu appears.
  • The aria-expanded and aria-label attribute values of the toggle button are updated. Plus, its icon is rotated 180 degrees, so it looks like an expand icon.

Here’s the required JavaScript code:

And the associated CSS:


That’s it, folks! We successfully built a fully functional admin dashboard layout. You’ll be able to expand on this foundation to create all kinds of admin interfaces. Hopefully, you enjoyed this journey as much as I did!

A Note on Accessibility

Just a last note: I’m certainly not an accessibility expert, yet I tried to make this UI more accessible by adding some common ARIA attributes. During this process, I checked the WordPress and CodePen dashboards for reference. There might be additional ARIA attributes that could have been included in the code. For example, I excluded the aria-controls attribute which is responsible for identifying the related content, but that was because Aria-Controls is Poop.

As a next step, make sure to optimize the code by using a CSS preprocessor and group the JavaScript code into functions. And if you plan to use this admin in a real project, I’d love to know it!

As always, thanks for reading!

More Admin Dashboard UI Resources

Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Web Design tutorials. Never miss out on learning about the next big thing.
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.