Automatically hide a button once there's no associated element left - javascript

I have a list of several elements, and some controlling buttons that can hide/show these elements. Some buttons have control over just one element, while others have multiple elements.
What does my code do:
Button01 hides/shows ElementX and ElementY,
Button02 hides/shows only ElementY.
Once Button01 is clicked, both of the elements are hidden, and clicking Button02 doesn't change anything until Button01 is clicked again.
What I want to do:
Once Button01 hides ElementX and ElementY, Button02 must also be grayed out automatically because its associated element is gone.
And then, clicking Button02 should bring ElementY back and enable Button01 too since one of the associated elements of Button01 is back.
for (let button of document.querySelectorAll(".filterbutton")) {
button.addEventListener("click", filter);
}
let filters = new Set;
function toggleDisplay(selector, display) {
let elems = document.querySelectorAll(selector);
for (let elem of elems) {
elem.style.display = display;
}
}
function filter() {
let filterSelector = this.dataset.filter;
let show = filters.delete(filterSelector);
this.style.color = show ? "" : "rgb(200,200,200)";
if (!show) {
filters.add(filterSelector); // toggle this filter
} else {
toggleDisplay(filterSelector, "");
}
if (filters.size) {
toggleDisplay([...filters].join(","), "none");
}
}
<div class="filterbutton" data-filter=".filter01">Filter01</div>
<div class="filterbutton" data-filter=".filter02">Filter02</div>
<div class="filter01">ElementX</div>
<div class="filter01 filter02">ElementY</div>

You would need to compare the shown elements with the filters on each button when a button gets clicked. See the solution below
const btns = Array.from( document.getElementsByClassName( 'filterbutton' ) );
const els = Array.from( document.getElementsByClassName( 'element' ) );
document.addEventListener( 'click', function( event ) {
const target = event.target.parentElement;
if ( target.hasAttribute('data-filter') ) {
const filter = target.getAttribute( 'data-filter' ).split(" ");
/* If button is active remove matching elements else show */
!target.classList.contains( 'hide' )
? filter.forEach( el => els[el - 1].classList.add( 'hide' ) )
: filter.forEach( el => els[el - 1].classList.remove( 'hide' ) );
btns.forEach( btn => {
const filter = btn.getAttribute( 'data-filter' ).split(" ");
/* Empty array to push true/false if buttons matching elements are visible */
const matches = [];
filter.forEach( match => matches.push( els[match - 1].classList.contains( 'hide' ) ) );
/* If any matches are visible button is active */
matches.includes( false )
? btn.classList.remove( 'hide' )
: btn.classList.add( 'hide' );
});
}
});
* { box-sizing: border-box } body { font-family: monospace; margin: 0 } hr { margin: 1em 0 }
:root { --transTime: .25s; --transFunction: ease-in-out }
#filters, #elements { display: flex; gap: 1em }
.filterbutton, .element {
--trans: opacity var(--transTime) var(--transFunction);
transition: var(--trans); -o-transition: width var(--trans); -moz-transition: var(--trans); -webkit-transition: var(--trans);
}
.filterbutton {
border: 1px solid currentColor;
border-radius: .375em;
color: black;
font-family: inherit;
padding: .5em 1em;
position: relative;
}
.filterbutton.hide { opacity: .5 }
.filterbutton span::before {
border-radius: .375em;
content: "";
cursor: pointer;
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
z-index: 1;
}
.filterbutton span:first-of-type { display: inline }
.filterbutton span:last-of-type { display: none }
.filterbutton.hide span:first-of-type { display: none }
.filterbutton.hide span:last-of-type { display: inline }
.element {
background: lightgrey;
flex: 1 0 0%;
padding: 1em;
text-align: center;
}
.element.hide { opacity: 0 }
<div id="filters">
<button class="filterbutton" type="button" data-filter="1 2 3 4">
<span>Hide</span><span>Show</span> All
</button>
<button class="filterbutton" type="button" data-filter="1">
<span>Hide</span><span>Show</span> 1
</button>
<button class="filterbutton" type="button" data-filter="2 3">
<span>Hide</span><span>Show</span> 2 & 3
</button>
<button class="filterbutton" type="button" data-filter="4">
<span>Hide</span><span>Show</span> 4
</button>
</div>
<hr>
<div id="elements">
<article class="element">Element 1</article>
<article class="element">Element 2</article>
<article class="element">Element 3</article>
<article class="element">Element 4</article>
</div>

Since you have not given a specific problem that can be expressed by code, the answer can only be given algorithmically:
Аdd class active to the visible elements. after clicking the filter button, remove this class from the filtered elements. at the end of filtering, go through all the buttons and if the result is document.querySelectorAll('.active.filter') empty set - disabled the filter button.

Related

Is there an alternative to foreach in Js?

I have several identical divs and each of them contains a button that is hidden. I want to make button visible when you hover on the parent div. I wrote this code:
const cardElements = document.querySelectorAll('.middle_section__president_section');
const learnButtons = document.querySelectorAll('.president_section__button');
cardElements.forEach((cardElement) => {
cardElement.addEventListener('mouseover', () => {
learnButtons.forEach((learnButton) => {
learnButton.style.height = "50px";
learnButton.style.opacity = "1";
learnButton.style.border = "3px solid rgb(129, 129, 129)";
});
});
cardElement.addEventListener('mouseout', () => {
learnButtons.forEach((learnButton) => {
learnButton.style.height = "0px";
learnButton.style.opacity = "0";
learnButton.style.border = "0px solid rgb(129, 129, 129)";
});
});
})
carElements is parent, learnButtons - child.
but with this code when i hover on one div buttons appears in every similiar div. How can i make button appear only on hovered div?
Use the Event object
cardElement.addEventListener('mouseover', () => {
learnButtons.forEach((learnButton) => {
convert this to
cardElement.addEventListener('mouseover', (e) => {
var learnButton = e.target;
There's no need to use JS for this. As Mister Jojo/traktor pointed out in their comments you can use the CSS :hover pseudo-class instead.
The key CSS line is .box:hover button { visibility: visible;} which means "when you hover over the parent container make its button visible".
.box { width: 50%; display: flex; flex-direction: column; border: 1px solid lightgray; margin: 0.25em; padding: 0.25em;}
button { visibility: hidden; margin: 0.25em 0; border-radius: 5px; background-color: lightgreen; }
.box:hover button { visibility: visible;}
.box:hover, button:hover { cursor: pointer; }
<section class="box">
Some text
<button>Click for a surprise!</button>
</section>
<section class="box">
Some text
<button>Click for a surprise!</button>
</section>
<section class="box">
Some text
<button>Click for a surprise!</button>
</section>
It is bad practice to iterate over all elements and give each an event, as you can add 1 event handler to the parent and when the event happens you can check the affected element by the event parameter in the handler call back
parent.addEVentListener('mouseover', (e) => {
if(e.target.classList.contains('middle_section__president_section')) {
// Do
}
});

How to iterate the div items in HTML, and assign the value to each one?

I consumed an api created, where it will return a list with emails, I created a modal, with a div, where by the amount of emails returned, I want to add a div, and at the same time put the value of the emails in each one of them , the most I got was to put the same email in all of them, but at least I managed to add the amount of divs according to the number of emails returned, follows the code
<div class="modal">
<h2>Lista</h2>
<div id="list">
</div>
</div>
modalList: (json) => {
qS('.screen').style.justifyContent = 'center';
qS('.screen').style.alignItems = 'center';
qS('.rightside').style.display = 'none';
qS('.modal').style.display = 'block';
json.list.forEach((item, index)=>{
let numeroHTML = ''
for(let i = 0; i <= index; i++ ){
numeroHTML += `<div class="result"></div>`;
}
qS('.modal #list').innerHTML = numeroHTML
qSa('.result').forEach((result) => {
result.innerHTML = item
})
});
}
the logic that I'm not able to do is how to put each item in the array, that is, each email in a div only, and thus make a list in this modal
Details are commented in example below
/*
I'll assume the JSON is a typical array of objects and each object having a
property/key "email"
*/
const data=[{email:"tmcgowing0#netlog.com"},{email:"ckelsow1#usa.gov"},{email:"zwrench2#github.io"},{email:"avayne3#biblegateway.com"},{email:"mmarquis4#telegraph.co.uk"},{email:"pbrannigan5#marketwatch.com"},{email:"czannetti6#zimbio.com"},{email:"baspey7#thetimes.co.uk"},{email:"ejaumet8#tripadvisor.com"},{email:"pfellow9#cnbc.com"}];
/**
* Renders a list in HTML from a given array of objects and a key.
* #param {string<CSS>} selector - A CSS selector of the <ul>, <ol>, or <menu>
* #param {array<object>} json - The data to make the list from
* #param {string} key - The property/key to get the value from for the list
*/
const modalList = (selector, json, key) => {
// Reference the list OR <body> (if undefined, null, etc)
const node = document.querySelector(selector) || document.body;
/*
On each iteration through >json< render a htmlString into a <li> and add
the current object's value of >key<
*/
json.forEach(item => node.insertAdjacentHTML('beforeEnd', `<li>${item[key]}</li>`));
};
/*
"click" event handler registered to button.open. When triggered the modal opens
and modalList() is called
*/
document.querySelector('.open').onclick = e => {
document.querySelector('.modal').showModal();
modalList('ul', data, 'email');
};
/* The rest is unrelated to question */
const UI = document.forms.UI;
UI.onclick = modalUI;
UI.onsubmit = funcX;
function modalUI(e) {
const OG = e.target;
if (OG.matches('.close')) {
document.querySelector('.modal').close();
}
};
function funcX(e) {
e.preventDefault();
console.log(e.type + ' event fired');
};
html {
font: 2ch/1.5 'Segoe UI'
}
html,
body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
main {
width: 100%;
height: 100%;
}
dialog {
margin: 10px auto;
min-height: 50%;
width: 50%;
}
header {
display: flex;
justify-content: space-between;
align-items: flex-end;
width: 90%;
padding-bottom: 5px;
border-bottom: 2px ridge grey
}
menu {
width: 90%;
display: flex;
justify-content: flex-end;
align-items: flex-start
}
h3 {
margin: 0 0 -8px 0;
}
.btn {
display: inline-block;
cursor: pointer;
border-radius: 5px;
}
section {
width: 90%
}
ul {
list-style: none;
margin-left: -35px
}
footer {
width: 90%;
border-top: 2px ridge grey;
}
.close {
align-self: flex-start;
}
<main>
<dialog class='modal'>
<form id='UI'>
<header>
<h3>Email List</h3>
<input class='btn close' type='button' value='X'>
</header>
<section>
<ul></ul>
</section>
<footer>
<menu>
<button class='btn confirm'>Confirm</button>
<button class='btn close' type='button'>Cancel</button>
</menu>
</footer>
</form>
</dialog>
<menu>
<button class='btn open'>Open Email List</button>
</menu>
</main>
To create HTML from your array you can use a foreach loop like you're doing.
You should be using the HTML <ul> element with <li>s inside.
Do something like this for each iteration:
const element = document.createElement('li')
element.innerText = item
list.appendChild(element)
const json = {
list: ["one", "two", "three"]
}
const listElement = document.querySelector('#list')
json.list.forEach((item, index) => {
const element = document.createElement('li')
element.classList.add('result')
element.innerText = item
list.appendChild(element)
});
<div class="modal">
<h2>Lista</h2>
<ul id="list">
</ul>
</div>

sidebar toggle background opacity not close

I created a sidebar toggle and also gave background opacity but when I click another area or when closed the sidebar the background opacity didn't close. when I click the button the dropdown-content show and the background-opacity show but when I click again on the button the dropdown content closed but the background opacity does not close. How I did it. Please help me. I gave the code below. If someone can help me it will be very helpful for me. I try so many times but in the end, I can't do it. 😥
function toggleDropDown(id) {
document.querySelectorAll('.dropdown-content').forEach(el => el.id === id ? el.classList.toggle('show') : el.classList.remove("show"));
document.body.style.backgroundColor = "rgba(0,0,0,0.4)";
}
document.addEventListener('click', (e) => {
// cases where we want to close the dropdown
if (e.target.closest(".dropdown") === null) {
document.querySelectorAll('.dropdown-content').forEach(el => el.classList.remove("show"));
}
});
*{margin:0;padding:0;}
.dropdown-content{
position: fixed;
width: 30%;
height:100%;
background-color: rgb(255,0,0);
margin-left: 20%;
top:0;
display:none;
z-index:100;
}
.dropbtn{width:20%}
.show{display:block;}
<div class="dropdown">
<button class="dropbtn" onclick="toggleDropDown('openContent')">open</button>
<div class="dropdown-content" id="openContent">Hello, Div</div>
</div>
<h1>Hello World, Heading 1</h1>
First, I would suggest to create a variable that keeps track of the current state of dropdown – which is either true or false.
Plus, I don’t see the benefit in using document.querySelectorAll and having to loop over every element, when you could just directly get the element by addressing its id (openContent)... unless you would want to reuse the function for other cases?
As you are also listening on a click event on the document, we have to watch out for event bubbling by calling e.stopPropagation. In the case of the button for example, this means that we only fire the event for the button but not for the document. Since the button is a child of the document, it would otherwise detect a click event for both and fire twice.
const dropdownContent = document.getElementById("openContent");
let dropDownVisible = false;
function toggleDropDown(e) {
// we need this to prevent the event bubbling from the dropdown button to the document
e.stopPropagation();
// set the dropDownVisible state to the opposite it has been before
dropDownVisible = !dropDownVisible;
if (dropDownVisible) {
dropdownContent.classList.add("show");
document.body.classList.add("bgcolor");
} else {
dropdownContent.classList.remove("show");
document.body.classList.remove("bgcolor");
}
}
// we need this to prevent the event bubbling from the dropdown to the document
dropdownContent.addEventListener("click", (e) => {
e.stopPropagation();
});
// listen for click events on the document
document.addEventListener("click", (e) => {
// -> if the dropdown is visible, toggle its state
dropDownVisible && toggleDropDown(e);
});
* {
margin: 0;
padding: 0;
}
.dropdown-content {
position: fixed;
width: 30%;
height: 100%;
background-color: rgb(255, 0, 0);
margin-left: 20%;
top: 0;
display: none;
z-index: 100;
}
.dropbtn {
width: 20%;
}
.show {
display: block;
}
.bgcolor {
background-color: rgba(0, 0, 0, 0.4);
}
<body>
<div class="dropdown">
<button class="dropbtn" onclick="toggleDropDown(event)">
open
</button>
<div class="dropdown-content" id="openContent">Hello, Div</div>
</div>
<h1>Hello World, Heading 1</h1>
</body>
You will have to remove also the "body" background.
document.body.style.backgroundColor = "initial";
function toggleDropDown(id) {
document.querySelectorAll('.dropdown-content').forEach(el => el.id === id ? el.classList.toggle('show') : el.classList.remove("show"));
document.body.style.backgroundColor = "rgba(0,0,0,0.4)";
}
document.addEventListener('click', (e) => {
// cases where we want to close the dropdown
if (e.target.closest(".dropdown") === null) {
document.querySelectorAll('.dropdown-content').forEach(el => el.classList.remove("show"));
document.body.style.backgroundColor = "initial";
}
});
*{margin:0;padding:0;}
.dropdown-content{
position: fixed;
width: 30%;
height:100%;
background-color: rgb(255,0,0);
margin-left: 20%;
top:0;
display:none;
z-index:100;
}
.dropbtn{width:20%}
.show{display:block;}
<div class="dropdown">
<button class="dropbtn" onclick="toggleDropDown('openContent')">open</button>
<div class="dropdown-content" id="openContent">Hello, Div</div>
</div>
<h1>Hello World, Heading 1</h1>
Add class to body document.body.classList.add('bgcolor'); and remove after close the dropdown
function toggleDropDown(id) {
document.querySelectorAll('.dropdown-content').forEach(el => el.id === id ? el.classList.toggle('show') : el.classList.remove("show"));
document.body.classList.add('bgcolor');
}
document.addEventListener('click', (e) => {
// cases where we want to close the dropdown
if (e.target.closest(".dropdown") === null) {
document.querySelectorAll('.dropdown-content').forEach(el => el.classList.remove("show"));
document.body.classList.remove('bgcolor');
}
});
*{margin:0;padding:0;}
.dropdown-content{
position: fixed;
width: 30%;
height:100%;
background-color: rgb(255,0,0);
margin-left: 20%;
top:0;
display:none;
z-index:100;
}
.dropbtn{width:20%}
.show{display:block;}
.bgcolor{
background-color:rgba(0,0,0,0.4);
}
<div class="dropdown">
<button class="dropbtn" onclick="toggleDropDown('openContent')">open</button>
<div class="dropdown-content" id="openContent">Hello, Div</div>
</div>
<h1>Hello World, Heading 1</h1>

Target multiple classes in a div and count number of times they have been clicked Vanilla JS

The purpose of this is to be able to track the number of times a button with class testButton or incButton has been clicked and if either has been clicked twice to show a overlay.
There are 2 main issues:
1: I'm not sure how to select 2 different classes of buttons
2: Once there are more than 1 button with the same class name the existing JS code does only works on the first button with the testButton class.
The code I have is:
<style>
#winOverlay {
position: fixed;
z-index: 200;
width: 100%;
height: 100%;
background-color: red;
top: 0;
left: 0;
}
</style>
<div id="winOverlay" style="display:none"></div>
<div id="buttonContainer">
<button class="testButton">1</button>
<button class="incButton">2</button>
<button class="testButton">3</button>
<button class="incButton">4</button>
<button class="testButton">5</button>
</div>
<script>
var count = 0;
var btn = document.getElementById("buttonContainer").querySelector(".testButton");
btn.onclick = function () {
count++;
if (count == 2) {
document.getElementById('winOverlay').style.display = "block";
}
}
</script>
Any help would be greatly appreciated.
You can make use of event Delegation where you add event listener on the common parent container with class buttonContainer and you can check if the button clicked with id only testButton and incButon
1) This code will work if you have to calculate of count of irrespective of which button is clicked.
var count = 0;
var btn = document.getElementById("buttonContainer");
const winOverlay = document.getElementById('winOverlay');
btn.addEventListener("click", e => {
const classes = e.target.classList;
if (classes.contains("testButton") || classes.contains("incButon")) {
count++;
if (count === 2) winOverlay.style.display = "block";
}
})
#winOverlay {
position: fixed;
z-index: 200;
width: 100%;
height: 100%;
background-color: red;
top: 0;
left: 0;
}
<div id="winOverlay" style="display:none"></div>
<div id="buttonContainer">
<button class="testButton">1</button>
<button class="incButon">2</button>
<button class="testButton">3</button>
<button class="incButon">4</button>
<button class="testButton">5</button>
</div>
2) This code will work if you have to calculate the count of specif key on which you clicked and show overlay if it's count is 2
var btn = document.getElementById("buttonContainer");
const winOverlay = document.getElementById("winOverlay");
const dict = {};
btn.addEventListener("click", (e) => {
const classes = e.target.classList;
const addOverlay = () => (winOverlay.style.display = "block");
if (classes.contains("testButton") || classes.contains("incButon")) {
const key = e.target.dataset.key;
dict[key] = (dict[key] || 0) + 1;
if (dict[key] === 2) addOverlay();
}
});
#winOverlay {
position: fixed;
z-index: 200;
width: 100%;
height: 100%;
background-color: red;
top: 0;
left: 0;
}
button {
color: white;
border: none;
padding: 1rem;
cursor: pointer;
}
button.testButton {
background-color: teal;
}
button.incButon {
background-color: orange;
}
<div id="winOverlay" style="display: none;"></div>
<div id="buttonContainer">
<button class="testButton" data-key="testButton">1</button>
<button class="incButon" data-key="incButon">2</button>
<button class="testButton" data-key="testButton">3</button>
<button class="incButon" data-key="incButon">4</button>
<button class="testButton" data-key="testButton">5</button>
</div>
You need to select all buttons with querySelectorAll add listener to all of them.
var count = 0;
const buttons = document.querySelectorAll("#buttonContainer > button");
for (let index = 0; index < buttons.length; index++) {
const e = buttons[index];
e.onclick = function() {
count++;
if (count == 2) {
document.getElementById('winOverlay').style.display = "block";
}
}
}
#winOverlay {
position: fixed;
z-index: 200;
width: 100%;
height: 100%;
background-color: red;
top: 0;
left: 0;
}
<div id="winOverlay" style="display:none"></div>
<div id="buttonContainer">
<button class="testButton">1</button>
<button class="incButon">2</button>
<button class="testButton">3</button>
<button class="incButon">4</button>
<button class="testButton">5</button>
</div>
To select 2 class you should do as in css:
querySelector(class1 class2)
But don't work because you can't use querySelector for two or more classes.
This code say only select class1 or class2 and take the first Element.
Use querySelectorAll() to have all of them
As the others have suggested querySelectorAll provides support for multiple selectors. It will return an array-like nodelist which you can then iterate over.
document.querySelectorAll('testButton', 'incButton');
I'm going to offer an alternative approach using event delegation which allows you to attach one listener to a parent element that captures events as they bubble up the DOM.
This example also uses a closure (basically a function that's returned from another function but that can carry any variables set outside it in the local lexical environment with it when it's returned. This is a useful pattern if you want to avoid global variables. In this case we create an object to hold the totals of the two types of buttons.
// Cache your container and overlay elements
const container = document.querySelector('.buttonContainer');
const overlay = document.querySelector('.overlay');
// Add one listener to the container which calls `handleClick`.
// `handleClick` sets up the object and returns a new function
// (the closure) that carries the object with it.
container.addEventListener('click', handleClick(), false);
function handleClick() {
// An object that holds the button totals
const cases = {
testButton: 0,
incButton: 0
};
// The function that will be added to the listener
// It has the event argument
return function (e) {
// Destructure the nodeName/className from the
// element that was clicked
const { nodeName, className } = e.target;
// Check to see if the element was a button
if (nodeName === 'BUTTON') {
// Increase the value in the object where
// the key matches the className
++cases[className];
console.log(JSON.stringify(cases));
// If that value is 2 show the overlay
if (cases[className] === 2) {
overlay.classList.add('show');
}
}
}
}
.overlay { display: none; margin: 1em; background-color: #acaccc; black: white; padding: 2em; }
.show { display: block; }
button { padding: 0.7em; }
button:hover { cursor: pointer; background-color: #acacac; }
<div class="buttonContainer">
<button class="testButton">1</button>
<button class="incButton">2</button>
<button class="testButton">3</button>
<button class="incButton">4</button>
<button class="testButton">5</button>
</div>
<div class="overlay">Overlay</div>
Additional documentation
Destructuring assignment
nodeName
classList

JavaScript Accordion Menu with querySelectorAll()

I'm attempting to build an accordion menu using querySelectorAll() but unsure what the best method would be to check if the clicked list item's children (.toggleContent and .toggleIcon) belong to it's clicked parent toggle_li[i].
Correct me if I am wrong, but I assume that controlling this within the onclick function will be more flexible than impacting the toggleDataAttr function?
I'm still new to querySelector so any guidance is appreciated.
codepen: http://codepen.io/seejaeger/pen/qdqxGy
// data attribute toggle
var toggleDataAttr = function (toggleElem, opt1, opt2, dataAttr) {
//
// ? belongs to clicked element (parent toggle_li[i])?
//
var toggleElem = document.querySelector(toggleElem);
toggleElem.setAttribute(dataAttr,
toggleElem.getAttribute(dataAttr) === opt1 ? opt2 : opt1);
};
// declare toggle onclick element
var toggle_li = document.querySelectorAll('li');
// iterate query and listen for clicks
for (var i = 0; i < toggle_li.length; i++) {
toggle_li[i].onclick = function() {
//
// ? belongs to clicked element (parent toggle_li[i])?
//
toggleDataAttr('.toggleContent', 'closed', 'open', 'data-state');
toggleDataAttr('.toggleIcon', 'plus', 'minus', 'data-icon');
};
}
Here is what I think you should do:
Update your toggleDataAttr function to receive one more parameter parentElem.
Use this new parentElem for querySelector instead of document inside toggleDataAttr.
And then in your loop, pass this as parameter to be used as parentElem.
Snippet:
var toggleDataAttr = function(parentElem, toggleElem, opt1, opt2, dataAttr) {
var toggleElem = parentElem.querySelector(toggleElem);
toggleElem.setAttribute(dataAttr, toggleElem.getAttribute(dataAttr) === opt1 ? opt2 : opt1);
};
var toggle_li = document.querySelectorAll('li');
for (var i = 0; i < toggle_li.length; i++) {
toggle_li[i].onclick = function() {
toggleDataAttr(this, '.toggleContent', 'closed', 'open', 'data-state');
toggleDataAttr(this, '.toggleIcon', 'plus', 'minus', 'data-icon');
};
}
body {
background: #034;
opacity: 0.9;
font-family: sans-serif;
font-size: 24px;
font-weight: 300;
letter-spacing: 2px;
}
ul {
list-style: none;
padding: 0 24px;
width: 30%;
overflow: hidden;
color: #333;
}
li {
background: #eee;
padding: 0px;
border-bottom: 2px solid #aaa;
}
i {
font-style: normal;
}
.li-label {
padding: 18px;
}
.toggleContent {
padding: 18px 14px;
border-top: 2px solid #bac;
background: #334;
color: #eee;
}
.toggleContent[data-state=closed] {
display: none;
}
.toggleContent[data-state=open] {
display: block;
}
.toggleIcon[data-icon=plus]:after {
content: '+';
float: right;
}
.toggleIcon[data-icon=minus]:after {
content: '-';
float: right;
}
<ul>
<li>
<div class="li-label">
list item one <i class="toggleIcon" data-icon="plus"></i>
</div>
<div class="toggleContent" data-state="closed">toggle content one</div>
</li>
<li>
<div class="li-label">
list item two <i class="toggleIcon" data-icon="plus"></i>
</div>
<div class="toggleContent" data-state="closed">toggle content two</div>
</li>
<li>
<div class="li-label">
list item three <i class="toggleIcon" data-icon="plus"></i>
</div>
<div class="toggleContent" data-state="closed">toggle content three</div>
</li>
</ul>
Hope it helps.

Categories

Resources