固定页头重叠页内锚

如果我在HTML页面中有一个非滚动头,固定在顶部,有一个定义的高度:

有没有一种方法可以使用URL锚(#fragment部分)来让浏览器滚动到页面中的某一点,但仍然尊重固定元素没有JavaScript的帮助的高度?

http://example.com/#bar
WRONG (but the common behavior):         CORRECT:
+---------------------------------+      +---------------------------------+
| BAR///////////////////// header |      | //////////////////////// header |
+---------------------------------+      +---------------------------------+
| Here is the rest of the Text    |      | BAR                             |
| ...                             |      |                                 |
| ...                             |      | Here is the rest of the Text    |
| ...                             |      | ...                             |
+---------------------------------+      +---------------------------------+
249239 次浏览
<div style="position:relative; top:-45px;">
<a name="fragment"> </a>
</div>

这段代码应该可以达到目的。将标题栏的高度替换为45px。

编辑:如果使用jQuery是一个选项,我也成功地使用jQuery。带有偏移值设置的localScroll。偏移量选项是jQuery的一部分。scrollTo, jQuery。localScroll是在此基础上构建的。这里有一个演示:http://demos.flesler.com/jquery/scrollTo/(第二个窗口,在'offset'下)

你可以试试这个:

<style>
h1:target { padding-top: 50px; }
</style>


<a href="#bar">Go to bar</a>


<h1 id="bar">Bar</h1>

将顶部填充值设置为头部的实际高度。这将在你的标题顶部引入一个轻微的额外间隙,但它只会在用户跳转到锚点然后向上滚动时才可见。我现在已经为我的网站制定了这个解决方案,但它只在页面顶部显示一个固定的小栏,没有太高。

我使用这种方法:

/* add class="jumptarget" to all targets. */


.jumptarget::before {
content:"";
display:block;
height:50px; /* fixed header height*/
margin:-50px 0 0; /* negative fixed header height */
}

它在每个目标之前添加一个隐形元素。支持IE8+。

以下是更多的解决方案: http://nicolasgallagher.com/jump-links-and-viewport-positioning/ < / p >

你可以用jQuery做到这一点:

var offset = $('.target').offset();
var scrollto = offset.top - 50; // fixed_top_bar_height = 50px
$('html, body').animate({scrollTop:scrollto}, 0);
我也有同样的问题。 我通过在锚元素中添加一个类来解决这个问题,并将topbar高度作为padding-top值
<h1><a class="anchor" name="barlink">Bar</a></h1>

我使用这样的CSS:

.anchor { padding-top: 90px; }

我已经很容易地使用CSS和HTML,使用上面提到的“锚:之前”方法。我认为它是最好的,因为它不会在你的divs之间产生大量的填充。

.anchor:before {
content:"";
display:block;
height:60px; /* fixed header height*/
margin:-60px 0 0; /* negative fixed header height */
}

这似乎并不适用于页面上的第一个div,但你可以通过添加填充到第一个div。

#anchor-one{padding-top: 60px;}

这里有一个工作小提琴:http://jsfiddle.net/FRpHE/24/

我发现处理这个问题的最好方法是(用固定的元素高度替换65px):

div:target {
padding-top: 65px;
margin-top: -65px;
}

如果你不喜欢使用目标选择器,你也可以这样做:

.my-target {
padding-top: 65px;
margin-top: -65px;
}
注意:如果目标元素的背景色与父元素的背景色不同,这个例子将不起作用。 例如:< / p >
<div style="background-color:red;height:100px;"></div>
<div class="my-target" style="background-color:green;height:100px;"></div>

在这种情况下,我的目标元素的绿色将覆盖65px的父元素红色。 我没有找到任何纯CSS解决方案来处理这个问题,但如果你没有其他背景颜色,这个解决方案是最好的

如果你不能或不想设置一个新类,在CSS中的:target伪类中添加一个固定高度的::before伪元素:

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

或者使用jQuery相对:target滚动页面:

var offset = $(':target').offset();
var scrollto = offset.top - 60; // minus fixed header height
$('html, body').animate({scrollTop:scrollto}, 0);

这是一个完整的jquery解决方案,将在IE中工作:

假设导航栏元素是这样的:

<ul>
<li><a class="navigation" href="/#contact-us">Contact us</a></li>
<li><a class="navigation" href="/#about-us">About us</a></li>
</ul>

你可以使用下面的jquery片段来偏移滚动:

$(function() {
$("a.navigation").click(function(event) {
event.preventDefault();
offSetScroll($(this));
});
offSetScrollFromLocation(window.location.href.toLowerCase());
});


function offSetScroll(anchor) {
var href = anchor.attr("href");
offSetScrollFromLocation(href);
}


function offSetScrollFromLocation(href) {
//Change this according to the height of the navigation bar
var fromTop = 250;
if(href.indexOf("#")<=0)
return;
var hash=href.substring(href.indexOf("#"));
var targetOffset = $(hash).offset().top-fromTop;
$('html, body').animate({scrollTop: targetOffset}, 400, function(e) {


});
}

对于Chrome/Safari/Firefox,您可以添加display: block并使用负边距来补偿偏移量,例如:

a[name] {
display: block;
padding-top: 90px;
margin-top: -90px;
}

参见示例http://codepen.io/swed/pen/RrZBJo

虽然一些提出的解决方案工作的片段链接(=哈希链接)相同的页面(像一个菜单链接向下滚动),我发现没有一个工作在当前的Chrome当你想使用片段链接来来自其他页面

因此,从头调用www.mydomain.com/page.html#foo将抵消当前Chrome中任何给定的CSS解决方案或JS解决方案的目标。

还有一个jQuery bug报告描述了问题的一些细节。

解决方案

到目前为止,我发现唯一一个真正在Chrome中工作的选项是JavaScript,不称为onDomReady,但有延迟。

// set timeout onDomReady
$(function() {
setTimeout(delayedFragmentTargetOffset, 500);
});


// add scroll offset to fragment target (if there is one)
function delayedFragmentTargetOffset(){
var offset = $(':target').offset();
if(offset){
var scrollto = offset.top - 95; // minus fixed header height
$('html, body').animate({scrollTop:scrollto}, 0);
}
}

总结

没有JS的延迟解决方案可能在Firefox, IE, Safari中工作,但在Chrome中行不通。

在我的纯粹主义思想中,这感觉有点俗气,但作为一个纯css的解决方案,你可以使用:target选择器为活动锚定元素添加填充:

.
html, body {height:100%; min-height:100%; margin:0;}
body {min-height:200%;}
header {display:inline-block; position:fixed; font-size:1.5em; height:100px; top:0; left:0; right:0; line-height:100px; background:black; text-align:center;}
header a {color:#fff;}
section {padding:30px; margin:20px;}
section:first-of-type, section:target {padding-top:130px;}
<header><a href="#one">#One</a> <a href="#two">#two</a> <a href="#three">#three</a></header>
<section id="one"><h1>One</h1>Aenean lacinia bibendum nulla sed consectetur. Nullam id dolor id nibh ultricies vehicula ut id elit. Integer posuere erat a ante venenatis dapibus posuere velit aliquet.</section>
<section id="two"><h1>Two</h1>Aenean lacinia bibendum nulla sed consectetur. Nullam id dolor id nibh ultricies vehicula ut id elit. Integer posuere erat a ante venenatis dapibus posuere velit aliquet.</section>
<section id="three"><h1>Three</h1>Aenean lacinia bibendum nulla sed consectetur. Nullam id dolor id nibh ultricies vehicula ut id elit. Integer posuere erat a ante venenatis dapibus posuere velit aliquet.</section>

添加一个带有“paddingtop”的类,这样它就可以工作了;)

<h1><a class="paddingtop">Bar</a></h1>

对于css,你有:

.paddingtop {
padding-top: 90px;
}

我发现我必须一起使用这两个 MutttenXdBadabam的CSS解决方案,因为第一个在Chrome中不起作用,第二个在Firefox中不起作用:

a.anchor {
padding-top: 90px;
}


a.anchor:before {
display: block;
content: "";
height: 90px;
margin-top: -90px;
}


<a class="anchor" name="shipping"></a><h2>Shipping (United States)</h2>
...

官方引导采用答案:

*[id]:before {
display: block;
content: " ";
margin-top: -75px; // Set the Appropriate Height
height: 75px; // Set the Appropriate Height
visibility: hidden;
}

< a href = " https://github.com/twbs/bootstrap/issues/1768 issuecomment - 46519033 " >信用< / >

< a href = " https://github.com/copyleft-org/copyleft-guide/commit/476a42bf0d737e13a561dbaf6f4e1e91a333e80d " > < / >合并

我使用@Jpsy的答案,但出于性能原因,我只在URL中存在散列时设置计时器。

$(function() {
// Only set the timer if you have a hash
if(window.location.hash) {
setTimeout(delayedFragmentTargetOffset, 500);
}
});


function delayedFragmentTargetOffset(){
var offset = $(':target').offset();
if(offset){
var scrollto = offset.top - 80; // minus fixed header height
$('html, body').animate({scrollTop:scrollto}, 0);
$(':target').highlight();
}
};

我之所以使用这种方法,是因为出于某种原因,其他提出的解决方案都不适合我。我保证我尽力了。

section {
position: relative;
border-top: 52px solid transparent; /* navbar height +2 */
margin: -30px 0 0;
-webkit-background-clip: padding-box;
-moz-background-clip: padding;
background-clip: padding-box;
}


section:before {
content: "";
position: absolute;
top: -2px;
left: 0;
right: 0;
border-top: 2px solid transparent;
}

如果您愿意,可以将部分替换为类。

来源:跳转链接和视口定位

  • 在Firefox 45和Chrome 52上测试。
  • 引导版本:3.3.7

对于那些不相信我的人,我善意地准备了一个jsfiddle的解决方案:解决方案

使用:before实现的效果很好,直到我们意识到伪元素实际上覆盖和阻塞了位于伪元素区域的指针事件。在:before上使用类似pointer-events: none的东西,甚至直接在锚上使用都没有影响。

我们最终所做的是使锚的定位是绝对的,然后调整它的位置为偏移/高度的固定区域。

偏移锚没有阻塞指针事件

.section-marker {


position: absolute;
top: -300px;
}

这里的值是我们不会阻塞300px范围内的任何元素。缺点是,从Javascript中获取元素的位置需要考虑偏移量,因此任何逻辑都必须进行调整。

这对我来说很管用:

HTML链接到锚点:

<a href="#security">SECURITY</a>

HTML锚:

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

CSS:

.anchor::before {
content: "";
display: block;
margin-top: -50px;
position: absolute;
}

这就是当你点击导航时,我如何让它最终到达正确的位置。我为导航单击添加了一个事件处理程序。然后你可以使用“scrollBy”来向上移动偏移量。

var offset = 90;


$('.navbar li a').click(function(event) {
event.preventDefault();
$($(this).attr('href'))[0].scrollIntoView();
scrollBy(0, -offset);
});

CSS技巧将是一个解决方案。使用jQuery可以实现一个适用于所有场景的解决方案。

参考https://codepen.io/pikeshmn/pen/mMxEdZ

方法:我们使用document.getElementById('header').offsetHeight来获取固定导航的高度

var jump=function(e){


e.preventDefault();                        //prevent "hard" jump
var target = $(this).attr("href");       //get the target


//perform animated scrolling
$('html,body').animate(
{
scrollTop: $(target).offset().top - document.getElementById('header').offsetHeight - 5  //get top-position of target-element and set it as scroll target
},1000,function()                  //scrolldelay: 1 seconds
{
location.hash = target;          //attach the hash (#jumptarget) to the pageurl
});
}


$(document).ready(function()
{
$('a[href*="#"]').bind("click", jump); //get all hrefs
return false;
});

注:

  • 它包含了头部和目标之间5个像素的差异
  • 滚动效果不硬,比较平滑;平滑滚动

一个非常简单的CSS答案是把它放在你的样式表的顶部:

a{padding-top: 90px;}
a:link{padding-top: unset;}

第一种样式管理所有锚标记,第二种样式使用超链接锚标记。

注意:这目前适用于Firefox和Edge,但不适用于Chrome。

我认为最干净的方法是:

  #bar::before {
display: block;
content: " ";
margin-top: -150px;
height: 150px;
visibility: hidden;
pointer-events: none;
}

使用jQuery的最小侵入性方法:

链接:

<a href="#my-anchor-1" class="anchor-link">Go To Anchor 1</a>

内容:

<h3 id="my-anchor-1">Here is Anchor 1</a>

脚本:

$(".anchor-link").click(function() {
var headerHeight = 120;
$('html, body').stop(true, true).animate({
scrollTop: $(this.hash).offset().top - headerHeight
}, 750);
return false;
});

通过将锚链接类分配给链接,其他链接(如手风琴或制表符控件)的行为不会受到影响。

这个问题不需要javascript,但另一个更常见的问题因为这个问题而关闭,我无法回答。

我在这里和其他地方的许多答案都遇到了很多麻烦,因为我的书签锚是FAQ页面中的部分标题,所以抵消标题并没有帮助,因为其余的内容只是停留在原地。所以我想我应该发帖。

我最终做的是几个解决方案的组合:

  1. < p > CSS:

    .bookmark {
    margin-top:-120px;
    padding-bottom:120px;
    display:block;
    }
    

Where "120px" is your fixed header height (maybe plus some margin).

  1. The bookmark link HTML:

    <a href="#01">What is your FAQ question again?</a>
    
  2. The bookmarked content HTML:

    <span class="bookmark" id="01"></span>
    <h3>What is your FAQ question again?</h3>
    <p>Some FAQ text, followed by ...</p>
    <p>... some more FAQ text, etc ...</p>
    

The good thing about this solution is that the span element is not only hidden, it is essentially collapsed and doesn't pad out your content.

I can't take much credit for this solution as it comes from a swag of different resources, but it worked best for me in my situation.

You can see the actual result here.

我对上面列出的答案没有任何运气,最终使用了这个完美的解决方案……

在想要设置锚点的地方创建一个空白span。

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

并应用以下类:

.anchor {
display: block;
height: 115px;       /* same height as header */
margin-top: -115px;  /* same height as header */
visibility: hidden;
}

这个解决方案将工作,即使部分有不同的颜色背景!我在这个链接。找到了解决方案

我创建了一个带有一些换行符的div,并给出了id,然后把我想要显示的代码放在下面。然后链接将带你到图像上方的空间,头部将不再碍事:

<a href="#image">Image</a>
<div id="image"><br><br></div>
<img src="Image.png">

当然,你可以改变换行符的数量来满足你的需要。 这对我来说非常有效,虽然不确定是否有任何问题,但我仍在学习HTML

使用这个脚本

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


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

我需要一些东西,适用于入站链接,页面上的链接,并可以通过JS的目标,以便页面可以响应头部高度的变化

超文本标记语言

<ul>
<li><a href="#ft_who">Who?</a></li>
<li><a href="#ft_what">What?</a></li>
<li><a href="#ft_when">When?</a></li>
</ul>
...
<h2 id="ft_who" class="fragment-target">Who?</h2>
...
<a href="#">Can I be clicked?</a>
<h2 id="ft_what" class="fragment-target">What?</h2>
...
<h2 id="ft_when" class="fragment-target">When?</h2>

CSS

.fragment-target {
display: block;
margin-top: -HEADER_HEIGHTpx;
padding-top: HEADER_HEIGHTpx;
z-index: -1;
}

z-index: -1允许片段目标上方“填充区域”中的链接仍然是可点击的,正如@MuttenXd在他的回答中所评论的那样

我还没有在IE 11、Edge 15+、Chrome 38+、FF 52+或Safari 9.1+中发现问题

从2021年4月起,有一个非黑客的、完全跨浏览器的解决方案:

h1 {
scroll-margin-top: 50px
}

它是CSS滚动快照规格的一部分。运行在所有现代浏览器上。(有关更多上下文,请参阅有关scroll-margin-topscroll-padding-top的MDN页面)

html {
scroll-padding-top: 70px; /* height of sticky header */
}

来自:https://css-tricks.com/fixed-headers-on-page-links-and-overlapping-content-oh-my/

刚刚发现了另一个纯CSS解决方案,对我来说就像一个魅力!

html {
scroll-padding-top: 80px; /* height of your sticky header */
}

这个网站找到!

我认为这种方法更有用:

<h2 id="bar" title="Bar">Bar</h2>

[id]:target {
display: block;
position: relative;
top: -120px;
visibility: hidden;
}


[id]:target::before {
content: attr(title);
top: 120px;
position: relative;
visibility: visible;
}

你现在可以使用scroll-margin-top,也就是被广泛采用

只需将以下CSS添加到你想要滚动到的元素:

.element {
scroll-margin-top: 2em;
}

上面的答案创建了一个60px高的标签,屏蔽了其他因此停止工作的链接。我发现这个解决方案工作没有副作用。

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


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

我用anchor元素的scroll-margin-top属性解决了这个问题

scroll-margin-top: 100px;

https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-margin-top

我没有看到简单地使用:目标的选项被列为选项。我发现

:target { margin-top: -100px; padding-top: 100px; }

似乎在提供的场景中工作。:目标也兼容所有现代浏览器。https://caniuse.com/?search=%3Atarget