CSS 使用文档片段的锚元素选择器

CSS selector for anchor element using document fragment

考虑以下示例代码

<body>
    <nav>
        <a href="#s1">First Section</a>
        <a href="#s2">Section 2</a>
    </nav>
    <main>
        <section id="s1">
            <p>Example paragraph
            <p>Paragraph 2
        </section>
        <section id="s2">
            <p>Example paragraph
            <p>Paragraph 2
        </section>
    </main>
</body>

我可以 select section select 与

编辑
section {
    background: #fff;
}

section:target {
    background: #f00;
}

但我想针对select编辑它的a仅使用HTML/CSS,我可以想象它像

a[href=:target] {
    font-weight: bold;  
}

a:target(href) {
    font-weight: bold;
}

我能想出的唯一解决办法是

HTML:

<body>
    <div id="s1"><div id="s2">
        <nav>
            <a href="#s1">First Section</a>
            <a href="#s2">Section 2</a>
        </nav>
        <main>
            <section name="s1">
                <p>Example paragraph
                <p>Paragraph 2
            </section>
            <section name="s2">
                <p>Example paragraph
                <p>Paragraph 2
            </section>
        </main>
    </div></div>
</body>

CSS:

#s1:target a[href="#s1"],
#s2:target a[href="#s2"] {
    font-weight: bold;
}

section {
    background: #fff;
}

#s1:target section[name="s1"],
#s2:target section[name="s2"] {
    background: #f00;
}

不过,我不喜欢这样,因为它引入了不必要的元素(目标 div)。

没有 JavaScript 是否有干净的方法来做到这一点?

虽然 :target 伪 class 存在用于匹配命名锚点或具有与当前 URL 片段对应的 ID 的元素,但 CSS 不提供用于匹配指向当前 URL 片段的链接的选择器。

没有 JavaScript 就没有干净的方法可以做到这一点。为了适应 CSS(section 元素不能具有 name 属性),我更愿意使用 JavaScript 而不是使用无语义元素和无效属性污染标记。

hashchange 事件是 well-supported,所以如果您负担得起,只需监听该事件并在正确的元素上切换 class:

var navLinks = document.querySelectorAll('nav > a');

window.onhashchange = function() {
    for (var i = 0; i < navLinks.length; i++) {
        if (navLinks[i].href.match(/(#.*)/)[1] == window.location.hash) {
            navLinks[i].className = 'selected';
        } else {
            navLinks[i].className = '';
        }
    }
};

var navLinks = document.querySelectorAll('nav > a');

window.onhashchange = function() {
    for (var i = 0; i < navLinks.length; i++) {
        if (navLinks[i].href.match(/(#.*)/)[1] == window.location.hash) {
            navLinks[i].className = 'selected';
        } else {
            navLinks[i].className = '';
        }
    }
};
section {
    background: #fff;
}

section:target {
    background: #f00;
}

a.selected {
    font-weight: bold;
}
<nav>
    <a href="#s1">First Section</a>
    <a href="#s2">Section 2</a>
</nav>
<main>
    <section id="s1">
        <p>Example paragraph
        <p>Paragraph 2
    </section>
    <section id="s2">
        <p>Example paragraph
        <p>Paragraph 2
    </section>
</main>

基于 BoltClock 代码,2021 年:

window.addEventListener("hashchange", event => {
    document.querySelectorAll("nav > a").forEach(link => {
        if (new URL(link).hash == new URL(event.newURL).hash) {
            link.classList.add("selected");
        } else {
            link.classList.remove("selected");
        }
    });
});

您可能还想在加载时设置它

for (const link of document.querySelectorAll("nav > a")) {
    if (new URL(link).hash == location.hash) {
        link.classList.add("selected");
        break;
    }
};