Problem
I’m putting together a video website for our company, with a working accordion. It works, but it using the same class name for each section creates issues with the expanding and collapsing. I found a solution, but I’m going to need 13 similar sections for 13 lessons, and having to recreate the same code repeatedly in CSS, JS, and HTML, I have to believe there is a better way to do this.
As the “IT Guy” who just got tossed into this stuff, I’d like to create something a bit cleaner.
$(document).ready(function() {
//lesson 1
$('.l1-vid').click(function() {
if($(this).next().is(':hidden') != true) {
$(this).removeClass('active');
$(this).next().slideUp("normal");
} else {
$('.l1-vid').removeClass('active');
$('#l1-vidlink').slideUp('normal');
if($(this).next().is(':hidden') == true) {
$(this).addClass('active');
$(this).next().slideDown('normal');
}
}
});
$('.l1').click(function() {
if($(this).next().is(':hidden') != true) {
$(this).removeClass('active');
$(this).next().slideUp("normal");
$('.l1-vid').removeClass('active');
$('#l1-vidlink').slideUp('normal');
} else {
$('.l1').removeClass('active');
$('.l1-info').slideUp('normal');
if($(this).next().is(':hidden') == true) {
$(this).addClass('active');
$(this).next().slideDown('normal');
}
}
});
//lesson 2
$('.l2-vid').click(function() {
if($(this).next().is(':hidden') != true) {
$(this).removeClass('active');
$(this).next().slideUp("normal");
} else {
$('.l2-vid').removeClass('active');
$('#l2-vidlink').slideUp('normal');
if($(this).next().is(':hidden') == true) {
$(this).addClass('active');
$(this).next().slideDown('normal');
}
}
});
$('.l2').click(function() {
if($(this).next().is(':hidden') != true) {
$(this).removeClass('active');
$(this).next().slideUp("normal");
$('.l2-vid').removeClass('active');
$('#l2-vidlink').slideUp('normal');
} else {
$('.l2').removeClass('active');
$('.l2-info').slideUp('normal');
if($(this).next().is(':hidden') == true) {
$(this).addClass('active');
$(this).next().slideDown('normal');
}
}
});
//Collapse all on load
$('.l1-info').hide();
$('#l1-vidlink').hide();
$('.l2-info').hide();
$('#l2-vidlink').hide();
//Expand all link
$('.expand').click(function(event){
$('.l2').next().slideDown('normal');
{$('.l2').addClass('active');}
$('.l1').next().slideDown('normal');
{$('.l1').addClass('active');}
}
);
//collapse all link
$('.collapse').click(function(event){
$('.l2').next().slideUp('normal');
{$('.l2').removeClass('active');}
$('.l2-vid').removeClass('active');
$('#l2-vidlink').slideUp('normal');
$('.l1').next().slideUp('normal');
{$('.l1').removeClass('active');}
$('.l1-vid').removeClass('active');
$('#l1-vidlink').slideUp('normal');
}
);
});
@import url(//fonts.googleapis.com/css?family=Volkhov:700,700italic,400italic,400);
@import url(http://fonts.googleapis.com/css?family=Oswald);
@font-face {
font-family : "'Oswald'";
font-style : normal;
font-weight : 400;
src : local('Oswald Regular'), local('Oswald-Regular'), url(http://themes.googleusercontent.com/static/fonts/oswald/v8/Y_TKV6o8WovbUd3m_X9aAA.ttf) format('truetype');
}
body{
background-color: #f6f6f6;
font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
color: black;
}
.content{
width: 50%;
margin: auto;
}
ul{
list-style: none;
}
li{
padding-left: inherit;
list-style: circle;
margin-left: 20px;
padding-left: 20px;
padding-bottom: 3px;
padding-top: 3px;
}
/*---------------Lesson 1---------------*/
.l1 {
width: 100%;
float: left;
background: #fff;
padding-left:20px;
padding-top:18px;
cursor: pointer;
color: #0079C1;
display: block;
font-weight: normal;
margin: 1px;
padding: 8px 15px;
border: 1px solid #E5E5E5;
}
.l1::after{
content: "+";
float: left;
padding-right: 15px;
}
.l1-info {
width: 100%;
background-color: #f6f6f6;
border: 1px solid #E5E5E5;
padding-right: 31px;
display: flex;
}
.l1-vid{
background: url('play.png') no-repeat left center !important;
padding-left: inherit;
list-style: none;
margin-left: 0;
}
.l1-vid a{
cursor: pointer;
}
.l1-vid::after{
content: "" !important;
}
#l1-vidlink{
padding-left: inherit;
}
/*---------------End Lesson 1---------------*/
/*---------------Lesson 2---------------*/
.l2 {
width: 100%;
float: left;
background: #fff;
padding-left:20px;
padding-top:18px;
cursor: pointer;
color: #0079C1;
display: block;
font-weight: normal;
margin: 1px;
padding: 8px 15px;
border: 1px solid #E5E5E5;
}
.l2::after{
content: "+";
float: left;
padding-right: 15px;
}
.l2-info {
width: 100%;
background-color: #f6f6f6;
border: 1px solid #E5E5E5;
padding-right: 31px;
display: flex;
}
.l2-vid{
background: url('play.png') no-repeat left center !important;
padding-left: inherit;
list-style: none;
margin-left: 0;
}
.l2-vid a{
cursor: pointer;
}
.l2-vid::after{
content: "" !important;
}
#l2-vidlink{
padding-left: inherit;
}
/*---------------End Lesson 2---------------*/
.active::after{
content: "-";
float: left;
padding-right: 15px;
}
a:hover{
text-decoration:underline
}
@media only screen and (max-device-width: 480px) {
}
<html>
<head>
<title>AAON Heating and Cooling Products</title>
<link rel="stylesheet" type="text/css" href="test.css">
<link href='http://fonts.googleapis.com/css?family=Oswald' rel='stylesheet' type='text/css'>
<link rel="icon" href="p2tab.png">
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="accordionscript.js"></script>
</head>
<body>
<div class="content">
<div>Prism2 - Operator Interface</div>
<div style="float:right;font-size: small;"><a href="javascript:void(0)" class="expand">Expand All</a> | <a href="javascript:void(0)" class="collapse">Collapse All</a></div><br>
<div class="l1">Intro</div>
<div class="l1-info">
<ul>
<li class="l1-vid"><a >Video</a></li>
<div id="l1-vidlink">
<iframe class="desktop" width="560" height="315" src="https://www.youtube.com/embed/H7hGxg92Khc" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></div>
<li>Intro - PDF</li>
<li>Prism 2 Technical Guide</li>
</ul>
</div>
<div class="l2">What is Prism2?</div>
<div class="l2-info">
<ul>
<li class="l2-vid"><a >Video</a></li>
<div id="l2-vidlink">
<iframe class="desktop" width="560" height="315" src="https://www.youtube.com/embed/H7hGxg92Khc" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></div>
<li>What is Prism2 - PDF</li>
</ul>
</div>
</div>
</body>
</html>
Solution
-
Do not reinvent the wheel and pick up an existing component framework. For instance, Bootstrap provides an accordion component out of the box. You simply need to drop in Bootstrap’s CSS and JS, then follow the prescribed markup, replacing the user-specific portions like the targets.
-
You might also want to consider using
<summary>
and<details>
elements to do accordions without having to bring in libraries or write down scripts. You can read HTML5Doctor’s analysis on<summary>
and<details>
, its purpose and use cases. -
Your indents need to be consistent. This can be remedied by using a text editor that’s geared towards code editing out of the box (instead of a plain text editor like Notepad). Sublime Text or VS Code should get you started. They allow you to set what your indent character and width are, and will indent a newline accordingly.
-
Avoid inline styles, put all your CSS in a stylesheet, use classes. The only case that inline CSS is allowed is when you have dynamic values for styles (i.e. positioning with
top
andleft
based on some calculation not known ahead of time). -
Avoid using IDs. IDs are limiting in a sense that it can only be assigned to one element. If you have multiple elements that need styling, classes are a better fit. Also, IDs have high specificity, meaning it’s harder to override unless you have a more specific selector – which can be a pain since a more specific selector means putting more into a selector making it unnecessarily long and brittle.
-
Avoid styling element selectors directly and use classes. For instance, styling lists using
ul
andli
as selectors assumes that ALL lists should look that way, but you don’t really want that. Use classes and target specific elements. And while you’re at it, use a naming convention, like BEM.