Mahdi
Mahdi

Reputation: 113

is it possible to focus-within a parent element and not get applied by all child elements but one specific?

Here's the Problem: focus-within applies to all Child Elements inside a Tag Example:

<a class="open" href="#">open menu</a>
    <div class="parent">
    <a class="link1" href="#">link1</a>
    <a class="link2" href="#">link2</a>
    <div class="menu2">...123</div>
    <a class="link3" href="#">link3</a>
    <div class="menu3">...456</div>
    </div>

in this example, I've used a.link2 and a.link3 for opening menu while they're on focus. and I need to set a.link1 for closing the div.parent and I've done that by:

 <style>
  .parent{width:200px;height:100%;position:fixed;left:-30em;background:lightyellow;}
            .open:focus + .parent,.parent:hover{left:0;}/*opening sidebar*/
            .parent:focus-within{left:-20em;}/*closing sidebar*/
            .parent:focus-within + a.link1{left:-20em}/*closing sidebar*/
    </style>

when i click on a.link2 & a.link3 it also close the sidebar,and I only want to apply to a.link1 to be able to close the sidebar!

How can i set a.link1 to close the sidebar and not(a.link2 & a.link3 and ....) with only css, no JavaScript? is there any way?

.parent{width:200px;height:100%;position:fixed;left:-30em;background:lightyellow;}
        .open:focus + .parent,.parent:hover{left:0;}/*opening sidebar*/
        .parent:focus-within{left:-20em;}/*closing sidebar*/
        .parent:focus-within + a.link1{left:-20em}/*closing sidebar*/
 <a class="open" href="#">open menu</a>
    <div class="parent">
    <a class="link1" href="#">link1</a>
    <a class="link2" href="#">link2</a>
    <div class="menu2">...123</div>
    <a class="link3" href="#">link3</a>
    <div class="menu3">...456</div>
    </div>

Upvotes: 1

Views: 3240

Answers (1)

isaacsan 123
isaacsan 123

Reputation: 1158

The short answer is that it isn't possible with the method you're trying to use.

The reason for this is that selectors only go top down. This means that although the parent div can get closed by clicking on one of it's children, this is only made possible because of the focus-within selector. It has nothing to do with the parent's children. If you want element A to affect element B in CSS, element A needs to be either a sibling or just at least a level above element B in order to affect it.

In order to create this sort of sidebar only with CSS, you'd have to use the "checkbox hack". I'll leave a small example here then explain how it works:

* {
    font-family: 'Segoe UI', monospace;
}
#toggler {
    display: none;
}
nav {
    position: fixed;
    top: 0;
    left: -150px;
    width: 200px;
    height: 100vh;
    box-shadow: 1px 2px 3px rgb(30 30 30 / 50%);
    transition: left 0.2s;
}
img {
    width: 30px;
}
label {
    display: block;
    text-align: right;
    padding: 10px;
    cursor: pointer;
}
#toggler:checked + nav {
    left: 0;
}
<input type="checkbox" id="toggler">
<nav>
    <label for="toggler">
        <img src="https://cdn4.iconfinder.com/data/icons/website-library/32/hamburger_List_hamburger_right_menu_website-512.png" alt="">
    </label>
</nav>

Basically, the actual checkbox is outside of the nav. That way, whether it's checked or not can affect the nav, which is its sibling. However, the label for that checkbox is still inside of the nav, which creates the behavior you seem to want. When a label is clicked on, it affects whether its corresponding checkbox is checked or not. This lets us get around the problem of children not being able to affect parents in CSS.


EDIT:

So, I just found another hack using anchor tags and the :target pseudo selector.

Here's another snippet:

nav {
    position: absolute;
    top: 0;
    left: -150px;
    width: 200px;
    height: 100vh;
    box-shadow: 1px 2px 3px rgb(30 30 30 / 50%);
    text-align: right;
    padding: 5px;
    box-sizing: border-box;
    transition: left 0.2s;
}
a {
    display: block;
    margin: 5px 0;
    font-family: 'Segoe UI', monospace;
    color: blue;
}
#open:target ~ nav {
    left: 0;
}
#close:target ~ nav {
    left: -150px;
}
<div id="open"></div>
<div id="close"></div>
<nav>
    <a href="#open">Open</a>
    <a href="#close">Close</a>
</nav>

The way this works is that first of all, we need some elements that will at least be on the same level as our nav, so that they'll have the ability to affect it. Each element has an id that anchor tags can use as a target. When an anchor tag is clicked on, the element with the id that is in the anchor tag's href has its :target pseudo selector triggered. Since the elements targeted in this example are siblings of the nav, they can affect its style when targeted. ~ is just a sibling selector, and it targets any sibling, not only adjacent siblings like + does.

Upvotes: 1

Related Questions