使锚点链接位于其链接位置上方一些像素处


123

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

当您单击锚点链接时,它将带您到页面的该部分,并且链接到的区域现在位于页面的非常顶部。我希望锚链接将我发送到页面的该部分,但我想在顶部留一些空间。在这种情况下,我不希望它将我发送到“链接到”的零件上,该零件在“非常好”的顶部,我希望在那里有100个像素左右的空间。

这有意义吗?这可能吗?

编辑以显示代码-这只是一个锚标记:

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

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


Answers:


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

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

编辑1:

正如@erb指出的那样,仅当您在页面上更改哈希值时,此方法才有效。输入#something网址中已经存在的页面不适用于上述代码。这是处理该问题的另一个版本:

// 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。谢谢@Neon。

编辑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 在这里


1
这仅在用户已经在页面上时才起作用,例如,当用户example.com/#anchor从进行访问时则不起作用example.com/about/
erb 2014年

7
谢谢@erb。OP的问题不需要这种情况,但是为了帮助其他人,我添加了实现的另一个版本。
埃里克·奥尔森

2
仍然缺少一个小细节。如果单击锚点,然后向上滚动,然后再次单击相同的锚点,则不会发生哈希更改,因此不会使用偏移量。有想法吗?
Teo Maragakis 2015年

你可以去$('a[href^="#"]').on('click', function() { offsetAnchor(); });。这样,如果href一个的a元素有开始#,您调用相同的功能。
Mave 2015年

2
无需jQuery-替换$(window).on("hashchange",window.addEventListener("hashchange",
Neon

89

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

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

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


3
如果上方有50像素以内的链接,则它可能会被掩盖并且无法点击,我相信
安德鲁(Andrew)

@Andrew在IE10或Chrome上似乎不是问题。
阴险的胡须2015年

11
您可以使用position: relativeCSS属性执行相同的操作。因此,就像position: relative; top: -50px;
Aleks Dorohovich 2015年

@AleksDorohovich-您可以将其作为单独的答案发布,因为它是现有答案所独有的。
BSMP 2015年

我的页面

64

更好的解决方案:

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

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

进入页面或通过页面内的哈希更改时有效。


4
我更喜欢您的解决方案,因为它不使用javascript。谢谢!
罗萨里奥·鲁索

1
我不明白这个答案。您是在将此链接引用到对象还是对象本身?
CZorio '16

3
带自举式固定顶部导航栏非常有用
Outside_Box

1
@CZorio如果我做对了,那就是(非常认真地)创建一个锚元素(可能是其他东西,例如“ span”而不是“ a”),并将其相对地定位在下面,以便其中的锚href="#anchor"指向该位置,而不是<p>直接指向元素。但有一个警告:请在HTML5中使用id代替name,请参阅:stackoverflow.com/questions/484719/html-anchors-with-name-or-id
逃避2017年

1
确实是更好的解决方案:)
Bobby Ax

21

这是2020年的答案:

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

因为它得到了广泛的支持


1
投反对票的原因是,虽然这样做很好,但并未得到广泛支持。无论是Opera mobile / mini还是safari浏览器/ ios,甚至第一个Edge都不完全支持。
Beda Schmid

1
略少于所有浏览器的90%(包括带有scroll-snap-margin-top的iOS)应该足以选择退出JavaScript解决方案,尤其是在用户影响仅需滚动的情况下。但是,嘿,让我们在这种方法伤害他人之前就放弃它了。
user127091

这样简单而有效的答案。很快就会达到100%的支持(对于现代浏览器)。
Leonel Becerra

17

最佳解决方案

<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>

8
为什么这是最好的解决方案?同样,如果您给出一些解释性/推理性的答案,它会更有帮助。
Phill Healey

在添加HTML来作为锚点时,添加跨度差别不大。然后,仅添加一点CSS就可以解决此问题,而不会出现任何错误。就像其他解决方案一样
Sondre

11

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

(function() {
    if (document.location.hash) {
        setTimeout(function() {
            window.scrollTo(window.scrollX, window.scrollY - 100);
        }, 10);
    }
})();

1
对我有用,并且比css方法具有优势,它适用于页面上的所有哈希位置,因此您不必编写包含每个哈希值的样式,并且记住在添加另一个参数时要修改样式一个新的哈希。它也可以让用户使用背景颜色设置目标样式,而无需像上面@ user3364768的答案那样在背景颜色上方扩展100px(或其他大小),尽管有一种解决方法。
大卫,

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 Fiddle演示

要使用普通的JavaScript方法:

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

window.addEventListener('hashchange', addMargin);

JS Fiddle演示


1
唯一的问题是现在它会将实际的div推到页面的下方。理想情况下,锚链接的下降幅度将比正常情况下下降100像素。如果有必要,我愿意使用JS或jQuery。
damon

3
这不能解决问题,只是在元素之前添加空格。
XCS

user1925805:请参阅更新的答案以获取JavaScript解决方案。@Cristy:我知道,我在回答本身中明确指出:元素仍然位于窗口的顶部,但从外观上看,它似乎位于顶部
大卫说恢复莫妮卡

使用您的JS的最佳,干净的解决方案。谢谢,它对我很好!
DanielaB67 '17

这仅适用于页面内发生哈希更改。但是使用ID重定向了使用,所以这
不起作用

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更改为适合您的锚链接。


3

如果您使用显式锚名称,例如,

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

然后在CSS中,您只需设置

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

只要您的HREF定位标记也未指定NAME属性,此方法便会起作用


谢谢。这是该列表中唯一对我有用的解决方案。
MikeyBunny

3

埃里克(Eric)的回答很好,但是您实际上不需要超时。如果您使用的是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();
});

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


3

尝试此代码,单击链接时它已经具有平滑的动画。

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

    $('html, body').animate({
        scrollTop: $($.attr(this, 'href')).offset().top - 100
    }, 500);
});

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>

1

托马斯(Thomas)解决方案的一种变体:CSS 元素>元素选择器在这里很方便:

的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: paddedAnchor

在非IE浏览器和版本9的IE中均受支持。要在IE 7和8上获得支持,<!DOCTYPE>必须声明一个。


1

我为自己找到了一个简单的解决方案。边距顶端为15像素

的HTML

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

的CSS

h2{margin-top:-60px; padding-top:75px;}

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>

1

把它放在样式中:

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

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

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

或将此PHP代码用于echo链接标记:

function HashLinkTag($id)
{
    echo "<div id='$id' class='hash_link_tag'></div>";
}

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);
});


摘要中只有js吗?无论如何都将无法正常工作

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);
});

0

我只是有同样的问题。我有一个虚拟的pix导航,我想让angkor在该导航下开始。解决方案window.addEventListener...对我不起作用,因为我将页面scroll-behavior:smooth设置为它,所以它设置了偏移量,而不是滚动到Angkor。该setTimeout()工作如果时间anough用于滚动到最后,但还是没有看起来很不错。所以我的解决方案是在Angkor中使用height:[the height of the nav]和添加一个绝对的div bottom:100%。在这种情况下,此div结束于Angkor元素的顶部,并从您将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>


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();
    });

-1
<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>

4
这基本上是与这个答案相同的答案。如果您发布了旧问题的答案,请尝试添加新内容。例如,您可以描述其工作原理。
Artjom B. 2015年

1
我认为,任何答案都应该对其起作用进行某种描述。;-)
Phill Healey's
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.