Switch On The Code RSS Button - Click to Subscribe
Apr
29

Javascript and CSS Tutorial - How to make Sliding Panels

X
Click the 'X' in the top-right corner to expand and contract this sliding panel.
Sliding Panel: Click the X to see it work
Making Sliding Panels with Javascript and CSS
This tutorial provides a step-by-step guide to creating sliding panels (like the one on the left) using nothing but Javascript and CSS. We used these panels on Gaming Textures so the user could hide parts of the page when they weren't being used.
The first thing we need to do is create all the elements that make up the panel. For this example I went with div elements. There are a total of 4 div elements that make up the entire sliding panel. There are 2 divs in the header, 1 div which slides up and down, and another div which just holds everything.
Let's start by creating the div which holds everything.

<div style="position:relative;width:250px;height:250px;"></div>

This is the div that is going to hold the other parts of the sliding panel. I made it 250x250, but you can make it any size that fits your needs. I went with position:relative; so the panel flows with the rest of the page contents.

As you're probably already aware, this code produces a large invisible square. Let's put on the header so it looks more like a typical window. The header consists of an 18 pixel tall div across the top and another square div which will hold the 'X' button.

<div style="position:relative;width:250px;height:250px;">
   <div style=
         "position:absolute;
         left:0px;
         top:0px;
         width:250px;
         height:18px;
         background-color:#3B587A;"
>

      <div style=
          "position:absolute;
          top:0px;
          right:0px;
          width:18px;
          height:18px;
          background-color:#85A1C2;"
>

      </div>
   </div>
</div>

At this point, you should see something along these lines:


Now let's add the div that will actually be doing the expanding and contracting.

<div style="position:relative;width:250px;height:250px;">
   <div style=
        "position:absolute;
        left:0px;
        top:0px;
        width:250px;
        height:18px;
        background-color:#3B587A;"
>

      <div style=
           "position:absolute;
           top:0px;
           right:0px;
           width:18px;
           height:18px;
           background-color:#85A1C2;"
>

      </div>
   </div>
   <div id="sliderElementId"
           style=
           "position:absolute;
           top:18px;
           left:0px;
           width:250px;
           height:232px;
           background-color:#A6BBCD;"
>

      </div>
</div>

The above code will produce something that looks very similar to the finished product. Placing the 'X' in the top-right corner is trivial, so I'll save it for the finished code at the end of this post. Since Javascript will be modifying this element, we need to assign it an ID. I chose "sliderElementId", but you can choose whatever you want.



Now that the panel is basically complete, let's start adding some Javascript code to handle the sliding. Let's begin by declaring some global variables:

var sliderIntervalId = 0;
var sliderHeight = 232;
var sliding = false;
var slideSpeed = 10;

sliderIntervalId holds the id of the interval that will be animating the slider. I'll explain what that means in more detail later. Since the slider starts expanded, I set sliderHeight equal to 232 - the height of "sliderElementId". sliding is a boolean which keeps track of whether or not the panel is currently sliding. This keeps it from trying to slide again if the user clicks the 'X' while it is already sliding. slideSpeed controls how fast the panel will contract and expand.

Let's now create the function that will be called when the 'X' is clicked.

function Slide()
{
   if(sliding)
      return;
   sliding = true;
   if(sliderHeight == 232)
      sliderIntervalId = setInterval('SlideUpRun()', 30);
   else
      sliderIntervalId = setInterval('SlideDownRun()', 30);
}

The first thing I do is check whether or not the panel is currently sliding. If it is, I simply return out of the function without doing anything. If it makes it past that check, we are going to slide the panel either up or down so I set the sliding variable to true. After that I need to determine whether to slide the panel up or slide it down. I do this by simply checking the value of sliderHeight. If sliderHeight is 232, it's expanded, so I need to contract it. Otherwise, I need to expand it.

I used Javascript's setInterval function to control the animating of the panel. setInterval takes a function to call and the time interval to call it at. I set it to 30, which means the function will be called every 30 milliseconds. I set sliderIntervalId equal to the return value, so I can cancel the interval later when the panel is finished sliding.

I created two functions that setInterval will call: SlideUpRun() and SlideDownRun(). Let's look at SlideUpRun() first.

function SlideUpRun()
{
   slider = document.getElementById('sliderElementId');
   if(sliderHeight <= 0)
   {
      sliding = false;
      sliderHeight = 0;
      slider.style.height = '0px';
      clearInterval(sliderIntervalId);
   }
   else
   {
      sliderHeight -= slideSpeed;
      if(sliderHeight <0)
         sliderHeight = 0;
      slider.style.height = sliderHeight + 'px';
   }
}

The first thing this function does is get the element from the id that was assigned earlier to the sliding panel. The next thing I do is check to see whether or not the panel is finished sliding. I do this by checking the value of sliderHeight. If the value is less than or equal to 0, the panel is fully retracted. If it's finished sliding, I set the value of sliderHeight to 0, I set the height style of the sliding panel to 0 pixels and call clearInterval to stop the animation.

If the panel is not finished sliding, I need to decrease the height by the amount defined in slideSpeed. I then check to make sure the value is not less than zero. Negative values can throw Javascript errors. I then set the height style of the sliding panel to the new sliderHeight.

Let's hook in what we have so far and see what happens. We'll need to add an onclick event handler to the div which will hold the 'X' button. This code will launch Slide(); whenever the div is clicked.

<div style="position:relative;width:250px;height:250px;">
   <div style=
        "position:absolute;
        left:0px;
        top:0px;
        width:250px;
        height:18px;
        background-color:#3B587A;"
>

      <div onclick="Slide();" style=
           "position:absolute;
           top:0px;
           right:0px;
           width:18px;
           height:18px;
           background-color:#85A1C2;"
>

      </div>
   </div>
   <div id="sliderElementId"
           style=
           "position:absolute;
           top:18px;
           left:0px;
           width:250px;
           height:232px;
           background-color:#A6BBCD;"
>

      </div>
</div>


You should now see the above sliding panel. When the square on the right of the header is clicked, the panel should retract like the above example. If you click the square again, a Javascript error will be thrown because we have not yet defined the function to control expanding the sliding panel. Let's do that now.

function SlideDownRun()
{
   slider = document.getElementById('exampleSlider');
   if(sliderHeight>= 232)
   {
      sliding = false;
      sliderHeight = 232;
      slider.style.height = '232px';
      clearInterval(sliderIntervalId);
   }
   else
   {
      sliderHeight += slideSpeed;
      if(sliderHeight> 232)
         sliderHeight = 232;
      slider.style.height = sliderHeight + 'px';
   }
}

This function is very similar to SlideUpRun(). The only major difference is now I'm checking to see if the panel is greater than or equal to 232 to see whether or not the panel is finished sliding. I also increment sliderHeight instead of decrementing it.

That's all the code required for a basic sliding panel. I'll finish up the tutorial by posting all the code required to duplicate the sliding panel that is at the top of this post.

var sliderIntervalId = 0;
var sliderHeight = 232;
var sliding = false;
var slideSpeed = 10;

function Slide()
{
   if(sliding)
      return;
   sliding = true;
   if(sliderHeight == 232)
      sliderIntervalId = setInterval('SlideUpRun()', 30);
   else
      sliderIntervalId = setInterval('SlideDownRun()', 30);
}

function SlideUpRun()
{
   slider = document.getElementById('exampleSlider');
   if(sliderHeight <= 0)
   {
      sliding = false;
      sliderHeight = 0;
      slider.style.height = '0px';
      clearInterval(sliderIntervalId);
   }
   else
   {
      sliderHeight -= slideSpeed;
      if(sliderHeight <0)
         sliderHeight = 0;
      slider.style.height = sliderHeight + 'px';
   }
}

function SlideDownRun()
{
   slider = document.getElementById('exampleSlider');
   if(sliderHeight>= 232)
   {
      sliding = false;
      sliderHeight = 232;
      slider.style.height = '232px';
      clearInterval(sliderIntervalId);
   }
   else
   {
      sliderHeight += slideSpeed;
      if(sliderHeight> 232)
         sliderHeight = 232;
      slider.style.height = sliderHeight + 'px';
   }
}

<div style=
    "position:relative;
     width:250px;
     height:250px;
     margin-bottom:5px;"
>

   <div style=
       "position:absolute;
        width:250px;
        height:18px;
        left:0px;
        top:0px;
        background-color:#3B587A;
        border:1px solid #FFFFFF;"
>

      <div style=
          "position:absolute;
           width:18px;
           height:18px;
           right:0px;
           top:0px;
           background-color:#85A1C2;
           text-align:center;
           border-left:1px solid #FFFFFF;
           color:#000000;
           cursor:pointer;
           padding:0px;"

           onclick="Slide();">

         <table width="100%"
                height="15px"
                cellspacing="0"
                cellpadding="0">

            <tr>
               <td align="center"
                   valign="middle"
                   style="text-size:9pt;">

                  X
               </td>
            </tr>
         </table>
      </div>
   </div>
   <div id="exampleSlider"
        style="position:absolute;
        top:18px;
        left:0px;
        width:250px;
        height:232px;
        background-color:#A6BBCD;
        border:1px solid #FFFFFF;
        color:#000000;
        overflow:hidden;"
>

      <table width="100%" height="100%">
         <tr>
            <td valign="top" style="padding:3px;">
               Click the 'X' in the top-right corner
               to expand and contract this sliding panel.
            </td>
         </tr>
      </table>   
   </div>
</div>

If you'd like to see sliding panels in action, check out Gaming Textures for some good examples.




Posted in CSS, Javascript, All Tutorials by The Reddest |

29 Responses

  1. kate Says:

    i love this script and it’s exactly the kind of thing i’ve been looking for to redo my portfolio. one question.. if i wanted to have multiple sliding panels (with each one showing a different piece of artwork) is there a way to code that using the script just once, rather than for each time you use it? ie.. a way for it to call upon different element ids? thanks!

  2. Brandon Says:

    Absolutely there is. For an example, let’s say you wanted two of these.

    The first thing you’d have to do is put all the html code in the two places you wanted the panels. Then, you’d need to give the sliding panels different id’s. In the above example, the id is “exampleSlider”. Let’s call the new ones “exampleSlider1″ and “exampleSlider2″.

    The next thing we’d do is modify the Slide() method to take the element you want to slide. Just change the method signature to function Slide(element).

    Now, to get the element into the Slide method, we need to modify what the onclick is doing in the top right corner. For the first sliding panel, change the onclick to “Slide(document.getElementById(’exampleSlider1′));”. For the second one, do the same thing but pass ‘exampleSlider2′ into document.getElementById.

    Now that the element is inside the Slide function, we need a way to get it inside the two run methods. Make a new global variable to hold the element - “var slideElement”. In the Slide method, set the variable to the element passed in after the if(sliding) check.

    All that’s left to do now is use the global slideElement in the two run methods instead of calling ‘getElementById’.

    This is the quickest way I can think of to get multiple sliding panels. Let us know when you get your portfolio finished, we’d love to see how you implemented these.

  3. Rodrigo Says:

    Hi,
    Loved your code. I’m learning css for a short time and this is a good step forward to mix it with javascript (first timer!!!). Flexible and easy to use and style! However, I didn’t manage to have the same behavior in firefox. IE works fine, but there is no behavior in Firefox. Do you know if there any way to make it work in FireFox? Thanks

  4. Brandon Says:

    I actually developed the code using Firefox, so it works just fine for me. One thing to look at would be Firefox’s Error Console: Tools->Error Console. Clear the console, then load your page again and see if there are any errors. Sometime IE is more forgiving than Firefox when it comes to errors.

  5. Ahmed Says:

    This a good script with a very good description .
    About the code modification for sliding more than one panel there will be a problem that all the sliding panels will have one “sliderHeight” variable so if a panel slided up all the other panels have to slide down.
    I will try to figure out a solution for it.

  6. Premium Mike Says:

    Is there a way to download a packaged version?

  7. Brandon Says:

    @Rodrigo
    You’re absolutely right about that being a problem. Here is a solution: instead of using the variable sliderHeight - just parse the height of the panel from slider.style.height.

    So the else statement in SlideUpRun will look something like this:

    sliderHeight = parseInt(slider.style.height);
    sliderHeight -= sliderSpeed;
    if(sliderHeight <0)
    sliderHeight = 0;

    slider.style.height = sliderHeight + ‘px’;

    Even though slider.style.height has a ‘px’ in the string, parseInt still works because it parses until it reaches a non-numerical value. So it will just ignore the ‘px’.

    @Premium Mike
    I hadn’t designed the code to be packaged - it was more of a way to give coders a technique on which to build their own packages. If I receive more requests for a packaged version, I’ll put one together. For now, however, there isn’t one available.

  8. Tim Says:

    Great script!! Is there a way we can change the plus sign to minus when the div expands? and make it plus sign when it collapses??

  9. The Reddest Says:

    There sure is! Right now there is a table cell that holds the ‘X’ in the top-right corner. What you need to do is give that cell an id and set its innerHTML when the panel is finished sliding. So now that table cell would look something like:

    <td align=”center”
    valign=”middle”
    id=”exampleSlider1X”
    style=”text-size:9pt;”>-</td>

    I set the id to the id of the slider plus an ‘X’. This way you can easily do the multiple sliders as mentioned in one of my previous comments. I also replaced the ‘X’ with a ‘-’ since the panel is expanded by default.

    In SlideUpRun and SlideDownRun, add the code to change the innerHTML of the table cell at the end of the ‘if’ statements. So in SlideUpRun, you’ll have:

    if(sliderHeight <= 0)
    {
    sliding = false;
    sliderHeight = 0;
    slider.style.height = ‘0px’;
    clearInterval(sliderIntervalId);

    //set the cell’s innerHTML to ‘+’
    document.getElementById(slider.id + ‘X’).innerHTML = ‘+’;
    }

    Now just do the same thing in SlideDownRun, but set the innerHTML to a ‘-’.

    You can replace the ‘+’ and ‘-’ with image tags if you want a more graphical look to the sliders. Enjoy.

  10. The Reddest Says:

    Hey guys. We just posted a new sliding panel tutorial that uses our new generic animation code. I would highly recommend using that tutorial for sliding panels because it makes the process much easier and much more extensible. Cheers.

  11. Corey Klemow Says:

    Lovely!

    Is there any way to make it so the “invisible” part of the box is not taking up space when the box is closed? (i.e. any text below it would be *directly* below it, and be pushed further down when the box opens).

    The kicker is that I’m looking for a way to do this without using anything that needs to go into the Head of the page, as I’m looking to add it to a php-based product page in a new shopping cart system I’m about to switch over to. It needs to be something that will work solely in the Body. Any pointers?

    I have other options, like simply making the info pop up in a separate window instead of using the slidebox, but your dropdown box is so pretty and so very nearly *almost* what I need that I’d like to see if I can make it work!

    Thanks!

  12. Lilly Says:

    Really very nice..
    Thanks a lot but I have a simple question. In the examples you gave, I need to know the width of the div, what if I want to set the width of the div to 100% to to width in pixels?? How can I slide the window when I don’t know the width and so don’t know the new left?

  13. Todd Thelin Says:

    I wanted to let you know that there is an error in your code if the person is following along. In SlideUpRun you call the element sliderElement but in SlideDownRun you call exampleSlider which is not what the div is called. In your full code it is correct. This is a fantastic example. Thank you for sharing with everyone.

  14. David Says:

    I’m impressed. Great tutorial

  15. Bryan Says:

    Hey great tutorial! I am new at this and was wondering if someone could post the code for the completed js and html for multiple sliding panels because some how I got lost and now it’s just a mess!! This pretty much sums up what I was going for http://www.gigxl.com/

  16. Chris Says:

    Does anyone know how i can change the code so that when the webpage is opened for the first time the sliding panel is now contracted and requires clicking on the cross to open it?

    Thanks

  17. devraj Says:

    very simple but excellent sliding tutorial. thanks for providing this type of code.
    dev

  18. luc Says:

    I have the same question that Chris.
    Does anyone know how i can change the code so that when the webpage is opened for the first time the sliding panel is now contracted and requires clicking on the cross to open it?

  19. The Reddest Says:

    I’ll whip up a new tutorial to cover starting the panel contracted. Until then, I would recommend the newer sliding panels tutorial here. It uses our generic animation code, which is a little easier to understand.

  20. The Reddest Says:

    Here’s a new tutorial on how to create sliding panels which start up and slide down.

  21. SHINOJ K Says:

    Hi,

    How to change web page view according to scren resolution.Thanks in Advance.

  22. Nathan Scheffey Says:

    Hi-
    Great code first of all, very useful.
    I was wondering what it would take to have other elements on the page move around as the panel expands and contracts, rather than having the panel expand over other elements. Would this be a relatively easy CSS change, or is it not possible?
    Thanks in advance for any help,
    Nate

  23. good Says:

    good thanks

  24. Shorewire Says:

    Is there a way to start the window at a closed state, and expand the window on click?

  25. The Reddest Says:

    Yes, check out this tutorial:

    http://blog.paranoidferret.com/index.php/2008/05/23/javascript-sliding-panels-starting-the-panels-up/

  26. majid Says:

    ” u need to include in ||||||||->style=”position:absolut;” then only it works as per ur demo “

    Click the ‘X’ in the top-right corner
    to expand and contract this sliding panel.

  27. Jota Says:

    The code does’nt work for me on IE

    Please check this out:

    http://www.moosic.xf-s.com/slide.php

    I hope you can help me to solve it.

    Thanks !

Tracebacks / Pingbacks


  1. Best of April 2007 | Best of the Month


  2. All in a days work…


Leave a Comment

Please note: Comment moderation is enabled and may delay your comment. There is no need to resubmit your comment.

Powered by WP Hashcash