Prologue
Hello everyone, today we will build two basic fixed sidebars to demonstrate how easy it is to produce a clean result. We will first start by a classic sidebar, wich overlaps content when opened. Then, we will add some small tweaks to make it push the content outside of the window when opened.
Fixed sidebar
Let's start with the fixed sidebar. You can find this post's code in the following Pen.
See the Pen Fixed Sidebar by Driss Chelouati (@cssninjaStudio) on CodePen.
Setting the layout
Before building our first sidebar, we are going to start by setting up a simple demo layout for our sidebar experiment.
Basic assets
Before diving into the code, we first need to import some assets for our project.
- First we need to import the Roboto font from Google fonts
https://fonts.googleapis.com/css?family=Roboto
- We also need jQuery to perform our sidebar toggle code, so let's import it too
https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js
- And finally, an icon library for our menu items, let's go with linearicons svg embedder
https://cdn.linearicons.com/free/1.0.0/svgembedder.min.js
Wrapper and navbar markup
We are going to need a wrapper for our layout. It is always a good practice to wrap your main page sections inside a wrapper. We will see later how this wrapper will help us to achieve some effects.
We will also setup a basic navbar inside the wrapper. It will have two elements : a slot for the brand and another one for the sidebar menu toggle. Let's add the wrapper and navbar html markup:
<div class="wrapper">
<nav class="navbar">
<div class="brand">
<img
src="https://cssninja.io/themes/cssninja/assets/images/logo/cssninja-blue.svg"
/>
</div>
<div class="menu">
<svg class="lnr lnr-menu"><use xlink:href="#lnr-menu"></use></svg>
</div>
</nav>
</div>
Wrapper and navbar styles
We should now add our basic styles to make our page look good. Let's start with the global styles. Since we are not using any framework like Bootstrap or Bulma, we need to do some basic resets for the body and define styles for our wrapper
and container
elements.
$fade-grey: #ededed;
$muted-grey: #999;
$white: #fff;
$sidebar: #1f293d;
* {
box-sizing: border-box;
}
body {
font-family: 'Roboto', sans-serif;
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
.wrapper {
min-height: 100vh;
height: 100%;
width: 100%;
background: $fade-grey;
.container {
padding-top: 60px;
max-width: 900px;
margin: 0 auto;
}
}
Now let's add the navbar styles:
nav.navbar {
display: flex;
justify-content: space-between;
align-items: center;
position: relative;
width: 100%;
padding: 20px 40px;
background: $white;
.brand {
img {
height: 42px;
}
}
.menu {
display: flex;
align-items: center;
svg {
height: 32px;
width: 32px;
cursor: pointer;
}
}
}
I use flexbox for the navbar as it simplifies a lot the positioning of our two menu items. To position each menu item, (.brand
and .menu
) we use :
display: flex;
justify-content: space-between;
align-items: center;
space-between
pushes the navbar children elements to their parent's boundaries. It is very useful in our case because we only have two menu items. The align-items: center;
property makes everything vertically centered inside a display: flex;
element. After that, add the styles for the .brand
and .menu
elements. Basically, it's just about setting some width, height, and a position for the hamburger menu icon.
Adding some content
To have a fully functionnal demo with page scrolling capabilities, we need to add some content. We will add cards with some generic text. Here is the markup :
<div class="container">
<div class="card">
<h1>Click the Hamburger</h1>
<p>
Lorem ipsum dolor sit amet, te has iuvaret scaevola, ei his nibh rebum
albucius. Ei accusata instructior sit, cum unum quodsi et. Laudem scripta
atomorum nam ei, laudem essent philosophia mei te, te nam mundi graecis
repudiandae. Dicat scaevola laboramus vel id, paulo detracto accusata sit
ut. Graecis ceteros cu pro, et vidit perpetua mel.
</p>
</div>
<div class="card">
<h1>Hello sidebar</h1>
<p>
Lorem ipsum dolor sit amet, te has iuvaret scaevola, ei his nibh rebum
albucius. Ei accusata instructior sit, cum unum quodsi et. Laudem scripta
atomorum nam ei, laudem essent philosophia mei te, te nam mundi graecis
repudiandae. Dicat scaevola laboramus vel id, paulo detracto accusata sit
ut. Graecis ceteros cu pro, et vidit perpetua mel.
</p>
</div>
<div class="card">
<h1>Hello sidebar</h1>
<p>
Lorem ipsum dolor sit amet, te has iuvaret scaevola, ei his nibh rebum
albucius. Ei accusata instructior sit, cum unum quodsi et. Laudem scripta
atomorum nam ei, laudem essent philosophia mei te, te nam mundi graecis
repudiandae. Dicat scaevola laboramus vel id, paulo detracto accusata sit
ut. Graecis ceteros cu pro, et vidit perpetua mel.
</p>
</div>
</div>
We need to do some styling to make everything look better :
.container {
padding-top: 60px;
max-width: 900px;
margin: 0 auto;
.card {
text-align: center;
background: $white;
max-width: 550px;
margin: 0 auto;
padding: 40px;
border-radius: 4px;
border: 1px solid $fade-grey;
margin-bottom: 30px;
p {
padding: 20px 0;
color: $muted-grey;
}
}
}
We are setting max-width
to 550px
and margin
to 0 auto
to make our cards look consistent and horizontally centered. We have now everything we need to start working on our fixed sidebar.
Fixed Sidebar
Before implementing any behaviour, we first need to design our sidebar and to set its very basic styles. Please nituce that in this post, we are only designing the sidebar, not what is going to be inside it (e.g sidebar menu). We might talk about inner menus in another future post. Let's start by writing a very basic markup:
<div class="sidebar">
<div class="sidebar-header">
<svg class="lnr lnr-cross"><use xlink:href="#lnr-cross"></use></svg>
</div>
</div>
Yeah, i know what you are thinking: "it looks pretty short for a sidebar, isn't it ?". Indeed, you are right. But this all we need to have a fully functional sidebar block. We don't even need the sidebar-header
part, but we will use it to display our close sidebar icon.
Styling the sidebar
We will now add the styles that will create our fixed sidebar:
.sidebar {
position: fixed;
top: 0;
left: 0;
height: 100%;
width: 280px;
background: $sidebar;
z-index: 2;
}
Now that you've added this code, your sidebar should look great, with a dark-ish background, full height sizing and fixed position. If you try to scroll, the sidebar should now follow you. But wait, at the moment it is visible and it overlaps the page content. We will start by hiding it. To do this, add the following properties to the above css :
transform: translateX(-281px);
transition: transform 0.4s;
By doing this, we are pushing our sidebar to the left, outside the window. We are also setting the transition property to create a smooth animation when the sidebar comes in. Let's finish with the css and add our sidebar header styles :
.sidebar {
.sidebar-header {
width: 100%;
height: 86px;
display: flex;
justify-content: flex-end;
align-items: center;
svg {
fill: $white;
height: 32px;
width: 32px;
cursor: pointer;
margin-right: 30px;
}
}
}
The last thing we have to do is to define an active state class that we will toggle to open our sidebar :
.sidebar {
&.is-active {
transform: translateX(0);
}
}
This means that when the sidebar has the class .is-active
, it is immediatly translated back to it's original position (wich is 0), creating the slide in / slide out effect. Now we need to implement this behaviour using javascript.
Toggling with javaScript
To execute our javascript action, we need to "listen" to clicks on the hamburger menu icon. And then, when a click is performed, we simply need to toggle the is-active
class on the sidebar
html element. We can achieve that by using a very simple jQuery code :
$(document).ready(() => {
$('.menu svg, .sidebar-header svg').click(() => {
$('.sidebar').toggleClass('is-active')
})
})
What is this little snippet doing ? it gets the clicks performed on both the navbar and the sidebar header svg icons and then executes a class toggle on the sidebar element. Easy isn'it ? You now have a fully functional fixed sidebar.
Converting to push Sidebar
In the first part of this post, we built a fixed sidebar that overlaps content when opened. We are now going to make the same sidebar push the hole content section when opened. Our code is already written, we will change only a few things. You can find the full code example in the pen below.
See the Pen Push Sidebar by Driss Chelouati (@cssninjaStudio) on CodePen.
Css adjustments
To achieve the desired effect, we simple need to push the content wrapper by 280px
, wich is also the sidebar width. To do that, we are simply going to setup an active state css class and assign it to the content wrapper :
.wrapper {
&.is-active {
transform: translateX(280px);
}
}
We also need to define transitions (transitions must have the same duration value for both elements) and an inactive state for the same element:
.wrapper {
transform: translateX(0);
transition: transform 0.4s;
}
A last important thing is to remove the X overflow from the body, to make sure that the hidden part of the wrapper stays hidden when the sidebar is opened. All we need now is some little jQuery magic to finish our job.
Tweak the javascript
We will use the same snippet as the one we used in the first part. We will simply add the .wrapper
element so it gets included too in the classe toggle :
$(document).ready(() => {
$('.menu svg, .sidebar-header svg').click(() => {
$('.sidebar, .wrapper').toggleClass('is-active')
})
})
Great ! You're done and your push sidebar now works. That was really simple !
Epilogue
In this post, we saw how to create fixed sidebars and animate them easily using some css transitions and some very light jQuery. If you want to share your thoughts or ask a question, give it a shot in the comments section. I hope you enjoyed this little session as much as i did writing it and to see you again soon on Css Ninja.