1

As you can see in the below code snippet I have a vertical sidebar that can become wider when a TOGGLE button is clicked. The Sidebar eases in with an animation and additionally displays the description text when the sidebar is wide. I think I achieved all of this properly.

My concern is more about my code. It doesn't feel right. Is there anyway I can do this all with simply adding and removing css classes?

Additionally, I would like advice on the way I am using delay to make sure when the extra description text appears it doesn't look horrible.

var menuSize = 'Small';

$(".js-menu-toggle").click(function(e) {
  e.preventDefault();

  if (menuSize == 'Small') {
    $('#sidebar').css('width', '180px');
    $('#content-wrapper').css('margin-left', '180px');

    $('#sidebar').css('-webkit-transition', 'all 0.3s ease');
    $('#sidebar').css('-moz-transition', 'all 0.3s ease');
    $('#sidebar').css('-ms-transition', 'all 0.3s ease');
    $('#sidebar').css('-o-transition', 'all 0.3s ease');
    $('#sidebar').css('transition', 'all 0.3s ease');
    $('#app-wrapper').css('-webkit-transition', 'all 0.3s ease');
    $('#app-wrapper').css('-moz-transition', 'all 0.3s ease');
    $('#app-wrapper').css('-ms-transition', 'all 0.3s ease');
    $('#app-wrapper').css('-o-transition', 'all 0.3s ease');
    $('#app-wrapper').css('transition', 'all 0.3s ease');

    $('.menu-item-desc').delay(120).show(0);

    menuSize = 'Large'
  } else {
    $('#sidebar').css('width', '50px');
    $('#content-wrapper').css('margin-left', '50px');

    $('#sidebar').css('-webkit-transition', 'all 0.3s ease');
    $('#sidebar').css('-moz-transition', 'all 0.3s ease');
    $('#sidebar').css('-ms-transition', 'all 0.3s ease');
    $('#sidebar').css('-o-transition', 'all 0.3s ease');
    $('#sidebar').css('transition', 'all 0.3s ease');
    $('#content-wrapper').css('-webkit-transition', 'all 0.3s ease');
    $('#content-wrapper').css('-moz-transition', 'all 0.3s ease');
    $('#content-wrapper').css('-ms-transition', 'all 0.3s ease');
    $('#content-wrapper').css('-o-transition', 'all 0.3s ease');
    $('#content-wrapper').css('transition', 'all 0.3s ease');

    $('.menu-item-desc').hide();

    menuSize = 'Small'
  }
});
html,
body {
  height: 100vh;
}

#sidebar {
  position: fixed;
  top: 0;
  left: 0;
  width: 50px;
  height: 100%;
  z-index: 2;
  background-color: #102027;
  color: #fff;
}

#sidebar ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

#sidebar a {
  color: #fff;
}

#content-wrapper {
  position: relative;
  top: 0;
  left: 0;
  overflow: hidden;
  height: 100%;
  margin-left: 50px;
  padding-top: 100px;
  padding-bottom: 30px;
}

#header-wrapper {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 2;
  overflow: hidden;
  width: 100%;
  height: 100px;
}

#header {
  width: 100%;
  height: 50px;
  background-color: #fff;
}

#subheader {
  width: 100%;
  height: 50px;
  background-color: #37474f;
  color: #fff;
  clear: right;
}

#content {
  position: relative;
  top: 0;
  left: 0;
  overflow: auto;
  z-index: 1;
  width: 100%;
  height: 100%;
  padding-top: 15px;
  padding-bottom: 15px;
}

#footer {
  position: absolute;
  bottom: 0;
  left: 0;
  z-index: 2;
  overflow: hidden;
  width: 100%;
  height: 30px;
  line-height: 30px;
  border-top: solid 1px #cfcfcf;
  background: #fff;
}

.menu-item-desc {
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="sidebar">
  <a class="js-menu-toggle" href="#">TOGL</a>
  <ul>
    <li>Item 1<span class="menu-item-desc"> - Item 1 Desc</span></li>
    <li>Item 2<span class="menu-item-desc"> - Item 2 Desc</span></li>
    <li>Item 3<span class="menu-item-desc"> - Item 3 Desc</span></li>
  </ul>
</div>
<div id="content-wrapper">
  <div id="header-wrapper">
    <div id="header" class="container-fluid">Header</div>
  </div>
  <div id="content" class="container-fluid">PRIMARY CONTENT</div>
</div>
Blake Rivell
  • 13,105
  • 31
  • 115
  • 231

5 Answers5

2

Yes you can! Use addClass, removeClass and toggleClass accordingly.

For example, the #sidebar element can have a class assigned to it:

.toggle-slidein {
  -webkit-transition: all 0.3s ease;
  -moz-transition: all 0.3s ease;
  -ms-transition: all 0.3s ease;
  -o-transition: all 0.3s ease;
}

In your jQuery you can apply it like so:

$('#sidebar').addClass('toggle-slidein');

That takes care of these lines of code:

$('#sidebar').css('-webkit-transition', 'all 0.3s ease');
$('#sidebar').css('-moz-transition', 'all 0.3s ease');
$('#sidebar').css('-ms-transition', 'all 0.3s ease');
$('#sidebar').css('-o-transition', 'all 0.3s ease');
$('#sidebar').css('transition', 'all 0.3s ease');

You can extend this to the rest of your code as you see fit.

Edit: providing toggleClass example for sidebar and content-wrapper:

First add some CSS classes that will represent the changes to the elements you want to dynamically change.

.sidebar--large {
  width: 180px;
}
.content-wrapper--pushleft {
  margin-left: 180px;
}

Then in your jQuery:

$(".js-menu-toggle").click(function(e) {
  e.preventDefault();

  if (menuSize == 'Small') {
    $('#sidebar').toggleClass('sidebar--large');
    $('#content-wrapper').toggleClass('content-wrapper--pushLeft');
    //... other code
    menuSize = 'Large';

  } else {
    $('#sidebar').toggleClass('sidebar--large');
    $('#content-wrapper').toggleClass('content-wrapper--pushLeft');
    //... other code
    menuSize = 'Small';
  }
}

The jQuery code using toggleClass creates a toggle effect by checking for the specified class name; so the class names are added if missing, and removed if already set on the element.

AGE
  • 3,752
  • 3
  • 38
  • 60
1

As mentioned in some other answers (I noticed after writing my code), you could use jQuery's toggleClass function to achieve this.

$(".js-menu-toggle").click(function(e) {
  e.preventDefault();
  $("#sidebar").toggleClass("expanded");
  $("#content-wrapper").toggleClass("expanded");
});
html,
body 

{
  height: 100vh;
}

#sidebar {
  position: fixed;
  top: 0;
  left: 0;
  width: 50px;
  height: 100%;
  z-index: 2;
  background-color: #102027;
  color: #fff;
  transition: all 0.3s ease;
  overflow: hidden;
   white-space: nowrap;
}
#sidebar.expanded {
   width: 180px;
}
#sidebar .menu-item-desc {
   display: inline-block;
   white-space: nowrap;
  transition: all 0.3s ease;
    opacity: 0;
   visibility: hidden;
}
#sidebar .menu-item-desc:hover{
   display: block;
}
#sidebar.expanded .menu-item-desc {
   opacity: 1;
    visibility: visible;
}
#sidebar ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

#sidebar a {
  color: #fff;
}

#content-wrapper {
  position: relative;
  top: 0;
  left: 0;
  overflow: hidden;
  height: 100%;
  margin-left: 50px;
  padding-top: 100px;
  padding-bottom: 30px;
  transition: all 0.3s ease;
}
#content-wrapper.expanded {
    margin-left: 180px;
}
#header-wrapper {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 2;
  overflow: hidden;
  width: 100%;
  height: 100px;
}

#header {
  width: 100%;
  height: 50px;
  background-color: #fff;
}

#subheader {
  width: 100%;
  height: 50px;
  background-color: #37474f;
  color: #fff;
  clear: right;
}

#content {
  position: relative;
  top: 0;
  left: 0;
  overflow: auto;
  z-index: 1;
  width: 100%;
  height: 100%;
  padding-top: 15px;
  padding-bottom: 15px;
}

#footer {
  position: absolute;
  bottom: 0;
  left: 0;
  z-index: 2;
  overflow: hidden;
  width: 100%;
  height: 30px;
  line-height: 30px;
  border-top: solid 1px #cfcfcf;
  background: #fff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="sidebar">
  <a class="js-menu-toggle" href="#">TOGL</a>
  <ul>
    <li>Item 1<span class="menu-item-desc"> - Item 1 Desc</span></li>
    <li>Item 2<span class="menu-item-desc"> - Item 2 Desc</span></li>
    <li>Item 3<span class="menu-item-desc"> - Item 3 Desc</span></li>
  </ul>
</div>
<div id="content-wrapper">
  <div id="header-wrapper">
    <div id="header" class="container-fluid">Header</div>
  </div>
  <div id="content" class="container-fluid">PRIMARY CONTENT</div>
</div>
Chrisstar
  • 626
  • 5
  • 23
  • Hey I love this example, however the opacity 0 technique is messing up my UI since the menu-item-desc is actually taking up space on the page. If the user puts their cursor to the right side of the small version of the menu it will cause a hover on the li because their cursor is technically over top of the menu-item-desc. Is there anyway I can get the best of both worlds? The opacity effect without the menu-item-desc taking up space when opacity=0? – Blake Rivell Aug 03 '17 at 15:08
  • You could use an animation to set it to display: none after the opacity reaches 0. – Chrisstar Aug 03 '17 at 15:14
  • would I do this by creating another class that does the animation or sets the display none? – Blake Rivell Aug 03 '17 at 17:05
  • thank you. So it was a matter of using Visibility: visible and hidden on the .menu-item-disc classes correct? – Blake Rivell Aug 09 '17 at 20:37
0

Woo buddy! That's a lot of CSS you have in your Javascript! Yes, you can simply put all of that into a CSS class and then add/remove said class dynamically in your Javascript. Check out this question that should answer what you're looking for :)

Here!

Alice Yu
  • 176
  • 1
  • 8
0

Yes you can.

If you create classes with your required css styles, you can then toggle them with jquery:

$('#sidebar').toggleClass('class-name', true) adds the class $('#sidebar').toggleClass('class-name', false) removes the class

Simply add classes for each menu size and add/remove them as required inside the event.

Seb Morris
  • 380
  • 1
  • 8
  • do the transitions go on the classes or on the divs? – Blake Rivell Aug 02 '17 at 14:49
  • The transitions should be included with classes. I would suggest creating classes for each element, depending on the menu size. For instance, create a `.sidebar-large` class which you can then toggle on if the sidebar is large. Add the transitions to this `.sidebar-large` class. – Seb Morris Aug 02 '17 at 14:51
  • The transition should be a standard rule of the element in question, in any state that it is in, the classes you add and remove should have the position/size changes declared. – UncaughtTypeError Aug 02 '17 at 14:53
  • @UncaughtTypeError If I do this and .sidebar-large class has a width of 180px and I create a content-wrapper large class with a margin-left of 180px will this override the original div styles? That is my concern. – Blake Rivell Aug 02 '17 at 14:55
  • @BlakeRivell Sure, it should just be a simple matter of specificity, so make sure that you have the right selectors declared to over-qualify default styles. – UncaughtTypeError Aug 02 '17 at 15:16
0

Nice question I think what you are looking for is .toggleClass method in jquery or you can use .addClass and .removeClass I have supplied links for it here:

Sem
  • 116
  • 2
  • what class would I be toggling. A class that changes the width and margin of my elements or a class that has the transitions? – Blake Rivell Aug 02 '17 at 14:54
  • Firstly you need to have the code of your transition/change of margin etc. and then use the .toggleClass function. I am not quit sure if what I told you helps you. Let me know though! Hope I helped you. – Sem Aug 02 '17 at 15:01