当链接包含一个哈希值,例如这样
<a href="#section-two">Section Two</a>
浏览器窗口将立即滚动到一个位置,使 ID 为“section-two”的元素可见。 它会滚动到最小的可能位置,使该元素完全可见。 通常这需要将窗口向下滚动,但请注意,如果任何可滚动的父容器需要水平滚动才能使元素可见,浏览器也会执行该操作。 我将这称为“顶撞”浏览器,因为该元素与浏览器窗口的顶边缘齐平。
这可能
- 在美学上不悦
- 令人困惑(尤其是在跳到一个包含大量其他标题的区域时)
- 在固定定位的始终置顶标题的情况下,问题非常严重
固定定位标题是最严重的威胁,因此让我们以它为例并解决它。
scroll-margin-top
更新! 只需使用 这正是 scroll-margin-top
属性的设计目的。 顾名思义,它在滚动事件后为元素添加顶部边距。 因此,如果我们想要在视窗顶部和元素之间有 50px
的空间,我们可以执行以下操作
但是等等! 如果您点击该锚点链接,但什么也没有发生,很可能是因为您使用的是 Safari 11 或更早版本(macOS 或 iOS)。 为了支持这些浏览器,我们需要将它与 scroll-snap-margin-top
配合使用,这是一个旧版本的属性
h2 {
scroll-margin-top: 50px;
scroll-snap-margin-top: 50px; /* iOS 11 and older */
}
/* If the browser supports the property... */
@supports (scroll-margin-top: 0;) {
h2 {
scroll-margin-top: 50px;
}
}
所有其他方法都来自这篇文章的原始版本,该版本于 2010 年发布。
坚如磐石(脏 HTML)方法
与其像往常一样首先关注最先进的方法,不如让我们看看最有可能跨浏览器兼容的实现方法。
我们不会将 ID 放置在标题上,而是将其放在标题内的空 span 标签上。 这完全不会影响标题的外观。 但是,将 span 用于像这样的纯粹行为事物并非理想。
<a href="#goto">Jump</a>
<!-- yadda yadda yadda -->
<h2>
<span id="goto"> </span>
Header
</h2>
然后在 CSS 中,我们将使用负的顶部边距将 span 吸收到实际标题的北部。 然后,我们将通过正的底部填充将标题推回,从而缓解吸取操作造成的任何奇怪的布局问题。
h2 span {
margin-top: -300px; /* Size of fixed header */
padding-bottom: 300px;
display: block;
}
理想情况下,我们只需将 span 绝对定位在标题顶部,但 IE7 不支持这种做法,完全忽略了跳转。 IE6 在固定定位方面存在重大问题,因此此演示在 IE6 中是无效的,让我们不要这样做,尽管我相信如果你能解决固定定位问题,这个想法基本上是可行的。
更花哨(干净 HTML)方法
使用额外的 span 由于两个原因是非语义的:(1) 您将链接直接关联到一个空 span,这是毫无意义的。(2) span 根本不应该在那里。 HTML 应该是
<a href="#goto">Jump</a>
<!-- yadda yadda yadda -->
<h2 id="goto">Header</h2>
然后为了解决顶撞/填充问题,我们将使用一个伪元素来执行 span 在我们的脏 HTML 版本中所做的相同任务。 我们将赋予它一个高度,这会向上推动标题的大小,然后使用负边距将其拉回到位。
h2::before {
display: block;
content: " ";
margin-top: -285px;
height: 285px;
visibility: hidden;
pointer-events: none;
}
来自 Nicolas Gallagher 的更多信息
我在 Forrst 上发布了这个想法的原始版本,Nicolas Gallagher 接受了它并继续研究,就像 Nic 喜欢做的那样 =)。 他指出,如果标题上有背景,并且您不希望背景扩展,则高度/边距技术可能存在问题。 他通过实验使用 background-clip
、使用底部边框和其他方法来防止这种情况。 同时要感谢 Ira McMahon 在 Forrst 上激发了这个想法。
作为 Nic 演示的一部分,他使用 :target 在“跳跃”后更改标题的颜色。 这很好地提醒了我们这个伪选择器,它是一种**完美**的用途。 目标将在 URL 中的哈希标签与元素的 ID 匹配时匹配。 快速提醒:如果 URL 是 http://blahblahblah.com/#header-one
并且存在一个类似于 的元素
怎么了
那么此选择器将匹配
h2:target { background: yellow; }
。
来自 Patrick Strietzel 的更多信息
我发现 IE7 的哈希标签行为(忽略
padding-top
)可以通过将 display 值设置为inline-block
来欺骗。
h2 {
margin-top: -285px;
padding-top: 285px;
display: inline-block;
}
当然,像这样的 display 更改会产生后果。 inline-block
与 block
大不相同,因此请注意。
来自 Kirk Gleffe 的更多信息
Kirk 找到了一种方法,只需使用边距和少量的 transition-delay
就可以实现。
来自 Alex Wolfe 的更多信息
Alex 写信说,标题上的填充可能位于其上方的文本之上。 这意味着它可能会阻止点击或选择文本。 您可以通过 z-index
解决,方法是将文本包装在具有更高 z-index
的东西中,或者,可能是在标题上使用负 z-index
。
哇 - 我从 1994 年开始做网页开发,但我怎么也想不到可以将哈希锚点指向除命名锚点以外的东西。
我一直都在做
好吧,Lance,
我认为你实际上并没有做网页开发,而是做网页“设计”。
是的,两者有区别,是的,作为一名“开发者”你必须知道这些知识;)
请不要往心里去,事实就是这样。
实际上,我做的是“开发”(即数据和算法),而不是设计——因此我对 HTML 的精妙之处不太熟悉。
您也应该能够在不需要任何伪元素的情况下实现这一点。 我相信这应该可以解决问题
h2 {margin-top: -285px; padding-top: 285px;}
目前无法在 IE7 及更早版本中进行尝试。 只要您避免在标题上使用背景/背景图像,您应该没问题。
@Lance
我的天哪! 我也有同样的想法! 所以读到这篇文章的时候我有点困惑。 我现在很想回到一些旧网站,重新做这部分…
对于那些不知道锚点标签可以链接到任何元素的 ID 的人,可能想要阅读 http://www.w3.org/TR/html401/struct/links.html#h-12.2.3。
说到让这些类型的链接在视觉上更吸引人,我喜欢使用 Ariel Flesler 的 jQuery.ScrollTo 插件 http://flesler.blogspot.com/2007/10/jqueryscrollto.html。它已经存在很长时间了,而且做得很好。
这就是我所用的。我喜欢这个插件,因为它为用户提供了他们将要前往的目标的视觉线索;让他们知道他们仍然在同一个页面上。
我一直都是这么做的
<a name="someheading"></a>
<h2>Some Heading</h2>
我认为它并不比你典型的(非上下文)超链接更不语义,而且它完全绕过了 css 问题。
在当前的 HTML5 规范中,在锚点上使用 "name" 属性是无效的。
此外,它并没有完全绕过这个问题。你仍然需要将锚点定位在标题上方,而不会影响文档的视觉流动。这意味着使用属性选择器(不受旧版 IE 支持)或向锚点添加类/id。
抱歉,我本意是想使用 id 而不是 name。是的,需要进行样式设置才能赋予它高度。我想要 "绕过" 的是所有向上拉和向下推的操作。
但是,在查看了 Chris 的演示后,我认为我错过了这些练习的重点(我一开始只看了你的演示,Chris 的有一个巨大的红色横幅,真正说明了这些方法试图解决的复杂性)。
通常,我在网页布局不会出现这种问题的网页中使用哈希链接。额外的 2em 空白不会困扰我(通常,哈希链接会在主要部分之间,因此额外的空间会是合适的)。但是,如果我确实需要绕过另一个元素(比如那个巨大的横幅,或图片、评论框或其他东西),那么它就不是一个合适的解决方案。
哇,这很有趣。我最近在我的这个网站上实现了这个概念(将 "脏 HTML" 放入 这个网站,我为设计师朋友编写的)。
你会看到它有固定位置的标题,并且使用了 jQuery scrollTo 插件。我让它在几乎所有浏览器中都以完全相同的方式运行,没有额外的 HTML 元素——但是 IE7 在点击其中一个链接时,会一直折叠边距。我之前遇到过 IE7 的这种行为,但是什么都无法修复它,即使给元素设置了布局等等。我甚至尝试过通过 JavaScript 重新应用边距设置。(对于 IE6,标题不是固定的,它只是正常滚动)
因此,我不得不求助于添加额外的元素来避免使用负边距。我认为伪元素解决方案是一个不错的选择,但我在想,IE7 的边距是否会出现同样的问题。值得研究一下。
差点忘了——IE7 不支持 :before 伪元素,因此如果需要 IE7 支持,最后一个选项将无法使用。
再次查看,我意识到你使用的 span 元素与我最初理解的方式不同。
这是一个使用干净 HTML 的解决方案,它在除了 IE6 之外的所有浏览器中都能运行
http://www.impressivewebs.com/bump.html
关键变化是标题上的 ID,然后它们获得边距/填充技巧。并且导航部分有一个负边距,页面包装有一些顶部填充,以使一切都整齐。
从 CSS 的角度来看,这不是最干净的解决方案,但为了跨浏览器兼容性,我认为它是可以接受的,并且标记是干净的。
仍然不确定为什么我的实时客户端版本在 IE7 中没有按预期运行,因为这基本上是我所做的,并且它在 IE7 中有效。
嗨 Louis,在我的文章(链接到 Chris 的文章)中,我涵盖了该技术。问题出现在你想要在目标元素上设置背景颜色或图像,并且还想使用 padding-top 的时候。解决方案是使用 border-top 和 background-clip(方法 E)。
是的,感谢你指出这一点。我直到现在才真正查看你的页面。但我认为需要使用背景的可能性很小,可以根据情况进行处理。
唯一支持 background-clip 的 IE 版本是 IE9 Beta。因此,解决此问题的唯一现实的跨浏览器解决方案是 Chris 的 "脏 HTML" 方法或我在上面演示的类似方法。
但是,了解旧版本的 IE 退出使用后会发生什么,这一点非常重要。只是在目前还没有什么实际意义。
对我的上一篇帖子做一个小小的补充。这似乎是一个可能的解决方案
h2 {margin-top: -285px; border-top: 285px solid #same-as-background; background: url(“bg.jpg”);}
没有伪元素,没有剪裁(除非你的标题位于带有背景图像的容器之上)。
是的 Anders,当然,但如果父元素的背景中有重复的图像,那么边框颜色方法将无法使用。
很好。
我一直使用以下方法来定位目标位置。
<a name=”top”>锚点位置</a>
<a href=”#top” >顶部</a>
-vara
怎么样
<a href="#section">跳转</a>
<h2 id="section" style="padding-top:50px">标题</h2>
网页内滚动的哈希标签链接的不错示例。LT
我有一个 70 像素高的固定位置标题。通过调整数值,我能够在 Chrome 中使其正常工作。有没有在 IE 10 中有效的修复方法?这是我的 CSS 代码片段
h2
{
font-family:Georgia, “Times New Roman”, Times, serif;
color:#306;
}
h2:before {
content: ” “;
margin-top: -175px;
height: 175px;
visibility: hidden;
display: block;
display: inline-block;
}
如果要滚动到的 div 嵌套在多个其他 div 中,该怎么办?例如,使用 bootstrap 的行和列类,并尝试滚动到特定内容列。
我在 Dreamweaver 的选项卡面板中遇到了同样的问题。
再一次,你帮助我快速解决了我的问题!非常感谢。
如果我的 `<div id="goto" class="section"></div>` 有背景,我可以使用哪个修复方法来避免在该 div 的内容开始之前出现很大的空白(在一个页面布局中)?
我原以为解决这个问题需要一些 js。但你提出了更简洁的 css **h2:before** 方法。非常感谢你的分享。
我该如何阻止浏览器地址栏中的 URL 更新为带有哈希标签的 URL?
我知道可以用 JavaScript 或 jQuery 来实现,但我找不到它。谢谢
将此添加到可靠的(脏 HTML)方法中可能会有用
h2 span {
margin-top: -300px; /* 固定标题的大小 */
padding-bottom: 300px;
display: block;
font-size:1px;
line-height:1px;
}
我在想,有没有办法在不硬编码高度和 margin-top 的像素的情况下实现这一点?我在我的一个项目中使用了它,当你更改浏览器窗口的大小后,它无法正常工作。
假设我正在查看网站中的一个页面,我已经向下滚动到某个位置,
然后我点击该页面上的一个链接,它使我跳转到第一个页面的完全副本。
现在我可以使用上面的代码在该副本页面的某些点上着陆,感谢你的分享,
但这里有一个令人费解的问题:我该如何跳转到我当前滚动的**完全相同的位置**。
例如,假设我向下滚动页面 120 像素,如何跳转到该页面的副本,并在**完全相同的滚动位置**上。
似乎需要 2 个指令: "步骤 1 - 注意用户当前滚动到多少像素" 和 "步骤 2 - 跳转到该页面的副本,并位于**完全相同的滚动位置**上"。
希望你能在这方面提供帮助,我会非常感谢第一个发布有效代码的人,并寄送 20 美元给他们。
再次感谢。
(附注 - 如果你想知道,想要跳转到当前页面的副本是有充分理由的。假设你在第一个页面上有一个未播放的视频。当有人点击它时,我们会跳转到该视频所在的副本页面,但在该副本页面上,该视频会自动开始播放。然后从那里,如果再向下滚动一点,该副本页面上就会有第二个视频,如果我们点击它,我们会跳转到该页面的另一个副本,其中第一个视频未播放,而第二个视频正在播放。)
这就是我使用这些副本页面的原因,以便让自动播放正常工作,同时告诉所有其他视频停止播放。
因此,如果有人有更好的有效代码想法,可以实现 "点击视频启动视频,同时告诉所有其他正在播放的视频停止播放" 的目标。这将是一个更简洁的解决方案。
对于以上两个请求中的任何一个,如果您能提供帮助,我将不胜感激,并将非常感谢地将20美元寄给第一个发布有效代码的人,无论哪个请求。
谢谢。:-)
这个演示很棒,感谢您花时间把它放在一起。有没有简单的方法可以修改它来适应屏幕顶部的菜单栏?当我点击“下一个”锚点时,我的部分内容标题被我的菜单栏遮挡了。
感谢您对这个问题的任何想法。
David
我只是想说一声非常感谢!这个跨浏览器问题已经困扰了我好几天了 - 您简洁、干净的方法非常完美。