157

我不确定询问/搜索此问题的最佳方式:

当您单击锚链接时,它会将您带到页面的该部分,链接区域现在位于页面的最顶部。我希望锚链接将我发送到页面的该部分,但我希望顶部有一些空间。例如,我不希望它将我发送到 VERY TOP 的链接部分,我希望那里有 100 像素左右的空间。

这有意义吗?这可能吗?

编辑显示代码 - 它只是一个锚标签:

<a href="#anchor">Click me!</a>

<p id="anchor">I should be 100px below where I currently am!</p>
4

26 回答 26

177
window.addEventListener("hashchange", function () {
    window.scrollTo(window.scrollX, window.scrollY - 100);
});

这将允许浏览器为我们完成跳转到锚点的工作,然后我们将使用该位置进行偏移。

编辑1:

正如@erb 所指出的,这仅适用于您在页面上同时更改哈希值的情况。输入#somethingURL 中已有的页面不适用于上述代码。这是处理该问题的另一个版本:

// The function actually applying the offset
function offsetAnchor() {
    if(location.hash.length !== 0) {
        window.scrollTo(window.scrollX, window.scrollY - 100);
    }
}

// This will capture hash changes while on the page
window.addEventListener("hashchange", offsetAnchor);

// This is here so that when you enter the page with a hash,
// it can provide the offset in that case too. Having a timeout
// seems necessary to allow the browser to jump to the anchor first.
window.setTimeout(offsetAnchor, 1); // The delay of 1 is arbitrary and may not always work right (although it did in my testing).

注意:要使用 jQuery,您可以在示例中window.addEventListener替换为。$(window).on谢谢@霓虹灯。

编辑2:

正如一些人所指出的,如果您连续两次或多次单击同一锚链接,上述操作将失败,因为没有hashchange事件强制偏移。

此解决方案是@Mave 建议的略微修改版本,并使用 jQuery 选择器为简单起见

// The function actually applying the offset
function offsetAnchor() {
  if (location.hash.length !== 0) {
    window.scrollTo(window.scrollX, window.scrollY - 100);
  }
}

// Captures click events of all <a> elements with href starting with #
$(document).on('click', 'a[href^="#"]', function(event) {
  // Click events are captured before hashchanges. Timeout
  // causes offsetAnchor to be called after the page jump.
  window.setTimeout(function() {
    offsetAnchor();
  }, 0);
});

// Set the offset when entering page with hash present in the url
window.setTimeout(offsetAnchor, 0);

这个例子的 JSFiddle 在这里

于 2013-07-08T20:07:21.700 回答
101

仅使用 css 您可以向锚定元素添加填充(如上面的解决方案中)为了避免不必要的空白,您可以添加相同高度的负边距:

#anchor {
    padding-top: 50px;
    margin-top: -50px;
}

我不确定这是否是最好的解决方案,但对我来说效果很好。

于 2014-02-28T12:27:52.857 回答
90

这是2020年的答案:

#anchor {
  scroll-margin-top: 100px;
}

因为它得到了广泛的支持

于 2020-04-01T16:21:21.003 回答
70

更好的解决方案:

<p style="position:relative;">
    <a name="anchor" style="position:absolute; top:-100px;"></a>
    I should be 100px below where I currently am!
</p>

只需将<a>具有绝对定位的标签定位在相对定位的对象内。

在进入页面或通过页面内的哈希更改时工作。

于 2015-03-26T07:45:02.540 回答
14

最佳解决方案

<span class="anchor" id="section1"></span>
<div class="section"></div>

<span class="anchor" id="section2"></span>
<div class="section"></div>

<span class="anchor" id="section3"></span>
<div class="section"></div>

<style>
.anchor{
  display: block;
  height: 115px; /*same height as header*/
  margin-top: -115px; /*same height as header*/
  visibility: hidden;
}
</style>
于 2015-03-19T14:02:02.743 回答
13

这将在没有 jQuery 和页面加载的情况下工作。

(function() {
    if (document.location.hash) {
        setTimeout(function() {
            window.scrollTo(window.scrollX, window.scrollY - 100);
        }, 10);
    }
})();
于 2014-01-31T06:57:52.527 回答
8

这个纯 CSS 解决方案对我有用。

:target:before {
content:"";
display:block;
height:90px; /* fixed header height*/
margin:-90px 0 0; /* negative fixed header height */
}

我在这里找到它-> https://www.wikitechy.com/tutorials/javascript/offsetting-an-html-anchor-to-adjust-for-fixed-header

这是一个小提琴: https ://jsfiddle.net/e8o2p3az/

于 2021-06-03T13:15:27.313 回答
5

试试这段代码,点击链接时已经有流畅的动画了。

$(document).on('click', 'a[href^="#"]', function (event) {
    event.preventDefault();

    $('html, body').animate({
        scrollTop: $($.attr(this, 'href')).offset().top - 100
    }, 500);
});
于 2018-05-15T05:38:25.553 回答
4

要链接到一个元素,然后使用纯 CSS 将该元素“定位”到距页面顶部任意距离,您必须使用padding-top,这样该元素仍位于窗口顶部,但它显然,它位于距视口顶部一定距离的位置,例如:

<a href="#link1">Link one</a>
<a href="#link2">Link two</a>

<div id="link1">
    The first.
</div>

<div id="link2">
    The second.
</div>

CSS:

div {
    /* just to force height, and window-scrolling to get to the elements.
       Irrelevant to the demo, really */
    margin-top: 1000px;
    height: 1000px;
}

#link2 {
    /* places the contents of the element 100px from the top of the view-port */
    padding-top: 100px;
}

JS 小提琴演示

要使用纯 JavaScript 方法:

function addMargin() {
    window.scrollTo(0, window.pageYOffset - 100);
}

window.addEventListener('hashchange', addMargin);

JS 小提琴演示

于 2013-07-08T19:49:25.060 回答
4

这应该有效:

    $(document).ready(function () {
    $('a').on('click', function (e) {
        // e.preventDefault();

        var target = this.hash,
            $target = $(target);

       $('html, body').stop().animate({
        'scrollTop': $target.offset().top-49
    }, 900, 'swing', function () {
    });

        console.log(window.location);

        return false;
    });
});

只需将 .top-49 更改为适合您的锚链接的内容。

于 2015-08-14T21:23:13.290 回答
3

如果您使用明确的锚名称,例如,

<a name="sectionLink"></a>
<h1>Section<h1>

然后在css中你可以简单地设置

A[name] {
    padding-top:100px;
}

只要您的 HREF 锚标记不指定 NAME 属性,这将起作用

于 2014-10-26T20:54:01.113 回答
3

埃里克的回答很好,但你真的不需要那个超时。如果您使用的是 jQuery,则可以等待页面加载。所以我建议将代码更改为:

// The function actually applying the offset
function offsetAnchor() {
    if (location.hash.length !== 0) {
        window.scrollTo(window.scrollX, window.scrollY - 100);
    }
}

// This will capture hash changes while on the page
$(window).on("hashchange", function () {
    offsetAnchor();
});

// Let the page finish loading.
$(document).ready(function() {
    offsetAnchor();
});

这也使我们摆脱了那个任意因素。

于 2016-05-29T21:54:03.050 回答
2

我刚刚为自己找到了一个简单的解决方案。上边距为 15px

HTML

<h2 id="Anchor">Anchor</h2>

CSS

h2{margin-top:-60px; padding-top:75px;}
于 2019-01-28T10:07:49.747 回答
1

最简单的解决方案:

CSS

#link {
    top:-120px; /* -(some pixels above) */
    position:relative;
    z-index:5;
}

HTML

<body>
    <a href="#link">Link</a>
    <div>
        <div id="link"></div> /*this div should placed inside a target div in the page*/
        text
        text
        text
    <div>
</body>
于 2017-03-03T10:22:20.600 回答
1

Thomas 解决方案的一个变体:CSS element>element选择器在这里很方便:

CSS

.paddedAnchor{
  position: relative;
}
.paddedAnchor > a{
  position: absolute;
  top: -100px;
}

HTML

<a href="#myAnchor">Click Me!</a>

<span class="paddedAnchor"><a name="myAnchor"></a></span>

单击链接会将滚动位置移动到 100px 上方的位置,其中包含 class of 的元素paddedAnchor

在非 IE 浏览器和 IE 版本 9 中受支持。对于 IE 7 和 8 的支持,<!DOCTYPE>必须声明 a。

于 2018-12-30T05:47:52.520 回答
1

仅使用 css 并且之前覆盖且不可点击的内容没有问题(重点是指针事件:无):

CSS

.anchored::before {
    content: '';
    display: block;
    position: relative;
    width: 0;
    height: 100px;
    margin-top: -100px;
}

HTML

<a href="#anchor">Click me!</a>
<div style="pointer-events:none;">
<p id="anchor" class="anchored">I should be 100px below where I currently am!</p>
</div>
于 2019-07-10T11:36:06.120 回答
1

把它放在风格中:

.hash_link_tag{margin-top: -50px; position: absolute;}

div并在链接之前的单独标签中使用此类,例如:

<div class="hash_link_tag" id="link1"></div> 
<a href="#link1">Link1</a>

或将此 php 代码用于回显链接标记:

function HashLinkTag($id)
{
    echo "<div id='$id' class='hash_link_tag'></div>";
}
于 2019-12-21T05:38:00.173 回答
0

我知道这有点晚了,但是如果您使用的是 Bootstrap 的 Scrollspy,我发现在您的代码中添加一些非常重要的内容。(http://getbootstrap.com/javascript/#scrollspy

这让我发疯了好几个小时。

滚动间谍的偏移量必须与 window.scrollY 匹配,否则您将面临以下风险:

  1. 滚动时出现奇怪的闪烁效果
  2. 您会发现,当您单击锚点时,您将进入该部分,但滚动间谍会假定您位于其上方的部分。

 var body = $('body');
    body.scrollspy({
        'target': '#nav',
        'offset': 100 //this must match the window.scrollY below or you'll have a bad time mmkay
});

$(window).on("hashchange", function () {
        window.scrollTo(window.scrollX, window.scrollY - 100);
});

于 2015-10-22T22:50:17.273 回答
0

基于@Eric Olson解决方案只需稍作修改以包含我想要专门去的锚元素

// Function that actually set offset
function offsetAnchor(e) {
    // location.hash.length different to 0 to ignore empty anchor (domain.me/page#)
    if (location.hash.length !== 0) {
        // Get the Y position of the element you want to go and place an offset
        window.scrollTo(0, $(e.target.hash).position().top - 150);
    }
}

// Catch the event with a time out to perform the offset function properly
$(document).on('click', 'a[href^="#"]', function (e) {
    window.setTimeout(function () {
        // Send event to get the target id later
        offsetAnchor(e);
    }, 10);
});
于 2018-03-16T05:20:26.407 回答
0

我只是有同样的问题。我有一个定位像素的导航,我希望吴哥从导航下开始。对我不起作用的解决方案是window.addEventListener...因为我将页面设置为scroll-behavior:smooth所以它设置了偏移量而不是滚动到吴哥。如果setTimeout()时间足够滚动到最后,但它仍然看起来不太好。所以我的解决方案是在吴哥添加一个假定的绝对 div,使用height:[the height of the nav]and bottom:100%。在这种情况下,这个 div 结束于 angkor 元素的顶部,并从您要滚动到的 angkor 的位置开始。现在我所做的就是将吴哥链接设置到这个绝对 div 并完成工作:)

html,body{
    margin:0;
    padding:0;
    scroll-behavior:smooth;
}

nav {
    height:30px;
    width:100%;
    font-size:20pt;
    text-align:center;
    color:white;
    background-color:black;
    position:relative;
}

#my_nav{
    position:fixed;
    z-index:3;
}
#fixer_nav{
    position:static;
}

#angkor{
    position:absolute;
    bottom:100%;
    height:30px;
}
<nav id="my_nav"><a href="#angkor">fixed position nav<a/></nav>
<nav id="fixer_nav"></nav>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nec lacus vel eros rutrum volutpat. Cras ultrices enim sit amet odio dictum, eget consectetur mi pellentesque. Sed mollis gravida nulla, eu euismod turpis efficitur id. Integer pretium posuere fringilla. Aenean laoreet, augue non pharetra elementum, lectus massa congue orci, a imperdiet neque enim ut dui. Praesent commodo orci bibendum leo suscipit viverra. Nunc fermentum semper eleifend. Pellentesque suscipit nulla aliquet, egestas lectus sed, egestas dui. Vivamus scelerisque maximus nibh, ac dignissim nunc tempor a. Praesent facilisis non lacus et aliquam. Proin ultricies lacus vitae nibh ullamcorper gravida. Proin elit arcu, convallis eget posuere quis, placerat id augue. Fusce ex risus, tempus nec orci vitae, feugiat faucibus quam. Integer risus metus, ornare et rhoncus vitae, accumsan a urna.
</p>

<nav><div id="angkor"></div>The angkor</nav>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nec lacus vel eros rutrum volutpat. Cras ultrices enim sit amet odio dictum, eget consectetur mi pellentesque. Sed mollis gravida nulla, eu euismod turpis efficitur id. Integer pretium posuere fringilla. Aenean laoreet, augue non pharetra elementum, lectus massa congue orci, a imperdiet neque enim ut dui. Praesent commodo orci bibendum leo suscipit viverra. Nunc fermentum semper eleifend. Pellentesque suscipit nulla aliquet, egestas lectus sed, egestas dui. Vivamus scelerisque maximus nibh, ac dignissim nunc tempor a. Praesent facilisis non lacus et aliquam. Proin ultricies lacus vitae nibh ullamcorper gravida. Proin elit arcu, convallis eget posuere quis, placerat id augue. Fusce ex risus, tempus nec orci vitae, feugiat faucibus quam. Integer risus metus, ornare et rhoncus vitae, accumsan a urna.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nec lacus vel eros rutrum volutpat. Cras ultrices enim sit amet odio dictum, eget consectetur mi pellentesque. Sed mollis gravida nulla, eu euismod turpis efficitur id. Integer pretium posuere fringilla. Aenean laoreet, augue non pharetra elementum, lectus massa congue orci, a imperdiet neque enim ut dui. Praesent commodo orci bibendum leo suscipit viverra. Nunc fermentum semper eleifend. Pellentesque suscipit nulla aliquet, egestas lectus sed, egestas dui. Vivamus scelerisque maximus nibh, ac dignissim nunc tempor a. Praesent facilisis non lacus et aliquam. Proin ultricies lacus vitae nibh ullamcorper gravida. Proin elit arcu, convallis eget posuere quis, placerat id augue. Fusce ex risus, tempus nec orci vitae, feugiat faucibus quam. Integer risus metus, ornare et rhoncus vitae, accumsan a urna.

</p>

于 2018-05-29T11:05:10.013 回答
0

我遇到了类似的问题,我通过使用以下代码解决了

$(document).on('click', 'a.page-scroll', function(event) {
        var $anchor = $(this);
        var desiredHeight = $(window).height() - 577;
        $('html, body').stop().animate({
            scrollTop: $($anchor.attr('href')).offset().top - desiredHeight
        }, 1500, 'easeInOutExpo');
        event.preventDefault();
    });
于 2018-12-26T11:54:03.073 回答
0

我遇到了同样的问题,并且没有 JS 的 CSS 有一个非常快速和简单的解决方案。只需创建一个单独的无样式 div,其 ID 为 " aboutMeAnchor,然后将其放置在您实际想要登陆的部分上方。

于 2020-12-17T19:10:01.467 回答
0

这也是一个很好的解决方案。像这样在目的地上方创建一个 divdiv并将 a 链接到该 div;

<div class="destination" id="link"></div> /**Needs to be above the destination**/

.destination {
    position:absolute;
    z-index:-1;
    left:0;
    margin-top:-100px;/* height of nav*/
}
于 2021-02-04T15:16:44.143 回答
0

我试图做类似的事情,最终对我有用的是将伪元素添加::before到要滚动到的 div 中。这将在元素之前添加一个空白区域,并且锚链接将滚动到该空白区域的顶部。例如:

#anchor::before {
  content: "";
  display: block;
  height: 60px;
}
于 2021-04-12T23:02:29.983 回答
0

对于我认为与锚链接目标的滚动位置基本相同的问题,我找到了一个令人惊讶的解决方案。

我有一个页面,它显示一个带有子部分的长文档,我通过在它们正上方放置一个书签 dom 元素来标记其标题,如下所示:

<div class = "TB_BookMark"
        id = "someId"  
></div>
<h3 class="TB">Section 1</h3>

这个想法是用户可以通过单击侧窗格中的链接导航到文档的子部分。第一个这样的链接应该将窗口滚动到页面的开头。请注意,上面的书签 div 的内容是空的,这意味着它不应该占用页面空间,因此导航到第一个链接应该导航到页面的开头。

问题是单击第一个链接会滚动页面,因此第一个部分标题立即位于可见区域的顶部,其上方没有空格。换句话说,页面从顶部向下滚动了一点。而当页面被加载或重新加载时,(并且应该)在第一个部分标题上方有一个可见的空白边距。

我相信这与原始问题描述的问题相同。似乎没有办法让第一个链接滚动到页面的最开头。

问题是您在加载页面时看到的与单击第一个链接时看到的不同。当第一个标题上方不再有空白边距时,它看起来不太好,或者当您加载或重新加载页面时边距太大。

我让它工作的方式是这个CSS:

.TB_Bookmark
{ border:solid 0px    Transparent;  /* Does NOT do what I want. */
  border:solid 0.01px Transparent;  /* Does what I want. */
}

h3.TB
{ margin-top:12px;
  margin-bottom:12px;
}

body
{ margin-top: 0px;
}

除了我留下的第一个边界定义作为不起作用的例子之外,以上所有内容都是让它工作的必要条件。第二个边界定义当然会覆盖第一个并因此生效。

为什么“边框:实心0.01px;” 有效,但“边框:实心 0px;” 不是我不明白。0和0.01之间应该没有很大的区别吗?该解决方案适用于 Chrome 和 Firefox,如果我使用“border:solid 0px;”,则两者都停止工作。

于 2021-12-07T03:40:44.427 回答
-2
<a href="#anchor">Click me!</a>

<div style="margin-top: -100px; padding-top: 100px;" id="anchor"></div>
<p>I should be 100px below where I currently am!</p>
于 2015-06-10T11:11:07.333 回答