Sliding Panels with CSS3 Transitions

6/11/14

CSS3 Transitions bring the capability for smooth css property changes. Transitions make it easy to implement components with animated interactions. For this example, I'll review the basics of transitions and implement sliding panels.

A transition is defined as a css property on an element with a corresponding transition-property, transition-duration, transition-timing-function, and transition-delay. The shorthand is transition with the properties defined in order. An example with background color:

      
    div {
      background-color: green;
      /* timing defaults to 'ease' */
      /* delay defaults to '0s' */
      transition: background-color 1s;
    }
      
    

Any time I change the background-color css property on the div, the change will be animated smoothly over a 1s duration. Let’s setup a hover selector to change the background color.

      
    div:hover {
      background-color: red;
    }
      
    

The example in action:

Alternative to triggering our transition in CSS, we can trigger it in JavaScript. For example, let’s say I want to change that color on click instead of hover:

      
    var example = document.getElementById('example');
    example.addEventListener(‘click’, function (e) {
      this.style.backgroundColor = 'yellow';
    });
      
    

Now that I've shown the basics, let's create a sliding panel module we could use for a variety of applications. I want a design that supports 1 active item at a time, and any number of additional items that can be browsed from right to left when clicked.

First, I’ll create a container to hold all my items.

      
  <div id="example" class="panel-container">
    <div class="panel active"></div>
    <div class="panel"></div>
  </div>
      
    

In order to apply position changes to the panels, I'll need a way to change the active item. For this I'll use two additional classes, next and prev. Next and prev will setup positions where I want to transition items from and to within the panel container.

      
  <!-- no prev shown, as it is the state after active -->
  <div id="example" class="panel-container">
    <div class="panel active"></div>
    <div class="panel next hide"></div>
  </div>
      
    

The css to position our panel classes looks like this:

      
  /* relatively positioned parent,
    so we can absolutely position our
    panel children */
  .panel-container {
    height: 100px;
    position: relative;
    width: 100px;
  }

  /* height and width set to
    fit the panel container */
  .panel {
    height: 100px;
    position: absolute;
    transition: left 1s;
    width: 100px;
  }

  .active {
    left: 0;
  }

  .next {
    left: 100px;
  }

  .prev {
    left: -100px;
  }
      
    

So far so good, with one minor issue, the items will currently show past the height and width boundaries of the container because of absolute positioning. The result is our items positioned next to each other:

We can account for this by setting the overflow property on our panel container to hidden.

      
  .panel-container {
    height: 100px;
    position: relative;
    overflow: hidden;
    width: 100px;
  }
      
    

Now that our container and items are setup, the last piece needed is a trigger to animate the position of panel items with the transition. In JavaScript, I'll register a click event listener on the panel container that will tell me when I need to show the next item. To show the next item, I'll manipulate the appropriate element classes.

      
  var panelContainer = document.getElementById('panel-container');
  panelContainer.addEventListener('click', function (e) {
    var active = this.querySelector('.active');
    var nextElementSibling = active.nextElementSibling;

    if (nextElementSibling) {
      // move the active to prev, -100 px left
      active.classList.remove('active');
      active.classList.add('prev');

      // move the next to active, 0 px left
      nextElementSibling.classList.remove('next');
      nextElementSibling.classList.add('active');
    }
  });
      
    

The sliding panels in action with a few extra children:

To improve upon this for something like a drill down menu, we could add a hook to go back, and manipulate classes for a transition in the opposite direction. I'll leave the drill down menu for another time, or post. I hope you enjoyed this intro to CSS3 Transitions. Comments and suggestions welcome.

References used in this post:

comments powered by Disqus