Combining CSS selections with parent child and sibling elements

Asked

Viewed 86 times

2

I have the following code:

<ul class="menu">
   <li><label for="menu1">Menu 1</label></li>
   <li><label for="menu2">Menu 2</label></li>
   <li><label for="menu3">Menu 3</label></li>
</ul>

<input type="radio" name="menu" id="menu1">
<div> Conteudo do Menu 1</div>

<input type="radio" name="menu" id="menu2">
<div> Conteudo do Menu 2</div>

<input type="radio" name="menu" id="menu3">
<div> Conteudo do Menu 3</div>

..and the CSS:

UL{
    border: 0;
    margin: -1px;
    padding: 0px;
    background-color: #eee;
    font-weight: bold;
    text-decoration: none;
    font-size: 100%;
    list-style: none;
    line-height: 0.5;
    border-bottom-right-radius: 0px;
    border-bottom-left-radius: 0px;

    border-top-right-radius: 6px;
    border-top-left-radius: 6px;
}

UL:after, UL:before{
    content: '';
    display: table;
    clear: both;
}
UL LI{
    border: 1px solid #cbc7bd;
    list-style: none;
    float: left;
    position: relative;
    top: 1px;
    margin: 0 .2em 1px 0;
    border-bottom: 0 !important;
    padding: 0;
    white-space: nowrap;

    border-top-right-radius: 6px;
    border-top-left-radius: 6px;
}
UL LI label{
    cursor: pointer;
    padding: .5em 1em;
    text-decoration: none;
    float: left;
}
input[type=radio]{
    height: 0;
    width: 0;
    position: absolute;
    opacity: 0;
}
input:checked + div{
    display: block;
}
div{
    display: none;
    border-width: 0;
    padding: 1em 1.4em;
    background: none;
    margin-top: 0;
    border-top: 0;
    border: 1px solid #d9d6c4;
    background-color: white;

    border-bottom-right-radius: 6px;
    border-bottom-left-radius: 6px;
    border-top-right-radius: 0px;
    border-top-left-radius: 0px;
}

Which is nothing more than a menu that shows your respective content with pure CSS. It’s working OK, just like to modify the CSS of the selected LI, to be highlighted that is selected by adding different background color for example.

I know that CSS could have a selector :has or :contains, to make

LI:has(input:checked)

or even a selector "<", (the inverse of " Y > X" which selects element X with parent Y), something like:

 LI < input:checked 

But I know that doesn’t exist in CSS yet. Does anyone have an idea of how it can be done currently ? Preferably without using JS. vlw

  • vc not want via JS, and via PHP?

2 answers

2

Yes, but you need to change your HTML, not only CSS, you have to put the radio buttons before the UL that has the labels inside. So when you click on label with the for for the radio you can reach all that is below, thus reaching the own label clicked and change her color, leaving her "active"

#menu1:checked ~ .menu1,
#menu2:checked ~ .menu2,
#menu3:checked ~ .menu3 {
    display: block;
}

#menu1:checked ~ ul [for="menu1"],
#menu2:checked ~ ul [for="menu2"],
#menu3:checked ~ ul [for="menu3"] {
    background-color: red;
}

Notice that now I no longer use the dial + , I’m gonna osar the ~ in place, and tb need that each tab have a class, see below to better understand.

Image code:

inserir a descrição da imagem aqui

UL {
    border: 0;
    margin: -1px;
    padding: 0px;
    background-color: #eee;
    font-weight: bold;
    text-decoration: none;
    font-size: 100%;
    list-style: none;
    line-height: 0.5;
    border-bottom-right-radius: 0px;
    border-bottom-left-radius: 0px;

    border-top-right-radius: 6px;
    border-top-left-radius: 6px;
}

UL:after,
UL:before {
    content: '';
    display: table;
    clear: both;
}

UL LI {
    border: 1px solid #cbc7bd;
    list-style: none;
    float: left;
    position: relative;
    top: 1px;
    margin: 0 .2em 1px 0;
    border-bottom: 0 !important;
    padding: 0;
    white-space: nowrap;

    border-top-right-radius: 6px;
    border-top-left-radius: 6px;
}

UL LI label {
    cursor: pointer;
    padding: .5em 1em;
    text-decoration: none;
    float: left;
}

input[type=radio] {
    height: 0;
    width: 0;
    position: absolute;
    opacity: 0;
}

#menu1:checked ~ .menu1,
#menu2:checked ~ .menu2,
#menu3:checked ~ .menu3 {
    display: block;
}

#menu1:checked ~ ul [for="menu1"],
#menu2:checked ~ ul [for="menu2"],
#menu3:checked ~ ul [for="menu3"] {
    background-color: red;
}

div {
    display: none;
    border-width: 0;
    padding: 1em 1.4em;
    background: none;
    margin-top: 0;
    border-top: 0;
    border: 1px solid #d9d6c4;
    background-color: white;

    border-bottom-right-radius: 6px;
    border-bottom-left-radius: 6px;
    border-top-right-radius: 0px;
    border-top-left-radius: 0px;
}
<input type="radio" name="menu" id="menu1">
<input type="radio" name="menu" id="menu2">
<input type="radio" name="menu" id="menu3">

<ul class="menu">
    <li><label for="menu1">Menu 1</label></li>
    <li><label for="menu2">Menu 2</label></li>
    <li><label for="menu3">Menu 3</label></li>
</ul>

<div class="menu1"> Conteudo do Menu 1</div>

<div class="menu2"> Conteudo do Menu 2</div>

<div class="menu3"> Conteudo do Menu 3</div>

  • 1

    Excellent response!

  • 1

    @Augustovasques was worth strength my dear In this case as the order of the radio doesn’t matter much, putting him above all brothers and children makes it easy to solve the problem :D

  • 2

    I was bothered by the fact that maybe this answer does not get many up vote, I say this because the reader to be surprised, just as I was, must understand how ingenious the use of this selector #menu1:checked ~ ul [for="menu1"],&#xA;#menu2:checked ~ ul [for="menu2"],&#xA;#menu3:checked ~ ul [for="menu3"] {&#xA; background-color: red;&#xA;} and be aware of how limiting the conditions imposed by the question were.

  • 1

    @Augustovasques is true, the selectors, order of elements etc, are "evil" that we catch with time. The advantage of JS in this case is that when you scale, for example imagine 10 tabs, the CSS code will get huge, bigger than it would be with JS... in complex projects you have to see the best option...

-1

The CSS "Cascading Style Sheets", as the name already says, cascades where the child inherits values from his ancestor. So a relative element cannot have altered properties in relation to its heir.

I believe that even the current versions, it is possible only relative to heir. If you really want to apply this type of change, going against the CSS proposal will have to use javascript. I believe this article can be useful when doing this work with JS: for-what-serve-the-attributes-data-target-e-data-toggle

Or search for variables in CSS, they can be useful as well.

  • From a read on the @hugocsl https://answall.com/questions/404338/combinando-sele%C3%A7%C3%b5es-css-com-elementos-pais-filhos-e-irm%C3%a3os/404926#404926.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.