Nested Accordion

A simple, nestable accordion with some examples of nesting levels and a media query.

Nested Accordion

A simple accordion that allows for a nested structure. The style comes with some examples of how to style three levels and how to add a media query for decreasing the size on smaller screens. Clicking a trigger element will open the content.

The HTML

<ul id="cbp-ntaccordion" class="cbp-ntaccordion">
	<li>
		<h3 class="cbp-nttrigger">Oat cake tootsie roll</h3>
		<div class="cbp-ntcontent">
			<p><!-- ... --></p>
			<ul class="cbp-ntsubaccordion">
				<li>
					<h4 class="cbp-nttrigger">Donut pastry</h4>
					<div class="cbp-ntcontent"><!-- ... --></div>
				</li>
				<li>
					<h4 class="cbp-nttrigger">Carrot cake</h4>
					<div class="cbp-ntcontent">
						<!-- ... -->
						<ul class="cbp-ntsubaccordion">
							<li>
								<h5 class="cbp-nttrigger">Donut pastry</h5>
								<div class="cbp-ntcontent"><!-- ... --></div>
							</li>
							<li><!-- ... --></li>
							<li><!-- ... --></li>
						</ul>
					</div>
				</li>
				<li>
					<h4 class="cbp-nttrigger">Tootsie roll marshmallow</h4>
					<div class="cbp-ntcontent">
						<!-- ... -->
					</div>
				</li>
			</ul>
		</div>
	</li>
	<li><!-- ... --></li>
	<li><!-- ... --></li>
	<li><!-- ... --></li>
</ul>

The CSS

/* Icon font for arrow icons */
@font-face {
	font-family: 'icomoon';
	src:url('../fonts/icomoon_arrows/icomoon.eot');
	src:url('../fonts/icomoon_arrows/icomoon.eot?#iefix') format('embedded-opentype'),
		url('../fonts/icomoon_arrows/icomoon.woff') format('woff'),
		url('../fonts/icomoon_arrows/icomoon.ttf') format('truetype'),
		url('../fonts/icomoon_arrows/icomoon.svg#icomoon') format('svg');
	font-weight: normal;
	font-style: normal;
} /* Iconfont by Icomoon http://icomoon.io/ */

/* Accordion style */
.cbp-ntaccordion {
	list-style: none;
	margin: 0;
	padding: 0;
}

.cbp-ntsubaccordion {
	list-style: none;
}

.cbp-ntaccordion .cbp-nttrigger {
	cursor: pointer;
} 

.cbp-ntaccordion h3 {
	margin: 0 0 0.3em;
	padding: 1em 0 0.5em;
	border-bottom: 1px solid #ddd;
	font-size: 2.75em;
	font-weight: 300;
}

.cbp-ntaccordion h4 {
	font-size: 1.2em;
	text-transform: uppercase;
	letter-spacing: 0.4em;
	padding: 0.5em 0 0.5em;
	margin: 0 0 0.5em;
}

.cbp-ntaccordion h5 {
	font-size: 1.2em;
	color: #aaa;
	padding: 0.5em 0 0.5em;
	margin: 0 0 0.5em;
}

.cbp-ntaccordion .cbp-ntcontent p {
	color: #888;
	font-size: 1.25em;
	font-weight: 300;
	line-height: 1.5;
	padding: 0.2em 0 1.5em;
	margin: 0;
}

/* Arrow icons */
.cbp-ntaccordion > li > .cbp-nttrigger:before,
.cbp-ntsubaccordion > li > .cbp-nttrigger:before {
	font-family: 'icomoon';
	speak: none;
	font-weight: normal;
	font-variant: normal;
	text-transform: none;
	line-height: 1;
	color: #ddd;
	margin-right: 0.5em;
	-webkit-font-smoothing: antialiased;
}

.cbp-ntaccordion > li > .cbp-nttrigger:before {
	font-size: 75%;
}

.cbp-ntaccordion > li > .cbp-nttrigger:before {
	content: "36";
}
.cbp-ntaccordion > li > .cbp-nttrigger:hover:before {
	content: "35";
	color: inherit;
}
.cbp-ntaccordion > li.cbp-ntopen > .cbp-nttrigger:before,
.no-js .cbp-ntaccordion > li > .cbp-nttrigger:before {
	content: "34";
	color: inherit;
}

.cbp-ntsubaccordion > li > .cbp-nttrigger:before {
	content: "32";
}
.cbp-ntsubaccordion > li > .cbp-nttrigger:hover:before {
	content: "33";
	color: inherit;
}
.cbp-ntsubaccordion > li.cbp-ntopen > .cbp-nttrigger:before,
.no-js .cbp-ntsubaccordion > li > .cbp-nttrigger:before {
	content: "31";
	color: inherit;
}

/* Initial height is zero */
.cbp-ntaccordion .cbp-ntcontent {
	height: 0;
	overflow: hidden;
}

/* When open, set height to auto */
.cbp-ntaccordion .cbp-ntopen > .cbp-ntcontent,
.cbp-ntsubaccordion .cbp-ntopen > .cbp-ntcontent,
.no-js .cbp-ntaccordion .cbp-ntcontent {
	height: auto;
}

/* Example for media query */
@media screen and (max-width: 32em) { 

	.cbp-ntaccordion {
		font-size: 70%;
	}

}

The JavaScript

/**
 * jquery.cbpNTAccordion.js v1.0.0
 * http://www.codrops.com
 *
 * Licensed under the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
 * 
 * Copyright 2013, Codrops
 * http://www.codrops.com
 */
;( function( $, window, undefined ) {

	'use strict';

	// global
	var $body = $( 'html, body' );

	$.CBPNTAccordion = function( options, element ) {
		this.$el = $( element );
		this._init( options );
	};

	// the options
	$.CBPNTAccordion.defaults = {};

	$.CBPNTAccordion.prototype = {
		_init : function( options ) {
			// options
			this.options = $.extend( true, {}, $.CBPNTAccordion.defaults, options );
			// cache some elements and initialize some variables
			this._config();
			// initialize/bind the events
			this._initEvents();
		},
		_config : function() {

			// the clickable items
			this.$items = this.$el.find( '.cbp-nttrigger' );

		},
		_initEvents : function() {
			
			this.$items.on( 'click.cbpNTAccordion', function() {
				var $listItem = $( this ).parent();
				if( $listItem.hasClass( 'cbp-ntopen' ) ) {
					$listItem.removeClass( 'cbp-ntopen' );
				}
				else {
					$listItem.addClass( 'cbp-ntopen' );
					$body.scrollTop( $listItem.offset().top );
				}
			} );

		},
		destroy : function() {
			this.$items.off( '.cbpNTAccordion' ).parent().removeClass( 'cbp-ntopen' );
		}
	};

	var logError = function( message ) {
		if ( window.console ) {
			window.console.error( message );
		}
	};

	$.fn.cbpNTAccordion = function( options ) {
		if ( typeof options === 'string' ) {
			var args = Array.prototype.slice.call( arguments, 1 );
			this.each(function() {
				var instance = $.data( this, 'cbpNTAccordion' );
				if ( !instance ) {
					logError( "cannot call methods on cbpNTAccordion prior to initialization; " +
					"attempted to call method '" + options + "'" );
					return;
				}
				if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) {
					logError( "no such method '" + options + "' for cbpNTAccordion instance" );
					return;
				}
				instance[ options ].apply( instance, args );
			});
		} 
		else {
			this.each(function() {	
				var instance = $.data( this, 'cbpNTAccordion' );
				if ( instance ) {
					instance._init();
				}
				else {
					instance = $.data( this, 'cbpNTAccordion', new $.CBPNTAccordion( options, this ) );
				}
			});
		}
		return this;
	};

} )( jQuery, window );

Tagged with:

Manoela Ilic

Manoela is the main tinkerer at Codrops. With a background in coding and passion for all things design, she creates web experiments and keeps frontend professionals informed about the latest trends.

Stay up to date with the latest web design and development news and relevant updates from Codrops.