【问题标题】:Div anchors scrolling too fardiv 锚滚动太远
【发布时间】:2021-10-22 11:58:49
【问题描述】:

我在我的网站顶部使用了一个静态栏,大约 20 像素高。当我点击一个锚链接时(对于那些不知道的人,维基百科上的导航就是这样工作的。点击一个标题,浏览器会转到它)部分文本消失在那个顶部栏后面。

有没有办法阻止这种情况发生?我无法使用 iFrame。我唯一能想到的就是让它每次回滚一点,但还有其他方法吗?一些 CSS 设置来操纵身体或其他什么?

【问题讨论】:

  • 我将 iframe 排除在外,这会使它更加混乱。
  • “还有其他方法吗?”是的,使用 JavaScript 更改浏览器的默认行为。默认情况下,锚点滚动到视图中的距离不够远。

标签: css anchor


【解决方案1】:

您可以只使用 CSS 而无需任何 javascript。

给你的主播上课:

<a class="anchor"></a>

然后,您可以通过将锚定为块元素并进行相对定位,将锚定位到高于或低于实际出现在页面上的位置。 -250px 将使锚点向上 250px

a.anchor{display: block; position: relative; top: -250px; visibility: hidden;}

到一月见offsetting an html anchor to adjust for fixed header

【讨论】:

  • 啊哈,所以display: block 是问题所在。我尝试做类似的事情,但浏览器会忽略相对偏移量,我最终得到a[name] {position: absolute; height: 150px; margin-top: -150px;}。
  • 这很好用。这个问题困扰了我多年。谢谢!
  • 这一定是我见过的最壮观的 CSS 技巧之一。
  • 我很高兴找到了这个答案,它帮助我解决了我的问题。我仍然想知道为什么有时会发生滚动太远的情况。也许只是锚点在标记中的位置太低了?
  • 应该是公认的答案。干得好。
【解决方案2】:

这是一个现代的、单行的、纯 CSS 解决方案:

scroll-margin-top: 20px;

它的作用就像它听起来的那样:就像有一个边距一样,但只有在滚动的上下文中。所以scroll-margin-top: 20px; 在元素上意味着单击该元素的锚标记会将页面滚动到元素上方 20px 。

兼容性 (See caniuse)

不支持 IE。此外,Safari 版本 11-14 使用非标准名称:scroll-snap-margin-top(但在其他方面按预期工作)。 Safari 14.1+ 使用标准名称。

完整示例:

nav{
  position: fixed;
  top:0;
  left:0;
  background: black;
  color: white;
  width: 100%;
}

#after-nav{
  margin-top: 25px;
}

#section-1{
  width: 100%;
  background: green;
  height: 500px;
  scroll-margin-top: 20px;
}

#section-2{
  width: 100%;
  background: blue;
  height: 500px;
  scroll-margin-top: 20px;
}

ul{
margin-top: 0;
}
<nav>
Nav bar: 20px (as in OP)
</nav>
<div id="after-nav">
Table of contents:
<ul>
<li><a href="#section-1">Section 1</a></li>
<li><a href="#section-2">Section 2</a></li>
</ul>


<div id="section-1">Section 1</div>
<div id="section-2">Section 2</div>
</div>

【讨论】:

  • 这个问题的其他一些答案已经有将近 10 年的历史了。 IMO,对于现代浏览器,这个答案是最简单和最干净的。
  • 不错的答案!这可能会干扰引导程序的滚动间谍。
  • 那么清新,那么干净。这非常有效。谢谢!
  • 'scroll-margin-top' 不受 Internet Explorer、Safari
  • 好东西,谢谢!
【解决方案3】:

要使用 CSS 解决此问题,您可以为要跳转到的元素添加填充:

Example

或者,您可以添加边框:

div{ 
  height: 650px; 
  background:#ccc; 
  /*the magic happens here*/
  border-top:42px solid #fff;
}
ul{
  top: 0; 
  width: 100%; 
  height:20px; 
  position: fixed; 
  background: deeppink; 
  margin:0;
  padding:10px; 
}
li{
  float:left;
  list-style:none;
  padding-left:10px;
}
div:first-of-type{ 
  margin-top:0; 
}
<!-- content to be placed inside <body>…</body> -->
<ul>
  <li><a href="#s1">link 1</a>
  <li><a href="#s2">link 2</a>
  <li><a href="#s3">link 3</a>
  <li><a href="#s4">link 4</a>
</ul>
<div id="s1" class="first">1</div>
<div id="s2">2</div>
<div id="s3">3</div>
<div id="s4">4</div>

但是,这并不总是适用的。

对于 javascript 解决方案,您可以使用附加到锚元素的点击事件来滚动调整的像素数量,如下所示:

document.querySelector("a").addEventListener("click",function(e){
    // dynamically determining the height of your navbar
    let navbar = document.querySelector("nav");
    let navbarheight = parseInt(window.getComputedStyle(navbar).height,10);
    // show 5 pixels of previous section just for illustration purposes 
    let scrollHeight = document.querySelector(e.target.hash).offsetTop - navbarheight - 5;
    /* scrolling to the element taking the height of the static bar into account*/
    window.scroll(0,scrollHeight);
    /*properly updating the window location*/
    window.location.hash = e.target.hash;
    /* do not execute default action*/
    e.preventDefault();
});
nav{
  position:fixed;
  top:0;
  left:0;
  right:0;
  height:40px;
  text-align:center;
  background:#bada55;
  margin:0;
}
a{
  display:block;
  padding-top:40px;
}
#section1{
  height:800px;
  background:repeating-linear-gradient(45deg,#606dbc55,#606dbc55 10px,#46529855 10px,#46529855 20px);
}
#section2{
  height:800px;
  background:repeating-linear-gradient(-45deg,#22222255,#22222255 10px,#66666655 10px,#66666655 20px);
}
<nav>static header</nav>
<a href="#section2">jump to section 2</a> 
<div id="section1">Section 1</div>
<div id="section2">Section 2</div>

【讨论】:

  • 我应该附加什么事件?请提供完整的 jQuery 示例。
  • @Arugin 我在 jQuery stackoverflow.com/a/50690779/722796 中找到了它,不需要填充,只是不要滚动太远。填充是错误的解决方案,因为它可能会破坏网页设计。
  • @PJBrunet 首先,如果您仔细阅读问题,OP 没有包含 JS 标签,这就是为什么我首先给出了 CSS 解决方案(这是他明确提到的)。另外,我看不出为什么填充应该“破坏”精心制作的网页设计。其次,我还提供了一个简洁的javascript解决方案,那么downvote的原因是什么?
  • 很抱歉,但我不同意填充是可接受的解决方案。例如,使用流行的 Envato 主题,我的所有锚点在屏幕上显示的 90 像素太高(标题完全隐藏在导航栏下),如果您尝试为每个锚点添加 90 像素,它看起来会消失。我想大多数设计师都会同意这将是一种严厉的方法。 Z 索引导航栏现在很流行。我在不同的设计中遇到过几次这个问题,填充太多了。坦率地说,我认为这是一个浏览器错误。浏览器应该负责知道锚点是否隐藏在导航栏下。
  • 我还想指出,即使没有导航栏,浏览器似乎也是为了将锚点放在屏幕边缘而设计的,这看起来已经很糟糕了。所以导航栏只会使问题更加复杂。例如,在您正在查看的这个页面上,如果您单击“共享”链接,您会发现问题——upvote 箭头从页面顶部被切掉,然后看起来它被 JS 轻推了。您认为 StackOverflow 是否应该在每个答案的顶部添加更多填充?如果你问我填充看起来很漂亮,我们不应该破坏设计比例来修复浏览器滚动错误。
【解决方案4】:

CSS-only:它有点脏,但:target {padding-top: 20px;} 会工作如果你链接到一个块元素(我假设你这样做,因为你的问题说分)。但是,当您之后手动滚动时,它可能看起来不太好。示例http://dabblet.com/gist/3121729

不过,我认为使用一点 JavaScript 来解决这个问题会更好。

【讨论】:

【解决方案5】:

我遇到了同样的问题。这是一个jQuery解决方案

$('a[href^="#"]').on('click',function (e) {
    e.preventDefault();
    var target = this.hash;
    var $trget = $(target);
    // Example: your header is 70px tall.
    var newTop = $trget.offset().top - 70; 
    $('html, body').animate ({
        scrollTop: newTop
    }, 500, 'swing', function () {
        window.location.hash = target;
    }); 
});

【讨论】:

  • html, body的原因是浏览器兼容性stackoverflow.com/a/19738288/722796
  • 类似的解决方案在这里stackoverflow.com/questions/11365091/…
  • 由于您对这里的几个答案应用了非常严格的规则和严厉的批评者,因此我在这里有以下不满之处:1) javascript 回答仅针对 css 的问题,2) 在1),包括一个用于完全不需要的东西的沉重框架 3) 错误代码(用无效值覆盖窗口哈希) 4) 产生重复的内容(正确的做法是提供指向问题的链接答案的评论部分)请至少清理您的代码!
  • @christoph 不要个人认为,我的解决方案效果更好。对不起,你有一个脆弱的自我,尤其是在这样一个薄弱的解决方案上。 1. 如果你懂英语,他确实不要求“仅 CSS”。 2. jQuery 已经在大多数浏览器的缓存中,对于大多数人来说没有什么可下载的。 3. 你剩下的评论是荒谬的。如果您看到错误,您可以尝试“编辑”按钮,但由于此 jQuery 解决方案适用于许多开发人员,请尝试“修复”它。原始代码源自流行的 YouTube 视频。 4. 摇摆效果很棒,可以控制速度。
  • 作为 SO 社区的一员,您似乎对平台的运作方式知之甚少:1) 标签的存在是有原因的,2) 投票不是为了表达您的个人意见,而是为了标记草率、糟糕或明显错误的答案 3) 避免重复内容应该符合每个用户的利益。另外,我解释了您的代码中有什么问题,因此这只是本着降低投票的原始含义的一种教育举措,让您解决代码中的明显问题-但是是的,我可能会编辑更友好用户的答案我自己而不是 DV。
【解决方案6】:

试试window.scrollBy(xnum,ynum);

xnum:沿 x 轴(水平)滚动多少像素 ynum:沿y轴(垂直)滚动多少像素

例如:http://www.w3schools.com/js/tryit.asp?filename=try_dom_window_scrollby

【讨论】:

  • 如果我没有针对这个问题的竞争帖子,我会给 -1 以引用 w3schools。如果您对原因感兴趣,请查看w3fools.com
  • @Christoph 感谢您提供宝贵的信息。这里我只提到了一个例子,它展示了它是如何工作的,仅此而已。
  • 是的,我只是想指出,必须非常小心地使用 w3schools。如果您想要更好的基础,请改用MDN。
【解决方案7】:

在搜索完上述所有其他答案后,对我来说解决滚动锚问题的答案如下:

代码:

#idname {
    scroll-margin-top: 20px;
}

感谢以上提出此答案的人。您显然可以更改边距的像素数。我将它从 20px 更改为 40px,它就像一个魅力。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-02
    • 2014-08-31
    • 1970-01-01
    • 1970-01-01
    • 2013-04-12
    • 1970-01-01
    • 2013-04-29
    相关资源
    最近更新 更多