I am trying to make a drop down menu in which there are selections consisting of a p
tag in which there is a span
tag. The problem is that when I select one of the options in the drop down menu it merges the text from the p
and span
tag together, and they should have different styles but they turn out to be the same.
const dropdowns = document.querySelectorAll('.start__dropdown');
dropdowns.forEach(dropdown => {
const select = dropdown.querySelector('.select');
const caret = dropdown.querySelector('.caret');
const menu = dropdown.querySelector('.menu');
const options = dropdown.querySelectorAll('.menu li');
const selected = dropdown.querySelector('.selected');
select.addEventListener('click', () => {
select.classList.toggle('select-clicked');
caret.classList.toggle('caret-rotate');
menu.classList.toggle('menu-open')
});
options.forEach(option => {
option.addEventListener('click', () => {
selected.innerHTML = option.innerText;
select.classList.remove('select-clicked');
caret.classList.remove('caret-rotate');
menu.classList.remove('menu-open');
options.forEach(opt => {
opt.classList.remove('active');
});
option.classList.add('active');
});
});
});
.start__dropdown {
width: 360px;
position: relative;
height: 68px;
border-bottom: 1px solid $text-black;
}
.select {
background-color: $white;
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;
padding: 16px;
height: 100%;
transition: background 300ms;
}
.selected {
font-size: 16px;
line-height: 28px;
font-weight: bold;
color: $accent-black;
}
.selected span {
color: $text-black;
margin-left: 8px;
}
.caret {
transition: 300ms;
}
.caret-rotate {
transform: rotate(180deg);
}
.menu {
z-index: 1;
list-style: none;
padding: 0px 30px;
background: $white;
border: 1px solid $text-black;
border-radius: 8px;
position: absolute;
top: 76px;
left: 50%;
transform: translateX(-50%);
width: 367px;
opacity: 0;
display: none;
transition: 200ms;
}
.menu li {
font-size: 16px;
line-height: 28px;
font-weight: bold;
color: $accent-black;
cursor: pointer;
width: 100%;
height: 68px;
border-bottom: 1px solid $text-black;
padding: 20px 16px;
}
.menu li:last-child {
border: none;
}
.menu li span {
color: $text-black;
margin-left: 8px;
}
.menu-open {
display: block;
opacity: 1;
}
<div class="start__dropdown">
<div class="select">
<p class="selected">Basic Pack <span>Free</span></p>
<div class="caret"><img src="icons/sign-up/icon-arrow-down.svg" alt="caret"></div>
</div>
<ul class="menu">
<li class="active">Basic Pack <span>Free</span></li>
<li>Pro Pack <span>$9.99</span></li>
<li>Ultimate Pack <span>$19.99</span></li>
</ul>
</div>
I tried using option.innerText
to get the text content of the selected option.
I used option.querySelector('span').innerText
to get the <span>
content from the selected option.
Then I updated the content of the .selected
element with .innerHTML
, inserting the text of the option and its price into the <span>
, but the price was duplicated and it looked like this: <p class="selected">Ultimate Pack $19.99 <span>$9.99</span></p>
options.forEach(option => {
option.addEventListener('click', () => {
// Get the text content and the span content of the selected option
const optionText = option.innerText;
const optionPrice = option.querySelector('span').innerText;
// Update the selected item text including the span
selected.innerHTML = `${optionText} <span>${optionPrice}</span>`;
// Close the dropdown and remove classes
select.classList.remove('select-clicked');
caret.classList.remove('caret-rotate');
menu.classList.remove('menu-open');
// Remove 'active' class from all options
options.forEach(opt => {
opt.classList.remove('active');
});
// Add 'active' class to the selected option
option.classList.add('active');
});
});
2
Answers
The issue is because you’re retrieving the
innerText
of the selected option, so thespan
is lost. Change this toinnerHTML
:Here’s a full working example, but note that I amended the CSS to specifically change the color of the selected
span
to red to highlight the effect:You have to use innerHTML instead of innerText. Actually innerHTML consider HTML tags as well as their content.
So, in option section you should insert below code.
below picture, illustrate different method to get content of a HTML element
method for accessing the content of HTML element