Collapsible 2-Tier Side Menu

Suitable for table of content

by kidino

HTML

<div id="side-right">
        <ul id="toc">
            <li><a href="#">Chapter 1</a>
                <ul>
                    <li><a href="#">Sub 1</a></li>
                    <li><a href="#">Sub 2 Sub 2 Sub 2 Sub 2 Sub 2 Sub 2 Sub 2 Sub 2 Sub 2 Sub 2 Sub 2 
                    Sub 2 Sub 2 Sub 2 Sub 2 Sub 2 Sub 2 Sub 2 Sub 2 Sub 2 Sub 2 Sub 2</a></li>
                    <li><a href="#">Sub 3</a></li>
                </ul>
            </li>
            <li><a href="#">Chapter 2 Chapter 2 Chapter 2 Chapter 2 Chapter 2 Chapter 2 Chapter 2 Chapter 2 Chapter 2 </a>
                <ul>
                    <li><a href="#">Sub 1</a></li>
                    <li><a href="#">Sub 2</a></li>
                    <li><a href="#">Sub 3</a></li>
                    <li><a href="#">Sub 4</a></li>
                    <li><a href="#">Sub 5</a></li>
                    <li><a href="#">Sub 6</a></li>
                </ul>
            </li>
            <li><a href="#">Chapter 3</a></li>
        </ul>
    </div>

CSS

div, ul, li, a {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}

ul#toc {
    width: 250px;
    border: 1px solid #ccc;
    border-top: none;
    border-bottom: none;
    overflow:hidden;
    position: relative;
    background-color: #e0e0e0;
    font-family:arial;
}   
        
ul#toc > li  {
    float: left;
    display:block;
    width: 250px;
    position: relative;
    overflow:hidden;
    border-top: 1px solid #dcdcdc;
    border-bottom: 1px solid #bdbdbd;
    }
    
ul#toc > li:hover > a,
ul#toc > li.expand > a {
    border-left: 3px solid #00f;
    padding-left: 4px;
}


ul#toc ul {
    position: absolute;
    width: 240px;
    overflow:hidden;
    left: 10px;
}

ul#toc li.expand ul {
    box-shadow: 0px 0px 5px rgba(0,0,0,0.6);
}

ul#toc ul li  {
    display:block !important;
    position: relative;
    min-height: 30px;
    margin-bottom: 0px;
    background-color: #fff;
    background-color: #e6e6e6;
    border-bottom: 1px solid #cfcfcf;
    border-top: 1px solid #ebebeb;
}

ul#toc ul li:first-child  {
    border-top: none;
}

ul#toc a {
    display:block;
    font-size: 14px;
    padding-left: 7px;
    text-decoration:none;
    color: #666;
    padding-top: 8px;
    padding-bottom: 8px;
    line-height:normal;
}

ul#toc ul a {
    display:block;
    width: 240px;
    z-index: 100;
    font-size: 12px;
    height:auto;
    min-height: 30px;
    overflow: hidden;
    line-height:normal;
    padding-right: 10px;
    padding-top: 8px;
    padding-bottom: 8px;
}

ul#toc > li > a { background-color: #d3d3d3; }
ul#toc ul li a:hover { background-color: #d3d3d3; }
                                
ul#toc li.expand {
    border-bottom: none;
}
ul#toc li.expand > a{
    box-shadow: 0px 0px 5px rgba(0,0,0,0.9);
    position:absolute; width: 250px;
    z-index: 100;
}

ul#toc > li.expand + li {
    box-shadow: 0px 0px 5px rgba(0,0,0,0.9);
}

#side-right {
    width: 250px;
    height: 700px;
    background-color: #ccc;
    
}

JavaScript

$('ul#toc li').each(function(){
        $(this).css( 'height', parseInt( $(this).find('a').css('height') ) + 2 +'px');
    });

$('ul#toc ul').each(function(){
        $(this).css('top',$(this).parent().height() +'px');    
    });
    
    $('ul#toc > li > a').on('click', function(){
        

        if ( $(this).parent().siblings('.expand').length )
        {
            $(this).parent().siblings('.expand').each(function(){
                $(this).removeClass('expand');
                $(this).animate( {height: parseInt( $(this).find('a').css('height') ) + 2 +'px'}  , 300);            
            });
        }
                                          
        if ( $(this).parent().find('ul').length) {
                                             
            if ( $(this).parent().hasClass('expand') ) {
                $(this).parent().removeClass('expand');
                console.log($(this).css('height'));
                $(this).parent().animate( {height: parseInt( $(this).css('height') ) + 2 +'px' }, 300);
                //$(this).find('ul').slideUp();
            } else {
                var li = parseInt( $(this).css('height') ); 
                $(this).parent().find('ul li').each(function(){
                    li += ($(this).height() + 2);
                });
                $(this).parent().addClass('expand');
                $(this).parent().animate( {height: (li-1) +'px'}, 300);  
                //$(this).find('ul').slideDown();
            }
            
        } else {
            $(this).parent().addClass('expand');
        }
    });