The simplest and most correct way to get the expected result would be to add a javascript (or jQuery) that turns on the li
when your link is clicked with a CSS class, and then you control the visual effect via CSS (in some cases animation via JS is also done, but animations via CSS are hardware-accelerated and have much better visual and processing performance). This is how most frameworks work.
More or less follows the code (with very weak JS).
$(".nav li > span").click(function() {
// confesso que esse código parece pouco otimizado, aceito sugestões
$parent_list_item = $(this).parent("li");
// Remove todas as classes ativas de todos os itens dessa lista, para não ter 2 ativos ao mesmo tempo no mesmo dropdown. Mas ignora o item atual para checarmos depois de precisamos minimizar-lo
$parent_list_item.parent("ul").find(".active").not($parent_list_item).removeClass("active");
// adiciona classe ativa para o <li> (pai) do <a> clicado, se ele não for o item que já está ativo
if (!$parent_list_item.hasClass("active")) {
$parent_list_item.addClass("active");
}else{
// Se for o que já está ativo remove a classe
$parent_list_item.removeClass("active");
}
});
body{
padding:20px;
}
/* apenas para visualização */
.nav{
width:400px;
}
/* reseta as listas em .nav */
.nav, .nav ul{
list-style:none;
margin:0;
padding:0;
}
/* estiliza todos os botões dentro de nav */
.nav a,
.nav span{
display:block;
text-decoration:none;
transition:all .3s ease; /* essa animação é entre a cor de fundo e cor da fonte, sempre muito útil */
}
/* posiciona o item relativo para os subitens (flutuantes) respeitarem sua posição */
.nav li{
position:relative;
}
/* estiliza o primeiro nível */
.nav > li > a,
.nav > li > span{
padding:10px;
background:#eee;
margin-bottom:1px;
color:#333;
}
.nav li > span{
cursor:pointer;
}
.nav li > span:after{
display:inline-block;
content:"+";
font-weight:bold;
font-size:16px;
float:right;
line-height:1em;
}
.nav > li > a:hover,
.nav > li > span:hover{
background:green;
color:white;
}
/* estiliza todos os subitems, ou seja, a lista pode ter vários subdropdowns. Está flutuante pois inseri position:absolute, se você remover o item mostra abaixo;*/
.nav li > ul{
position:absolute; /* comente esta linha para mostrar abaixo*/
top:100%;
z-index:2;
background:#aaa;
max-height:0; /* limita a altura para animarmos (obs este elemento não pode ter padding) */
overflow:hidden;
transition:all 0.5s ease; /* anima os estados do elemento */
/*left: 100%; /* descomente esta linha para mostrar ao lado invés de abaixo */
width:100%; /* deixa o submenu com a largura do pai, depende do caso, ele sobrepõe todos os filhos nesse caso, que não é bom */
margin-left:5px; /* um espaçamento pra ficar visualmente compreensível os níveis */
}
/* 2º nível */
.nav li ul > li > a,
.nav li ul > li > span{
padding:9px;
font-size:0.9em;
border-bottom:1px solid white;
color:#666;
}
.nav li > ul > li > a:hover,
.nav li > ul > li > span:hover{
background:tomato;
color:white;
}
/* 3º nível */
.nav li > ul > li > ul > li > a,
.nav li > ul > li > ul > li > span{
padding:7px;
font-size:0.8em;
border-bottom:1px solid white;
color:#666;
}
.nav li > ul > li > ul > li > a:hover,
.nav li > ul > li > ul > li > span:hover{
background:limegreen;
color:white;
}
/* estiliza o link dentro do item quando está ativo */
.nav li.active > a,
.nav li.active > span{
background:#333;
color:#fff;
}
.nav li.active > span:after{
content:"-";
}
.nav li.active > ul{
max-height:100vh; /* remove a limitação de altura para animar para height:auto.*/
animation:0s 1s delay-overflow forwards; /* pequeno hack para o overflow mudar apenas para o item aberto depois da animação terminada */
}
@keyframes delay-overflow {
to { overflow:visible; }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="nav">
<li><span>Consultores</span>
<ul>
<li><a href="#0">sub - 1</a></li>
<li><a href="#0">sub - 2</a></li>
<li><span>sub - 3 (com subs)</span> <!-- como aqui é um botão simples de ordenação, ele não deve ser um link -->
<ul>
<li><a href="#0">sub sub - 1</a></li>
<li><a href="#0">sub sub - 2</a></li>
<li><a href="#0">sub sub - 3</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#0">Colaboradores</a></li>
<li><a href="#0">Comercial</a></li>
<li><a href="#0">RH</a></li>
</ul>
I find it strange how stackoverflow inserts code right into the page, so I always use alternatives like Codepen, click here to see this solution.
Other remarks about your code:
- Try not to use
ID
s on elements that may be generic / modularized / componentized or repeatable on the page, try treating the ID only for specific JS selections. Ex: the page can have multiple dropdowns, so the component is generic.
I hope I helped (although this JS still bother me rs)
It’s really hard to understand. Can you edit the question and code your CSS? Add HTML as well.
– DaviAragao
Have you tried instead of :Hover using :Focus? I think it works ;-)
– Renato Muller Ventura