使用 focus-within 显示带有 CSS 的嵌套列表

Display nested lists with CSS using focus-within

提问人:Dan 提问时间:8/6/2021 最后编辑:TylerHDan 更新时间:5/31/2022 访问量:534

问:

我正在寻找尝试创建一个 HTML 列表,其中嵌套元素仅在使用 CSS 的伪类聚焦时显示。ulfocus-within

这个想法是,仅使用键盘制表符(暂时忽略鼠标交互),您应该能够将列表项从一个焦点聚焦到下一个列表项,并且当您专注于按钮元素时,它会显示下一级列表项。这部分工作正常。但是,当您离开按钮元素时,它应该保持下一个元素可见,因为焦点应该放在嵌套中的第一个元素上,因此嵌套元素应确定为聚焦在其中。ulaulul

我有它,这样当我在 s 上设置背景颜色时,这就可以作为演示。自然状态是白色背景,但“开放”状态由红色背景表示。这工作正常:ol

.menu ul ul {
                background: #fff;
            }
            .menu button:focus + ul,
            .menu ul ul:focus-within {
                background: #f00;
            }
<nav class="menu">
            <ul>
                <li>
                    <a href="#">Level 1</a>
                </li>
                <li class="has-children">
                    <a href="#">Level 1</a>
                    <button>Show sub-menu for ‘Level 1’</button>
                    <ul>
                        <li class="has-children">
                            <a href="#">Level 2</a>
                            <button>Show sub-menu for ‘Level 2’</button>
                            <ul>
                                <li class="has-children">
                                    <a href="#">Level 3</a>
                                    <button>Show sub-menu for ‘Level 3’</button>
                                    <ul>
                                        <li>
                                            <a href="#">Level 4</a>
                                        </li>
                                        <li>
                                            <a href="#">Level 4</a>
                                        </li>
                                    </ul>
                                </li>
                            </ul>
                        </li>
                        <li>
                            <a href="#">Level 2</a>
                        </li>
                    </ul>
                </li>
                <li>
                    <a href="#">Level 1</a>
                </li>
                <li>
                    <a href="#">Level 1</a>
                </li>
                <li class="has-children">
                    <a href="#">Level 1</a>
                    <button>Show sub-menu for ‘Level 1’</button>
                    <ul>
                        <li class="has-children">
                            <a href="#">Level 2</a>
                            <button>Show sub-menu for ‘Level 2’</button>
                            <ul>
                                <li class="has-children">
                                    <a href="#">Level 3</a>
                                    <button>Show sub-menu for ‘Level 3’</button>
                                    <ul>
                                        <li>
                                            <a href="#">Level 4</a>
                                        </li>
                                        <li>
                                            <a href="#">Level 4</a>
                                        </li>
                                    </ul>
                                </li>
                            </ul>
                        </li>
                        <li>
                            <a href="#">Level 2</a>
                        </li>
                    </ul>
                </li>
            </ul>
        </nav>

因此,当嵌套列表变为红色时,即是可见的,否则它们不可见。

但是,当我将背景颜色替换为并且它不起作用时:display: blockdisplay: none

.menu ul ul {
                display: none;
            }
            .menu button:focus + ul,
            .menu ul ul:focus-within {
                display: block;
            }
<nav class="menu">
            <ul>
                <li>
                    <a href="#">Level 1</a>
                </li>
                <li class="has-children">
                    <a href="#">Level 1</a>
                    <button>Show sub-menu for ‘Level 1’</button>
                    <ul>
                        <li class="has-children">
                            <a href="#">Level 2</a>
                            <button>Show sub-menu for ‘Level 2’</button>
                            <ul>
                                <li class="has-children">
                                    <a href="#">Level 3</a>
                                    <button>Show sub-menu for ‘Level 3’</button>
                                    <ul>
                                        <li>
                                            <a href="#">Level 4</a>
                                        </li>
                                        <li>
                                            <a href="#">Level 4</a>
                                        </li>
                                    </ul>
                                </li>
                            </ul>
                        </li>
                        <li>
                            <a href="#">Level 2</a>
                        </li>
                    </ul>
                </li>
                <li>
                    <a href="#">Level 1</a>
                </li>
                <li>
                    <a href="#">Level 1</a>
                </li>
                <li class="has-children">
                    <a href="#">Level 1</a>
                    <button>Show sub-menu for ‘Level 1’</button>
                    <ul>
                        <li class="has-children">
                            <a href="#">Level 2</a>
                            <button>Show sub-menu for ‘Level 2’</button>
                            <ul>
                                <li class="has-children">
                                    <a href="#">Level 3</a>
                                    <button>Show sub-menu for ‘Level 3’</button>
                                    <ul>
                                        <li>
                                            <a href="#">Level 4</a>
                                        </li>
                                        <li>
                                            <a href="#">Level 4</a>
                                        </li>
                                    </ul>
                                </li>
                            </ul>
                        </li>
                        <li>
                            <a href="#">Level 2</a>
                        </li>
                    </ul>
                </li>
            </ul>
        </nav>

就好像在焦点移动到嵌套链接之前,状态就开始了。谁能确认我在这里吠叫一棵不可能的树,或者是否有办法让它工作?display: none

编辑:另一件需要注意的事情是,如果你继续制表,它会在列表项的第一级中保持正确的位置,所以它确实感觉焦点是嵌套列表的第一个锚元素,但它只是没有认识到嵌套有一个焦点在其中。ol

html css css-selectors 嵌套列表

评论


答:

0赞 Dan 8/6/2021 #1

设法使用元素而不是元素来解决它:focus-withinliul

    .menu ul li ul {
        display:none;
    }
    .menu button:focus + ul,
    .menu ul li:focus-within > ul {
        display: block;
    }
    .menu ul li:focus-within a:focus ~ ul {
        display: none;
    }

仍然不能 100% 理解为什么原始场景不起作用,但这是一个可行的解决方案。