I want to add an active class to every first element of the submenu (not to all the li's, only the first one from a bunch of li's with same first letter). and add the labels as A, B, C ----- i am achieving this with the css, but the problem is that it keeps adding labels to all, as i want the label to only first element. for example Brittle, britiana, bronze - it will add active class to first B only and same with the others.
how would i go about this?
.groupmenu-drop {
max-width: 900px;
margin: auto;
column-count: 4;
counter-reset: alphabeticList;
}
@media (max-width: 767px) {
.groupmenu-drop {
column-count: 1;
margin-left: 40px;
}
}
@media (min-width: 768px) and (max-width: 1024px) {
.groupmenu-drop {
column-count: 2;
margin-left: 50px;
}
}
.groupmenu-drop > .level1 {
position: relative;
padding: 0 0 14px !important;
counter-increment: alphabeticList;
}
.groupmenu-drop > .level1 {
padding-bottom: 5px;
}
.groupmenu-drop > .level1 a {
font: 600 14px/30px 'Open Sans', sans-serif;
letter-spacing: 0px;
color: #166665;
}
.groupmenu-drop .level1:before {
content: counter(alphabeticList, upper-alpha);
position: absolute;
top: 3px;
left: -40px;
border: 2px solid #166665;
text-align: center;
border-radius: 7px;
font: bold 21px/34px 'Open Sans', sans-serif;
letter-spacing: 0px;
color: #095352;
width: 27px;
height: 27px;
line-height: 23px;
}
.groupmenu-drop .level1:first-child:before {
background-color: #166665;
color: #fef6eb;
}
<ul >
<li >
<a
href="/brands/angelcare.html"
><span>Angelcare</span></a
>
</li>
<li >
<a
href="/brands/baby-art.html"
><span>Baby Art</span></a
>
</li>
<li >
<a
href="/brands/barbie.html"
><span>Barbie</span></a
>
</li>
<li >
<a
href="/brands/bibado.html"
><span>Bibado</span></a
>
</li>
<li >
<a
href="/brands/boon.html"
><span>Boon</span></a
>
</li>
<li >
<a
href="/brands/braun.html"
><span>Braun</span></a
>
</li>
<li >
<a
href="/brands/diono.html"
><span>Diono</span></a
>
</li>
<li >
<a
href="/brands/disney.html"
><span>Disney</span></a
>
</li>
<li >
<a
href="/brands/dorel.html"
><span>Dorel</span></a
>
</li>
<li >
<a
href="/brands/dr-brown-s.html"
><span>Dr Brown's</span></a
>
</li>
<li >
<a
href="/brands/dreambaby.html"
><span>Dreambaby</span></a
>
</li>
<li >
<a
href="/brands/dreamgenii.html"
><span>Dreamgenii</span></a
>
</li>
<li >
<a
href="/brands/dumbo.html"
><span>Dumbo</span></a
>
</li>
<li >
<a
href="/brands/earth-friendly-baby.html"
><span>Earth Friendly Baby</span></a
>
</li>
<li >
<a
href="/brands/east-coast.html"
><span>East Coast</span></a
>
</li>
<li >
<a
href="/brands/fisher-price.html"
><span>Fisher-Price</span></a
>
</li>
<li >
<a
href="/brands/fisher-price-little-people.html"
><span>Fisher-Price Little People</span></a
>
</li>
<li >
<a
href="/brands/flair.html"
><span>Flair</span></a
>
</li>
<li >
<a
href="/brands/gift-wrap-accessories.html"
><span>Gift Wrap Accessories</span></a
>
</li>
<li >
<a
href="/brands/halilit.html"
><span>Halilit</span></a
>
</li>
<li >
<a
href="/brands/hey-clay.html"
><span>Hey Clay</span></a
>
</li>
<li >
<a
href="/brands/hot-wheels.html"
><span>Hot Wheels</span></a
>
</li>
<li >
<a
href="/brands/infantino.html"
><span>Infantino</span></a
>
</li>
<li >
<a
href="/brands/janod.html"
><span>Janod</span></a
>
</li>
<li >
<a
href="/brands/kaloo.html"
><span>Kaloo</span></a
>
</li>
<li >
<a
href="/brands/keel-toys.html"
><span>Keel Toys</span></a
>
</li>
<li >
<a
href="/brands/lalaboom.html"
><span>Lalaboom</span></a
>
</li>
<li >
<a
href="/brands/lamaze.html"
><span>Lamaze</span></a
>
</li>
<li >
<a
href="/brands/lansinoh.html"
><span>Lansinoh</span></a
>
</li>
<li >
<a
href="/brands/leap-frog.html"
><span>Leap Frog</span></a
>
</li>
<li >
<a
href="/brands/lindam.html"
><span>Lindam</span></a
>
</li>
<li >
<a
href="/brands/little-bird-told-me.html"
><span>Little Bird Told Me</span></a
>
</li>
<li >
<a href="/brands/mam.html"
><span>MAM</span></a
>
</li>
<li >
<a
href="/brands/mattel.html"
><span>Mattel</span></a
>
</li>
<li >
<a
href="/brands/medela.html"
><span>Medela</span></a
>
</li>
<li >
<a
href="/brands/mega-bloks.html"
><span>Mega Bloks</span></a
>
</li>
<li >
<a
href="/brands/milton.html"
><span>Milton</span></a
>
</li>
<li >
<a
href="/brands/munchkin.html"
><span>Munchkin</span></a
>
</li>
<li >
<a
href="/brands/my-garden-baby.html"
><span>My Garden Baby</span></a
>
</li>
<li >
<a
href="/brands/nuby.html"
><span>Nuby</span></a
>
</li>
<li >
<a href="/brands/nuk.html"
><span>NUK</span></a
>
</li>
<li >
<a
href="/brands/philips-avent.html"
><span>Philips Avent</span></a
>
</li>
<li >
<a
href="/brands/plasticine.html"
><span>Plasticine</span></a
>
</li>
<li >
<a
href="/brands/playmobil.html"
><span>Playmobil</span></a
>
</li>
<li >
<a
href="/brands/ragtales.html"
><span>Ragtales</span></a
>
</li>
<li >
<a
href="/brands/safety-first.html"
><span>Safety First</span></a
>
</li>
<li >
<a
href="/brands/schleich.html"
><span>Schleich</span></a
>
</li>
<li >
<a
href="/brands/summer-infant.html"
><span>Summer Infant</span></a
>
</li>
<li >
<a
href="/brands/swaddleme.html"
><span>SwaddleMe</span></a
>
</li>
<li >
<a
href="/brands/taf-toys.html"
><span>Taf Toys</span></a
>
</li>
<li >
<a
href="/brands/thomas-and-friends.html"
><span>Thomas and Friends</span></a
>
</li>
<li >
<a
href="/brands/tiny-love.html"
><span>Tiny Love</span></a
>
</li>
<li >
<a
href="/brands/tommee-tippee.html"
><span>Tommee Tippee</span></a
>
</li>
<li >
<a
href="/brands/tomy.html"
><span>Tomy</span></a
>
</li>
<li >
<a
href="/brands/vicks.html"
><span>Vicks</span></a
>
</li>
<li >
<a
href="/brands/vital-baby.html"
><span>Vital Baby</span></a
>
</li>
<li >
<a
href="/brands/vtech.html"
><span>vTech</span></a
>
</li>
<li >
<a
href="/brands/we-made-me.html"
><span>We Made Me</span></a
>
</li>
<li >
<a
href="/brands/widdop-bingham.html"
><span>Widdop Bingham</span></a
>
</li>
<li >
<a
href="/brands/winnie-the-pooh.html"
><span>Winnie The Pooh</span></a
>
</li>
</ul>
Output i am getting: https://paste.pics/be37c962a84545356f416db149368a92
i want to achieve like the screen shot below: https://paste.pics/ff36dd98eb6fcf126004b581ac466f93
CodePudding user response:
The approach is straightforward.
One queries a node list of all of a navigation/link-list's direct children ...
document.querySelectorAll('.groupmenu-drop > li')
.Following up one creates an
Array.from
this node list andmaps
s it into an array of mutated list-item elements which each gets assigned its text-content's first letter-character as value of an owndata-first-char
-attribute.Then one
reduce
s all items into an array of list-item elements which each start with a different letter than their directly preceding list-item.Finally
forEach
collected new first-character list-item one adds a related class-name likenew-first-char
.In the same time one would slightly change some selector rules
The
::before
pseudo-element rendering would be covered by a changed rule like ....groupmenu-drop .level1.new-first-char::before { content: attr(data-first-char); }
... which targets every list-item that features a
new-first-char
class-name , and where the latter's content gets rendered by the value of this very element'sdata-first-char
attribute.The active/selected state of such pseudo-elements then just needs to be targeted by ...
.groupmenu-drop .level1.new-first-char.selected::before { background-color: #166665; color: #fef6eb; }
One has to at least touch the list elements where the pseudo-element rendering takes place because one can not rely anymore on the OP's original content
rendering via the counter
css-function. This is due to the OP's design of a single flat/non-nested list which by the OP's original counter-functionality forces the continuous alphabetical pseudo-element enumeration for each list item.
Therefore it is best to target the pseudo-element rendering by just a class-name like new-first-char
where the pseudo-element's content gets rendered from this very element's data-first-char
attribute-value.
function init() {
const newFirstCharacterItems = Array
.from(
document
.querySelectorAll('.groupmenu-drop > li')
)
.map(elmNode => {
const textContent = elmNode
.querySelector('a > span')
?.textContent ?? '';
let char = textContent
.trim()
// https://www.regular-expressions.info/unicode.html#category
.match(/\p{L}/u) // first letter character.
?.[0] ?? '';
char = char
.toUpperCase();
elmNode
.dataset
.firstChar = char;
return elmNode;
})
.reduce(({ currentCharacter = '', result }, elmNode) => {
const char = elmNode
.dataset
.firstChar;
if (char !== '' && char !== currentCharacter) {
currentCharacter = char;
result
.push(elmNode);
}
return { currentCharacter, result };
}, { result: [] }).result;
newFirstCharacterItems
.forEach(elmNode =>
elmNode
.classList
.add('new-first-char')
);
}
init();
body { margin: 0; zoom: .7; }
.groupmenu-drop {
max-width: 900px;
margin: auto;
column-count: 4;
counter-reset: alphabeticList;
/* additional fix */
list-style: none;
}
@media (max-width: 767px) {
.groupmenu-drop {
column-count: 1;
margin-left: 40px;
}
}
@media (min-width: 768px) and (max-width: 1024px) {
.groupmenu-drop {
column-count: 2;
margin-left: 50px;
}
}
.groupmenu-drop > .level1 {
position: relative;
padding: 0 0 14px !important;
counter-increment: alphabeticList;
}
.groupmenu-drop > .level1 {
padding-bottom: 5px;
}
.groupmenu-drop > .level1 a {
font: 600 14px/30px 'Open Sans', sans-serif;
letter-spacing: 0px;
color: #166665;
}
/* slightly changed selector */
.groupmenu-drop .level1.new-first-char::before {
/*content: counter(alphabeticList, upper-alpha);*/
/* changed content rendering */
content: attr(data-first-char);
position: absolute;
top: 3px;
left: -40px;
border: 2px solid #166665;
text-align: center;
border-radius: 7px;
font: bold 21px/34px 'Open Sans', sans-serif;
letter-spacing: 0px;
color: #095352;
width: 27px;
height: 27px;
line-height: 23px;
}
/* slightly changed selector */
.groupmenu-drop .level1.new-first-char.selected::before {
background-color: #166665;
color: #fef6eb;
}
<ul >
<li >
<a
href="/brands/angelcare.html"
><span>Angelcare</span></a
>
</li>
<li >
<a
href="/brands/baby-art.html"
><span>Baby Art</span></a
>
</li>
<li >
<a
href="/brands/barbie.html"
><span>Barbie</span></a
>
</li>
<li >
<a
href="/brands/bibado.html"
><span>Bibado</span></a
>
</li>
<li >
<a
href="/brands/boon.html"
><span>Boon</span></a
>
</li>
<li >
<a
href="/brands/braun.html"
><span>Braun</span></a
>
</li>
<li >
<a
href="/brands/diono.html"
><span>Diono</span></a
>
</li>
<li >
<a
href="/brands/disney.html"
><span>Disney</span></a
>
</li>
<li >
<a
href="/brands/dorel.html"
><span>Dorel</span></a
>
</li>
<li >
<a
href="/brands/dr-brown-s.html"
><span>Dr Brown's</span></a
>
</li>
<li >
<a
href="/brands/dreambaby.html"
><span>Dreambaby</span></a
>
</li>
<li >
<a
href="/brands/dreamgenii.html"
><span>Dreamgenii</span></a
>
</li>
<li >
<a
href="/brands/dumbo.html"
><span>Dumbo</span></a
>
</li>
<li >
<a
href="/brands/earth-friendly-baby.html"
><span>Earth Friendly Baby</span></a
>
</li>
<li >
<a
href="/brands/east-coast.html"
><span>East Coast</span></a
>
</li>
<li >
<a
href="/brands/fisher-price.html"
><span>Fisher-Price</span></a
>
</li>
<li >
<a
href="/brands/fisher-price-little-people.html"
><span>Fisher-Price Little People</span></a
>
</li>
<li >
<a
href="/brands/flair.html"
><span>Flair</span></a
>
</li>
<li >
<a
href="/brands/gift-wrap-accessories.html"
><span>Gift Wrap Accessories</span></a
>
</li>
<li >
<a
href="/brands/halilit.html"
><span>Halilit</span></a
>
</li>
<li >
<a
href="/brands/hey-clay.html"
><span>Hey Clay</span></a
>
</li>
<li >
<a
href="/brands/hot-wheels.html"
><span>Hot Wheels</span></a
>
</li>
<li >
<a
href="/brands/infantino.html"
><span>Infantino</span></a
>
</li>
<li >
<a
href="/brands/janod.html"
><span>Janod</span></a
>
</li>
<li >
<a
href="/brands/kaloo.html"
><span>Kaloo</span></a
>
</li>
<li >
<a
href="/brands/keel-toys.html"
><span>Keel Toys</span></a
>
</li>
<li >
<a
href="/brands/lalaboom.html"
><span>Lalaboom</span></a
>
</li>
<li >
<a
href="/brands/lamaze.html"
><span>Lamaze</span></a
>
</li>
<li >
<a
href="/brands/lansinoh.html"
><span>Lansinoh</span></a
>
</li>
<li >
<a
href="/brands/leap-frog.html"
><span>Leap Frog</span></a
>
</li>
<li >
<a
href="/brands/lindam.html"
><span>Lindam</span></a
>
</li>
<li >
<a
href="/brands/little-bird-told-me.html"
><span>Little Bird Told Me</span></a
>
</li>
<li >
<a href="/brands/mam.html"
><span>MAM</span></a
>
</li>
<li >
<a
href="/brands/mattel.html"
><span>Mattel</span></a
>
</li>
<li >
<a
href="/brands/medela.html"
><span>Medela</span></a
>
</li>
<li >
<a
href="/brands/mega-bloks.html"
><span>Mega Bloks</span></a
>
</li>
<li >
<a
href="/brands/milton.html"
><span>Milton</span></a
>
</li>
<li >
<a
href="/brands/munchkin.html"
><span>Munchkin</span></a
>
</li>
<li >
<a
href="/brands/my-garden-baby.html"
><span>My Garden Baby</span></a
>
</li>
<li >
<a
href="/brands/nuby.html"
><span>Nuby</span></a
>
</li>
<li >
<a href="/brands/nuk.html"
><span>NUK</span></a
>
</li>
<li >
<a
href="/brands/philips-avent.html"
><span>Philips Avent</span></a
>
</li>
<li >
<a
href="/brands/plasticine.html"
><span>Plasticine</span></a
>
</li>
<li >
<a
href="/brands/playmobil.html"
><span>Playmobil</span></a
>
</li>
<li >
<a
href="/brands/ragtales.html"
><span>Ragtales</span></a
>
</li>
<li >
<a
href="/brands/safety-first.html"
><span>Safety First</span></a
>
</li>
<li >
<a
href="/brands/schleich.html"
><span>Schleich</span></a
>
</li>
<li >
<a
href="/brands/summer-infant.html"
><span>Summer Infant</span></a
>
</li>
<li >
<a
href="/brands/swaddleme.html"
><span>SwaddleMe</span></a
>
</li>
<li >
<a
href="/brands/taf-toys.html"
><span>Taf Toys</span></a
>
</li>
<li >
<a
href="/brands/thomas-and-friends.html"
><span>Thomas and Friends</span></a
>
</li>
<li >
<a
href="/brands/tiny-love.html"
><span>Tiny Love</span></a
>
</li>
<li >
<a
href="/brands/tommee-tippee.html"
><span>Tommee Tippee</span></a
>
</li>
<li >
<a
href="/brands/tomy.html"
><span>Tomy</span></a
>
</li>
<li >
<a
href="/brands/vicks.html"
><span>Vicks</span></a
>
</li>
<li >
<a
href="/brands/vital-baby.html"
><span>Vital Baby</span></a
>
</li>
<li >
<a
href="/brands/vtech.html"
><span>vTech</span></a
>
</li>
<li >
<a
href="/brands/we-made-me.html"
><span>We Made Me</span></a
>
</li>
<li >
<a
href="/brands/widdop-bingham.html"
><span>Widdop Bingham</span></a
>
</li>
<li >
<a
href="/brands/winnie-the-pooh.html"
><span>Winnie The Pooh</span></a
>
</li>
</ul>
CodePudding user response:
Suppose the HTML list is in the alphabet order. I will retrieve the list using the query selector method first. Then loop and compare the text inside, if the characters are different then add an active
class to the element.
<div >
<div >
<div >
<a href="#"><span>Albama</span></a>
</div>
<div >
<a href="#"><span>Brittle</span></a>
</div>
<div >
<a href="#"><span>Beat</span></a>
</div>
</div>
</div>
<script>
let elements = document.querySelectorAll('.mainbrain-item > .menu-link > span');
let firstLeter = '';
for (const element of elements) {
if(firstLeter !== element.text[0].toLowerCase()){
// select the parent element which is the div with mainbraind-item class
element.parentElement.parentElement.classList.add('active');
firstLeter = element.text[0].toLowerCase();
}
}
</script>
Updated based on the structure OP provided. I added the .active selector in the css code
<style>
/* ..... */
.groupmenu-drop .level1.active:before {
content: counter(alphabeticList, upper-alpha);
position: absolute;
top: 3px;
left: -40px;
border: 2px solid #166665;
text-align: center;
border-radius: 7px;
font: bold 21px/34px 'Open Sans', sans-serif;
letter-spacing: 0px;
color: #095352;
width: 27px;
height: 27px;
line-height: 23px;
}
/* ... */
</style>
<ul >
<li >
<a href="/brands/angelcare.html"><span>Angelcare</span></a>
</li>
<li >
<a href="/brands/baby-art.html"><span>Baby Art</span></a>
</li>
<li >
<a href="/brands/barbie.html"><span>Barbie</span></a>
</li>
</ul>
<script>
document.addEventListener("DOMContentLoaded", function () {
// code...
let elements = document.querySelectorAll('.groupmenu-drop > .item > .menu-link > span');
let firstLeter = '';
for (const element of elements) {
if (firstLeter !== element.textContent[0].toLowerCase()) {
let level1El = element.parentElement.parentElement;
level1El.classList.add('active');
firstLeter = element.textContent[0].toLowerCase();
}
}
});
</script>