The use of expandable and collapsible panels is widespread on the Internet. There are many plugins and code available that allow you to implement various types of expandable content or ‘accordion’ effects which essentially involve the user clicking on a panel heading to reveal the content underneath. Expandable panels are often used as a way to break up content rich pages into more visually appealing sections, where visitors can choose to read more about a particular section if they wish.
This tutorial walks through the processes and code required to create your own version of expandable panels using a mix of HTML, CSS and jQuery. Modifying and styling the panels is easy and the code has been tested on multiple browsers and devices including Internet Explorer 8, 9 and 10 as well as Chrome, FireFox and Safari. The expandable panels are also responsive and fit 100% of the parent container.
Complete Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Demo of expandable & collapsible panels in jQuery</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript">
(function($) {
$(document).ready(function () {
/*-------------------- EXPANDABLE PANELS ----------------------*/
var panelspeed = 500; //panel animate speed in milliseconds
var totalpanels = 3; //total number of collapsible panels
var defaultopenpanel = 0; //leave 0 for no panel open
var accordian = false; //set panels to behave like an accordian, with one panel only ever open at once
var panelheight = new Array();
var currentpanel = defaultopenpanel;
var iconheight = parseInt($('.icon-close-open').css('height'));
var highlightopen = true;
//Initialise collapsible panels
function panelinit() {
for (var i=1; i<=totalpanels; i++) {
panelheight[i] = parseInt($('#cp-'+i).find('.expandable-panel-content').css('height'));
$('#cp-'+i).find('.expandable-panel-content').css('margin-top', -panelheight[i]);
if (defaultopenpanel == i) {
$('#cp-'+i).find('.icon-close-open').css('background-position', '0px -'+iconheight+'px');
$('#cp-'+i).find('.expandable-panel-content').css('margin-top', 0);
}
}
}
$('.expandable-panel-heading').click(function() {
var obj = $(this).next();
var objid = parseInt($(this).parent().attr('ID').substr(3,2));
currentpanel = objid;
if (accordian == true) {
resetpanels();
}
if (parseInt(obj.css('margin-top')) <= (panelheight[objid]*-1)) {
obj.clearQueue();
obj.stop();
obj.prev().find('.icon-close-open').css('background-position', '0px -'+iconheight+'px');
obj.animate({'margin-top':0}, panelspeed);
if (highlightopen == true) {
$('#cp-'+currentpanel + ' .expandable-panel-heading').addClass('header-active');
}
} else {
obj.clearQueue();
obj.stop();
obj.prev().find('.icon-close-open').css('background-position', '0px 0px');
obj.animate({'margin-top':(panelheight[objid]*-1)}, panelspeed);
if (highlightopen == true) {
$('#cp-'+currentpanel + ' .expandable-panel-heading').removeClass('header-active');
}
}
});
function resetpanels() {
for (var i=1; i<=totalpanels; i++) {
if (currentpanel != i) {
$('#cp-'+i).find('.icon-close-open').css('background-position', '0px 0px');
$('#cp-'+i).find('.expandable-panel-content').animate({'margin-top':-panelheight[i]}, panelspeed);
if (highlightopen == true) {
$('#cp-'+i + ' .expandable-panel-heading').removeClass('header-active');
}
}
}
}
$(window).load(function() {
panelinit();
}); //END LOAD
}); //END READY
})(jQuery);
</script>
<style type="text/css">
/* --------- COLLAPSIBLE PANELS ----------*/
h2, p, ol, ul, li {
margin:0px;
padding:0px;
font-size:13px;
font-family:Arial, Helvetica, sans-serif;
}
ol, ul {
padding:3px 0 10px 22px;
}
li {
padding:0 0 4px 0;
}
hr {
border:none;
height:1px;
border-top:1px dashed #999;
}
#container {
width:300px;
margin:auto;
margin-top:100px;
}
.expandable-panel {
width:100%;
position:relative;
min-height:50px;
overflow:auto;
margin-bottom: 20px;
border:1px solid #999;
}
.expandable-panel-heading {
width:100%;
cursor:pointer;
min-height:50px;
clear:both;
background-color:#E5E5E5;
position:relative;
}
.expandable-panel-heading:hover {
color:#666;
}
.expandable-panel-heading h2 {
padding:14px 10px 9px 15px;
font-size:18px;
line-height:20px;
}
.expandable-panel-content {
padding:0 15px 0 15px;
margin-top:-999px;
}
.expandable-panel-content p {
padding:4px 0 6px 0;
}
.expandable-panel-content p:first-child {
padding-top:10px;
}
.expandable-panel-content p:last-child {
padding-bottom:15px;
}
.icon-close-open {
width:20px;
height:20px;
position:absolute;
background-image:url(icon-close-open.png);
right:15px;
}
.expandable-panel-content img {
float:right;
padding-left:12px;
clear:both;
}
.header-active {
background-color:#D0D7F3;
}
</style>
</head>
<body>
<div id="container">
<div class="expandable-panel" id="cp-1">
<div class="expandable-panel-heading">
<h2>Panel content heading 1<span class="icon-close-open"></span></h2>
</div>
<div class="expandable-panel-content">
<p>This is a regular paragraph within the first collapsible panel.</p>
<hr />
<p>A second paragraph after a HR element within the first collapsible panel.</p>
</div>
</div>
<div class="expandable-panel" id="cp-2">
<div class="expandable-panel-heading">
<h2>Panel content heading 2<span class="icon-close-open"></span></h2>
</div>
<div class="expandable-panel-content">
<p>Another collapsible panel. The following variables can be set expandable panels:</p>
<ol>
<li><em>panelspeed:</em> defines panel expand/collapse speed in milliseconds</li>
<li><em>totalpanels:</em> the total number of colapsible panels used</li>
<li><em>defaultopenpanel:</em> leave at 0 to keep all panels initially closed</li>
<li><em>accordian:</em> sets accordion effect (only one panel can remain open at once)</li>
</ol>
</div>
</div>
<div class="expandable-panel" id="cp-3">
<div class="expandable-panel-heading">
<h2>Panel content heading 3<span class="icon-close-open"></span></h2>
</div>
<div class="expandable-panel-content">
<p><img src="image1.jpg" height="70" alt="penguins" />This last collapsible panel contains an image floated right to the paragraph content.</p>
<p>One thing good to note with the expandable panels is that adding top or bottom padding to the expandable-panel-content class can cause animation issues in IE 8</p>
</div>
</div>
<p style="margin-top:50px;"><a style="color:#CCC;" href="http://www.webdevdoor.com/jquery/expandable-collapsible-panels-jquery/">Return to expandable panels post »</a></p>
</div>
</body>
</html>