使用 CSS :target 选择器

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您的旅程的每个阶段提供云产品。 立即开始使用 $200 免费积分!

CSS 中的 :target 伪选择器在 URL 中的哈希值和元素的 ID 相同时匹配。

当前 URL 的哈希值为“voters”。
<section id="voters"> 
   Content
</section>
:target {
   background: yellow;
}

只要 URL 保持不变,该 section 元素就会根据我们的 CSS 具有黄色背景。

您将在何时使用此功能?

一种可能性是,当您需要使用“状态”进行样式设置时。 当页面具有特定哈希值时,它就处于该状态。 它不像操作类名那样灵活(因为只能有一个哈希值,并且它只能与一个元素相关联),但它们类似。 在元素处于 :target 状态时,您可以在更改类名以更改状态时执行任何操作。 例如:更改颜色、更改位置、更改图像、隐藏/显示内容,等等。

我会使用以下经验法则来判断何时 :target 是一个不错的选择。

  1. 当需要“状态”时
  2. 当向下跳转的行为可以接受时
  3. 当可以影响浏览器历史记录时

我们将在本文中介绍所有这些内容。

如何在 URL 中添加哈希值?

最常见的方法是用户单击包含哈希值的链接。 可以是内部(同页面)链接,也可以是完全限定的 URL,该 URL 恰好以哈希值和值结尾。 例如

<a href="#voters">Go To There</a>

<a href="http://example.com/#specific-part">Go To There</a>

跳转行为

无论是否是同页面链接,浏览器的行为都是滚动页面,直到该元素位于页面顶部。 或者,如果无法滚动到那么远,则尽可能地滚动。 这点非常重要,因为这意味着利用这种“状态”行为有点棘手/有限。

例如,我曾经 尝试过各种技术 来复制功能性 CSS 选项卡,但最终决定使用 复选框技巧 是一个 更好的主意,因为它避免了页面跳转问题。 CSS Science 的 Ian Hansson 也提供了一些 选项卡示例。 他的第三个示例使用 :target以及绝对定位的元素,这些元素隐藏在页面顶部上方,以防止页面跳转行为。 这个方法很巧妙,但并不是真正的解决方案,因为如果选项卡位于页面更下方,则页面会向上跳转。 锚点实际上是固定位置的,这意味着它们会随着页面滚动而滚动,并且不会出现顶部跳转行为。 非常巧妙!

完美用法:突出显示部分

问题:当哈希链接将您快速滚动到页面上的相关部分时,它会尝试将该部分紧贴到浏览器窗口的顶部。

但是,如果该部分下方没有足够的滚动空间怎么办? 该部分将可见,但不会紧贴顶部,这可能会让人感觉奇怪和令人困惑。

这会让人感到迷惑。

我可不是在信口开河。 根据个人经验,页面跳转链接不会将我带到我所链接到的位置的顶部,我就会感到十分困惑。 我发现这种情况在 FAQ 页面上经常发生,因为链接到的部分通常不太高。

所以,让我们解决这个问题!

一种历史方法称为 黄色淡出技巧。 37signals 在页面中添加新内容的情况下采用了这种方法,他们试图吸引用户注意新内容。 Jonathan Snook 将这个想法移植到了 CSS 中,并将其与 :target 相结合。

我们不会使用黄色淡出,而是通过将部分向右轻轻推动并闪烁红色边框来指示我们刚刚单击的链接所引用的部分。 我们不会让你觉得,你已经到达了这里。

该结构是导航的一部分,它通过 ID 链接到各个部分。

<nav>
  <a href="#one">1</a>
  <a href="#two">2</a>
  <a href="#three">3</a>
</nav>

<section>
  <div id="one"><h2>One</h2>Pellentesque habitant morbi ...</div>
  <div id="two"><h2>Two</h2>Pellentesque habitant morbi ...</div>
  <div id="three"><h2>Three</h2>Pellentesque habitant morbi ...</div>
</section>

当部分变为 :target 时,它们会通过 translateX 变换稍微向右移动(防止出现任何奇怪的文本换行或我们在使用填充时可能遇到的任何问题),并且通过关键帧动画闪烁红色边框。

:target {
  animation: highlight 1s ease;  
  transform: translateX(20px);     
}
@keyframes highlight {
  0% { border-left-color: red; }
  100% { border-left-color: white; }
}
section > div {
  border-left: 40px solid white;
  padding: 10px;
  transition: all 0.5s ease;     
  padding-right: 50px;
  margin-left: -20px;    
}

实际上,这就是全部内容。 如果您担心浏览器支持,我会将其归类为渐进增强。 也就是说,这只是一个不错的功能,不是必需的功能。

查看演示

解决跳转问题!

假设您喜欢使用 :target 来实现状态,但不喜欢页面跳转行为,您可以在不跳转页面的情况下更改 URL 中的哈希链接。

使用 jQuery,您可以定位所有哈希链接,阻止其默认行为,并使用 pushState(或者 replaceState,我认为)来更改 URL(这不会移动页面)。

$("a[href^=#]").on("click", function(e) {
  e.preventDefault();
  history.pushState({}, "", this.href);
});

您也可以在那里互换使用 replaceState,这会更改 URL,但不会在浏览器历史记录中添加条目。 有时您可能想要这样做,有时您可能不想要。 至少在这里您可以选择,而默认情况下单击哈希链接则不行,因为哈希链接总是添加条目。

但是,有一个坏消息

当 URL 更改为新的哈希值时,您可能会认为当前的目标会更改,并且新的 CSS 会生效。 但事实并非如此(在撰写本文时已测试了当前的 WebKit 和 Firefox)。 这是一个错误。

从理论上讲,您可以测量并保存页面当前的滚动位置,让链接自然移动,然后将其设置回原来的位置。 但这听起来太糟糕了,我甚至无法强迫自己为它创建一个测试页面。

更多