是否有可能将焦点放在父元素内而不被所有子元素应用,但只有一个特定的子元素?

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

问题来了: focus-within 适用于标签内的所有子元素 示例:

<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>

在此示例中,我使用 a.link2 和 a.link3 在它们处于焦点时打开菜单。 我需要设置 a.link1 来关闭 div.parent 我通过以下方式做到了:

 <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>

当我点击 a.link2 和 a.link3 时它也关闭了侧边栏,我只想申请 a.link1 才能关闭侧边栏!

如何设置 a.link1 关闭侧边栏而不是(a.link2 & a.link3 和 ....)只有 css,没有 JavaScript? 有什么办法吗?

.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>

简短的回答是,您尝试使用的方法是不可能的。

原因是选择器只能自上而下。这意味着虽然 parent div 可以通过单击其中一个 children 来关闭,但这只是因为 focus-within 选择器才成为可能。它与 parent 的 children 无关。如果您希望元素 A 影响 CSS 中的元素 B,元素 A 需要是兄弟元素或至少比元素 B 高一级才能影响它。

为了仅使用 CSS 创建这种侧边栏,您必须使用“复选框 hack”。我会在这里留下一个小例子然后解释它是如何工作的:

* {
    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>

基本上,实际的复选框在导航之外。这样,无论它是否被选中都会影响导航,它是它的兄弟。但是,该复选框的标签仍在导航内,这会创建您似乎想要的行为。单击标签时,它会影响其对应的复选框是否被选中。这让我们解决了 children 无法影响 CSS.

中的 parent 的问题

编辑:

所以,我刚刚发现了另一个使用锚标记和 :target 伪选择器的技巧。

这是另一个片段:

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>

它的工作方式是,首先,我们需要一些至少与我们的 nav 处于同一级别的元素,以便它们能够影响它。每个元素都有一个 id,锚标签可以将其用作目标。单击锚标记时,锚标记 href 中具有 id 的元素会触发其 :target 伪选择器。由于此示例中的目标元素是 nav 的兄弟元素,因此它们在目标时会影响其样式。 ~ 只是一个兄弟选择器,它针对任何兄弟,而不仅仅是像 + 那样的相邻兄弟。