Reputation: 137
I'm trying to click on a title to display content and change the icon next to the title.
The main idea is that there is a plus sign and that when clicking, the content is visible and the icon changes to a minus sign.
I am working with scss and vanilla js, so far I have this:
var jsaccordion = {
init : function (target) {
var headers = document.querySelectorAll("#" + target + " .accordion-titulo");
if (headers.length > 0) { for (var head of headers) {
head.addEventListener("click", jsaccordion.select);
}}
},
select : function () {
var contents = this.nextElementSibling;
contents.classList.toggle("open");
}
};
window.addEventListener('load', function(){
jsaccordion.init("accordion-definiciones");
});
.accordion-titulo::before {
content: ".";
display: block;
background: url("./../Iconos/Icono\ some-icon");
background-repeat: no-repeat;
background-position: center;
cursor: pointer;
width: 35px;
height: 35px;
color: transparent;
float: right;
}
.accordion-texto {
display: none;
color: #808080;
padding: 15px;
}
.accordion-texto.open {
display: block;
}
.accordion-titulo.open {
background: url("./../Iconos/Icono\ some-different-icon.svg");
background-repeat: no-repeat;
background-position: 98% center;
}
<div id="accordion-definiciones">
<div class="my-3">
<h3 class="accordion-titulo ">¿Lorem ipsum?</h3>
<div class="accordion-texto">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Illo, animi perferendis necessitatibus sint molestiae eius magni! Libero voluptas mollitia laudantium, ad nihil cum quibusdam rerum laboriosam quia ea facere temporibus.</p>
</div>
</div>
</div>
I know it can be easier with Jquery but I want to do it with vanilla js
Upvotes: 2
Views: 739
Reputation: 207501
You can actually do it with just HTML and CSS
.accordion input[type="checkbox"] {
display: none
}
.accordion input[type="checkbox"] + h3 {
cursor: pointer;
}
.accordion input[type="checkbox"] + .accordion-titulo label:after {
content: "\27F0";
}
.accordion input[type="checkbox"]:checked + .accordion-titulo label:after {
content: "\27F1";
}
.accordion input[type="checkbox"] + .accordion-titulo + .accordion-texto {
max-height: 0;
overflow: auto;
transition: max-height .8s;
}
.accordion input[type="checkbox"]:checked + .accordion-titulo + .accordion-texto {
height: auto;
max-height: 200px;
transition: max-height .8s;
}
.accordion-texto {
background-color: #CCC;
}
<div id="accordion-definiciones">
<div class="my-3 accordion">
<input type="checkbox" id="ac1">
<h3 class="accordion-titulo "><label for="ac1">¿Lorem ipsum?</label></h3>
<div class="accordion-texto">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Illo, animi perferendis necessitatibus sint molestiae eius magni! Libero voluptas mollitia laudantium, ad nihil cum quibusdam rerum laboriosam quia ea facere temporibus.</p>
</div>
</div>
</div>
Upvotes: 1
Reputation: 7591
Here is a pure CSS solution, using a hidden checkbox and the sibling selector (~) to toggle the visibility of a neighbor div and the symbol of a before element. I also took the liberty of styling everything slightly differently.
If you want a behavior where you automatically close an already open section, when clicking on a headline, then use radio-buttons with the same name
attribute.
.hidden {
display: none;
}
.accordion-titulo > label {
cursor: pointer;
}
.accordion-titulo > label::before {
content: "+";
display: inline-block;
width: 1rem;
}
input[type="checkbox"]:checked ~ .accordion-titulo > label::before {
content: "-";
}
.accordion-texto {
display: none;
color: #808080;
padding-left: 1rem;
padding-bottom: 1rem;
}
input[type="checkbox"]:checked ~ .accordion-texto {
display: block;
}
<div class="my-3">
<input id="part-1" class="hidden" type="checkbox">
<h3 class="accordion-titulo "><label for="part-1">Part 1</label></h3>
<div class="accordion-texto">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Illo, animi perferendis necessitatibus sint molestiae eius magni! Libero voluptas mollitia laudantium, ad nihil cum quibusdam rerum laboriosam quia ea facere temporibus.</p>
</div>
</div>
<div class="my-3">
<input id="part-2" class="hidden" type="checkbox">
<h3 class="accordion-titulo "><label for="part-2">Part 2</label></h3>
<div class="accordion-texto">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Illo, animi perferendis necessitatibus sint molestiae eius magni! Libero voluptas mollitia laudantium, ad nihil cum quibusdam rerum laboriosam quia ea facere temporibus.</p>
</div>
</div>
Upvotes: 0
Reputation: 6325
From your code, it seems that the icon some-different-icon
should be placed in a :before selector, as the icon some-icon
is being added in a :before.
Also, on the JavaScript side you are setting the class open
to the next sibling element of the .accordion-titulo
(which is the .accordion-texto
). So, your styles for .accordion-titulo.open
will never apply.
Instead, I would set the open
class in the .accordion-titulo
element and show the .accordion-texto
with the CSS sibling selector +
.
Wrapping all that, the code would look like:
var jsaccordion = {
init : function (target) {
var headers = document.querySelectorAll("#" + target + " .accordion-titulo");
if (headers.length > 0) { for (var head of headers) {
head.addEventListener("click", jsaccordion.select);
}}
},
select : function () {
this.classList.toggle("open");
}
};
window.addEventListener('load', function(){
jsaccordion.init("accordion-definiciones");
});
.accordion-titulo::before {
content: " ";
display: block;
background: url("./../Iconos/Icono\ some-icon");
background-repeat: no-repeat;
background-position: center;
cursor: pointer;
width: 35px;
height: 35px;
color: transparent;
float: right;
}
.accordion-texto {
display: none;
color: #808080;
padding: 15px;
}
.accordion-titulo.open + .accordion-texto{
display: block;
}
.accordion-titulo.open::before {
background: url("./../Iconos/Icono\ some-different-icon.svg");
background-repeat: no-repeat;
background-position: 98% center;
}
<div id="accordion-definiciones">
<div class="my-3">
<h3 class="accordion-titulo ">¿Lorem ipsum?</h3>
<div class="accordion-texto">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Illo, animi perferendis necessitatibus sint molestiae eius magni! Libero voluptas mollitia laudantium, ad nihil cum quibusdam rerum laboriosam quia ea facere temporibus.</p>
</div>
</div>
</div>
Upvotes: 0
Reputation: 231
Something like this can do what you want (there are plenty other, probably better, ways to do it, but this does what you described).
var jsaccordion = {
init : function (target) {
var headers = document.querySelectorAll("#" + target + " .accordion-titulo");
if (headers.length > 0) { for (var head of headers) {
head.addEventListener("click", jsaccordion.select);
}}
},
select : function () {
var contents = this.nextElementSibling;
if (this.innerHTML.includes("+")) {
this.innerHTML = this.innerHTML.replace("+", "-");
} else {
this.innerHTML = this.innerHTML.replace("-", "+");
}
contents.classList.toggle("open");
}
};
window.addEventListener('load', function(){
jsaccordion.init("accordion-definiciones");
});
.accordion-titulo::before {
content: ".";
display: block;
background: url("./../Iconos/Icono\ some-icon");
background-repeat: no-repeat;
background-position: center;
cursor: pointer;
width: 35px;
height: 35px;
color: transparent;
float: right;
}
.accordion-texto {
display: none;
color: #808080;
padding: 15px;
}
.accordion-texto.open {
display: block;
}
.accordion-titulo.open {
background: url("./../Iconos/Icono\ some-different-icon.svg");
background-repeat: no-repeat;
background-position: 98% center;
}
<div id="accordion-definiciones">
<div class="my-3">
<h3 class="accordion-titulo ">¿Lorem ipsum? +</h3>
<div class="accordion-texto">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Illo, animi perferendis necessitatibus sint molestiae eius magni! Libero voluptas mollitia laudantium, ad nihil cum quibusdam rerum laboriosam quia ea facere temporibus.</p>
</div>
</div>
</div>
Upvotes: 0