固定页眉与页内锚点重叠

时间:2010-11-03 10:31:11

标签: html url anchor fragment

如果HTML页面中有非滚动页眉,则固定在顶部,具有已定义的高度:

有没有办法使用网址锚点(#fragment部分)让浏览器滚动到页面中的某个点,但仍然尊重固定元素的高度没有帮助的JavaScript

http://foo.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    |
| ...                             |      | ...                             |
+---------------------------------+      +---------------------------------+

37 个答案:

答案 0 :(得分:202)

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

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

答案 1 :(得分:126)

我遇到了同样的问题。 我通过向anchor元素添加一个类来解决它,topbar height作为padding-top值。

<h1><a class="anchor" name="barlink">Bar</a></h1>

然后简单地说css:

.anchor { padding-top: 90px; }

答案 2 :(得分:114)

我使用这种方法:

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

答案 3 :(得分:33)

官方Bootstrap采纳的答案:

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

Credits

Merge

答案 4 :(得分:25)

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

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

如果您不想使用target选择器,也可以这样做:

.my-target {
    padding-top: 65px;
    margin-top: -65px;
}

注意:如果目标元素的背景颜色与其父元素不同,则此示例将不起作用。 例如:

<div style="background-color:red;height:100px;"></div>
<div class="my-target" style="background-color:green;height:100px;"></div>

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

答案 5 :(得分:13)

虽然一些建议的解决方案适用于片段链接(=哈希链接)同一页面(如向下滚动的菜单链接),但我发现它们在当前的Chrome中都不起作用你想使用来自其他网页的中的片段链接

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

还有jQuery bug report描述了问题的一些细节。

<强>解

我发现到目前为止唯一可以在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。

答案 6 :(得分:10)

您现在可以使用scroll-margin-top,即pretty widely adopted

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

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

答案 7 :(得分:8)

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

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

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

答案 8 :(得分:6)

您可以使用jQuery执行此操作:

var offset = $('.target').offset();
var scrollto = offset.top - 50; // fixed_top_bar_height = 50px
$('html, body').animate({scrollTop:scrollto}, 0);

答案 9 :(得分:5)

你可以试试这个:

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

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

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

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

答案 10 :(得分:5)

它对我有用:

HTML LINK to Anchor:

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

HTML主播:

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

CSS:

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

答案 11 :(得分:4)

我使用CSS和HTML轻松使用上面提到的“anchor:before”方法。我认为它是最好的,因为它不会在你的div之间创建大量的填充。

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

答案 12 :(得分:3)

我发现最干净的方式是:

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

答案 13 :(得分:3)

在这里和其他地方,我在很多答案上都遇到了麻烦,因为我标记为书签的锚点是FAQ页面中的节标题,因此抵消标题无济于事,因为其余内容只会保留在原处。所以我以为会发表。

我最终要做的是将一些解决方案综合在一起:

  1. CSS:

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

其中“ 120px”是您固定的页眉高度(可能加上一些边距)。

  1. 书签链接HTML:

    <a href="#01">What is your FAQ question again?</a>
    
  2. 已添加书签的内容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>
    

此解决方案的优点是span元素不仅被隐藏,而且实际上已折叠并且不会填充您的内容。

由于该解决方案来自大量不同的资源,因此我对此不抱以太多的信任,但是在我所处的情况下,它最适合我。

您可以看到实际结果here

答案 14 :(得分:3)

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

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

答案 15 :(得分:3)

我正在使用@ Jpsy的答案,但出于性能原因,我只是在URL中存在哈希时才设置计时器。

select field1, field2, cast(field3 as date) as fieldDate FROM table

答案 16 :(得分:3)

我发现我必须同时使用 MutttenXd Badabam 的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>
...

答案 17 :(得分:3)

对于我的纯粹主义思想感觉有点笨拙,但作为一个仅限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>

答案 18 :(得分:2)

我需要一些适用于入站链接,页面上的链接并且可以被JS定位的东西,以便页面可以响应页眉高度的变化

HTML

<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+中发现问题

答案 19 :(得分:2)

我对上面列出的答案一无所获,最终使用了效果很好的解决方案...

在您要设置锚点的位置创建一个空白跨度。

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

即使各节的背景颜色不同,此解决方案也将有效!我在this link.

找到了解决方案

答案 20 :(得分:2)

刚刚发现了另一个纯粹的CSS解决方案,对我来说就像一个咒语!

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

this site上找到!

答案 21 :(得分:2)

使用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,但the other more popular question因为这个问题而被关闭,我无法在那里回答。

答案 22 :(得分:2)

我使用锚元素的 scroll-margin-top 属性解决了我的问题

scroll-margin-top: 100px;

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

答案 23 :(得分:1)

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

var offset = 90;

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

答案 24 :(得分:1)

使用:before实现了很好的工作,直到我们意识到伪元素实际上覆盖并阻止了伪元素区域内的指针事件。 <{1}}上的pointer-events: none甚至是锚点上的:before之类的东西没有任何影响。

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

不阻止指针事件的偏移锚点

.section-marker {

    position: absolute;
    top: -300px;
}

这个值是我们不会阻止任何可能属于这些300px的元素。缺点是从Javascript中获取该元素的位置需要考虑该偏移,因此必须调整任何逻辑。

答案 25 :(得分:1)

我创建了一个带有几个换行符的div并给出了id,然后将要显示的代码放在下面。然后,该链接会将您带到图片上方的空间,并且标题将不再碍事:

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

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

答案 26 :(得分:1)

使用了此脚本

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

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

答案 27 :(得分:1)

随着CSS Scroll Snap spec进入游戏,使用scroll-margin-top属性很容易实现。目前在Chrome和Opera上运行(2019年4月)。 Safari 11+也应该支持此功能,但是我无法在Safari 11上运行它。可能我们必须等待其他人在那里修复它。

Codepen example

body {
  padding: 0;
  margin: 0;
}

h1,
p {
  max-width: 40rem;
  margin-left: auto;
  margin-right: auto;
}
h1 {
  scroll-margin-top: 6rem; /* One line solution. :-) */
}
.header {
  position: sticky;
  top: 0;
  background-color: red;
  text-align: center;
  padding: 1rem;
}
.header .scroll {
  display: block;
  color: white;
  margin-bottom: 0.5rem;
}
.header .browsers {
  color: black;
  font-size: 0.8em;
}
<header class="header">
  <a class="scroll" href="#heading">Scroll to heading</a>
  <span class="browsers" >Chrome 69+, Opera 56+ and Safari 11+ only</span>
</header>
<p>
  Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
</p>
<h1 id="heading">What is Lorem Ipsum?</h1>
<p>
  Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
</p>
<p>
  

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent pulvinar eleifend dolor, in cursus augue interdum quis. Morbi volutpat pulvinar nisl et condimentum. Quisque elit lacus, egestas non ante sit amet, hendrerit commodo dui. Nunc ac sagittis dolor. Proin iaculis ante non est pharetra, et ullamcorper nisl accumsan. Aenean quis leo vel sapien eleifend aliquam. Pellentesque finibus dui ex, blandit tristique risus vestibulum vitae. Nam a quam ac turpis porta eleifend. Sed at hendrerit risus, ac efficitur ante. Aenean pretium justo feugiat condimentum consectetur. Etiam mattis urna id porta hendrerit.
</p>
<p>
Mauris venenatis quam sed egestas auctor. Fusce lacus eros, condimentum nec quam vel, malesuada gravida libero. Praesent vel sollicitudin justo. Donec mattis nisl id mauris scelerisque, quis placerat lectus scelerisque. Ut id justo a magna mattis luctus. Suspendisse massa est, pretium vel suscipit sit amet, iaculis at mi. Aenean vulputate ipsum non consectetur sodales. Proin aliquet erat nec mi eleifend, eu dapibus enim ultrices. Sed fringilla tortor ac rhoncus consectetur. Aliquam aliquam orci ultrices tortor bibendum facilisis.
</p>
<p>
Donec ultrices diam quam, non tincidunt purus scelerisque aliquam. Nam pretium interdum lacinia. Donec sit amet diam odio. Donec eleifend nibh ut arcu dictum, in vulputate magna malesuada. Nam id dignissim tortor. Suspendisse commodo, nunc sit amet blandit laoreet, turpis nibh rhoncus mi, et finibus nisi diam sed erat. Vivamus diam arcu, placerat in ultrices eu, porta ut tellus. Aliquam vel nisi nisi.
</p>
<p>
Integer ornare finibus sem, eget vulputate lacus ultrices ac. Vivamus aliquam arcu sit amet urna facilisis consectetur. Sed molestie dolor et tortor elementum, nec bibendum tortor cursus. Nulla ipsum nulla, luctus nec fringilla id, sagittis et sem. Etiam at dolor in libero pharetra consequat. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Suspendisse quis turpis non diam mattis varius. Praesent at gravida mi. Etiam suscipit blandit dolor, nec convallis lectus mattis vitae. Mauris placerat erat ipsum, vitae interdum mauris consequat quis. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</p>
<p>
Nunc efficitur scelerisque elit. Integer ac massa ipsum. Cras volutpat nulla purus, quis molestie dolor iaculis eget. Maecenas ut ex nulla. Pellentesque sem augue, ornare ut arcu eu, porttitor consectetur orci. Aenean iaculis blandit quam, in efficitur justo sodales auctor. Vivamus dignissim pellentesque risus eget consequat. Pellentesque sit amet nisi in urna convallis egestas vitae nec mauris. 
</p>

答案 28 :(得分:1)

我认为这种方法更有用:

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

答案 29 :(得分:1)

这是一个完整的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) {

    });
}

答案 30 :(得分:1)

<div style="position:relative; top:-45px;">
    <a name="fragment"> </a>
</div>

这段代码可以解决问题。将标题栏的高度换成45像素。

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

答案 31 :(得分:0)

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

alert()

第一个样式调节所有锚标签,其中第二个样式使用超链接锚定标签。

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

答案 32 :(得分:0)

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

请参阅https://codepen.io/pikeshmn/pen/mMxEdZ

方法:我们使用 document.getElementById(&#39;标题&#39;)获取固定导航的高度.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;
  });

P.S:

  • 它包含标题和目标之间的5个像素差异
  • 滚动效果并不难,相当顺畅;平滑滚动

答案 33 :(得分:0)

我使用这种方法是因为出于某种原因,所提出的其他解决方案都没有真正为我工作。我保证我试过了。

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

如果您愿意,可以按类替换部分

来源:Jump links and viewport positioning

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

对于那些不相信我的人,我慷慨地准备了一个解决方案:SOLUTION

答案 34 :(得分:0)

// handle hashes when page loads
// <http://stackoverflow.com/a/29853395>
function adjustAnchor() {
  const $anchor = $(':target');
  const fixedElementHeight = $('.navbar-fixed-top').outerHeight();
  if ($anchor.length > 0)
    window.scrollTo(0, $anchor.offset().top - fixedElementHeight);
}
$(window).on('hashchange load', adjustAnchor);
$('body').on('click', "a[href^='#']", function (ev) {
  if (window.location.hash === $(this).attr('href')) {
    ev.preventDefault();
    adjustAnchor();
  }
});

答案 35 :(得分:0)

使用&#34; paddingtop&#34;添加一个类所以它有效;)

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

对于css你有:

.paddingtop { 
   padding-top: 90px; 
}

答案 36 :(得分:-1)

此处的最高答案是创建了一个60px高的标记,该标记掩盖了因此而停止工作的其他链接。我发现this solution没有副作用。

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

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