偏移 html 锚点以调整固定标题

发布于 2024-12-29 10:02:50 字数 157 浏览 3 评论 0原文

我正在努力清理我的锚点的工作方式。我有一个固定在页面顶部的标题,因此当您链接到页面中其他位置的锚点时,页面会跳转,因此锚点位于页面顶部,将内容留在固定标题后面(我希望这是有道理的)。我需要一种方法将锚点从标题高度偏移 25 像素。我更喜欢 HTML 或 CSS,但 Javascript 也可以接受。

I am trying to clean up the way my anchors work. I have a header that is fixed to the top of the page, so when you link to an anchor elsewhere in the page, the page jumps so the anchor is at the top of the page, leaving the content behind the fixed header (I hope that makes sense). I need a way to offset the anchor by the 25px from the height of the header. I would prefer HTML or CSS, but Javascript would be acceptable as well.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(28

狼性发作 2025-01-05 10:02:50

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

为您的锚点指定一个类:

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

然后,您可以通过将锚点设为块元素并相对定位它,将锚点定位在比其实际出现在页面上的位置更高或更低的偏移量。 -250px 会将锚点向上定位 250px

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

You could just use CSS without any javascript.

Give your anchor a class:

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

You can then position the anchor an offset higher or lower than where it actually appears on the page, by making it a block element and relatively positioning it. -250px will position the anchor up 250px

a.anchor {
    display: block;
    position: relative;
    top: -250px;
    visibility: hidden;
}
冬天旳寂寞 2025-01-05 10:02:50

我找到了这个解决方案:

<a name="myanchor">
    <h1 style="padding-top: 40px; margin-top: -40px;">My anchor</h1>
</a>

这不会在内容中造成任何间隙,并且锚链接效果非常好。

I found this solution:

<a name="myanchor">
    <h1 style="padding-top: 40px; margin-top: -40px;">My anchor</h1>
</a>

This doesn't create any gap in the content and anchor links works really nice.

挽心 2025-01-05 10:02:50

FWIW 这对我有用:

[id]::before {
  content: '';
  display: block;
  height:      75px;
  margin-top: -75px;
  visibility: hidden;
}

FWIW this worked for me:

[id]::before {
  content: '';
  display: block;
  height:      75px;
  margin-top: -75px;
  visibility: hidden;
}
才能让你更想念 2025-01-05 10:02:50

我也在寻找解决方案。就我而言,这很容易。

我有一个包含所有链接的列表菜单:

<ul>
<li><a href="#one">one</a></li>
<li><a href="#two">two</a></li>
<li><a href="#three">three</a></li>
<li><a href="#four">four</a></li>
</ul>

下面是它应该去的标题。

<h3>one</h3>
<p>text here</p>

<h3>two</h3>
<p>text here</p>

<h3>three</h3>
<p>text here</p>

<h3>four</h3>
<p>text here</p>

现在,因为我的页面顶部有一个固定菜单,所以我不能将其转到我的标签,因为它位于菜单后面。

相反,我在标签内放置了一个带有正确 ID 的 span 标签。

<h3><span id="one"></span>one</h3>

现在使用 2 行 CSS 来正确定位它们。

h3{ position:relative; }
h3 span{ position:absolute; top:-200px;}

更改顶部值以匹配固定标题的高度(或更高)。
现在我认为这也适用于其他元素。

I was looking for a solution to this as well. In my case, it was pretty easy.

I have a list menu with all the links:

<ul>
<li><a href="#one">one</a></li>
<li><a href="#two">two</a></li>
<li><a href="#three">three</a></li>
<li><a href="#four">four</a></li>
</ul>

And below that the headings where it should go to.

<h3>one</h3>
<p>text here</p>

<h3>two</h3>
<p>text here</p>

<h3>three</h3>
<p>text here</p>

<h3>four</h3>
<p>text here</p>

Now because I have a fixed menu at the top of my page I can't just make it go to my tag because that would be behind the menu.

Instead, I put a span tag inside my tag with the proper id.

<h3><span id="one"></span>one</h3>

Now use 2 lines of CSS to position them properly.

h3{ position:relative; }
h3 span{ position:absolute; top:-200px;}

Change the top value to match the height of your fixed header (or more).
Now I assume this would work with other elements as well.

场罚期间 2025-01-05 10:02:50

由于这是演示的问题,因此纯 CSS 解决方案将是理想的选择。然而,这个问题是在 2012 年提出的,尽管已经提出了相对定位/负边距解决方案,但这些方法看起来相当老套,会产生潜在的流程问题,并且无法动态响应 DOM/视口的变化。

考虑到这一点,我相信使用 JavaScript仍然(2017 年 2 月)最好的方法。下面是一个普通的 JS 解决方案,它将响应锚点点击并解析加载时的页面哈希(请参阅JSFiddle)。如果需要动态计算,请修改.getFixedOffset()方法。如果您使用 jQuery,这里有一个修改后的解决方案,具有更好的事件委托和平滑滚动

(function(document, history, location) {
  var HISTORY_SUPPORT = !!(history && history.pushState);

  var anchorScrolls = {
    ANCHOR_REGEX: /^#[^ ]+$/,
    OFFSET_HEIGHT_PX: 50,

    /**
     * Establish events, and fix initial scroll position if a hash is provided.
     */
    init: function() {
      this.scrollToCurrent();
      window.addEventListener('hashchange', this.scrollToCurrent.bind(this));
      document.body.addEventListener('click', this.delegateAnchors.bind(this));
    },

    /**
     * Return the offset amount to deduct from the normal scroll position.
     * Modify as appropriate to allow for dynamic calculations
     */
    getFixedOffset: function() {
      return this.OFFSET_HEIGHT_PX;
    },

    /**
     * If the provided href is an anchor which resolves to an element on the
     * page, scroll to it.
     * @param  {String} href
     * @return {Boolean} - Was the href an anchor.
     */
    scrollIfAnchor: function(href, pushToHistory) {
      var match, rect, anchorOffset;

      if(!this.ANCHOR_REGEX.test(href)) {
        return false;
      }

      match = document.getElementById(href.slice(1));

      if(match) {
        rect = match.getBoundingClientRect();
        anchorOffset = window.pageYOffset + rect.top - this.getFixedOffset();
        window.scrollTo(window.pageXOffset, anchorOffset);

        // Add the state to history as-per normal anchor links
        if(HISTORY_SUPPORT && pushToHistory) {
          history.pushState({}, document.title, location.pathname + href);
        }
      }

      return !!match;
    },

    /**
     * Attempt to scroll to the current location's hash.
     */
    scrollToCurrent: function() {
      this.scrollIfAnchor(window.location.hash);
    },

    /**
     * If the click event's target was an anchor, fix the scroll position.
     */
    delegateAnchors: function(e) {
      var elem = e.target;

      if(
        elem.nodeName === 'A' &&
        this.scrollIfAnchor(elem.getAttribute('href'), true)
      ) {
        e.preventDefault();
      }
    }
  };

  window.addEventListener(
    'DOMContentLoaded', anchorScrolls.init.bind(anchorScrolls)
  );
})(window.document, window.history, window.location);

As this is a concern of presentation, a pure CSS solution would be ideal. However, this question was posed in 2012, and although relative positioning / negative margin solutions have been suggested, these approaches seem rather hacky, create potential flow issues, and cannot respond dynamically to changes in the DOM / viewport.

With that in mind I believe that using JavaScript is still (February 2017) the best approach. Below is a vanilla-JS solution which will respond both to anchor clicks and resolve the page hash on load (See JSFiddle). Modify the .getFixedOffset() method if dynamic calculations are required. If you're using jQuery, here's a modified solution with better event delegation and smooth scrolling.

(function(document, history, location) {
  var HISTORY_SUPPORT = !!(history && history.pushState);

  var anchorScrolls = {
    ANCHOR_REGEX: /^#[^ ]+$/,
    OFFSET_HEIGHT_PX: 50,

    /**
     * Establish events, and fix initial scroll position if a hash is provided.
     */
    init: function() {
      this.scrollToCurrent();
      window.addEventListener('hashchange', this.scrollToCurrent.bind(this));
      document.body.addEventListener('click', this.delegateAnchors.bind(this));
    },

    /**
     * Return the offset amount to deduct from the normal scroll position.
     * Modify as appropriate to allow for dynamic calculations
     */
    getFixedOffset: function() {
      return this.OFFSET_HEIGHT_PX;
    },

    /**
     * If the provided href is an anchor which resolves to an element on the
     * page, scroll to it.
     * @param  {String} href
     * @return {Boolean} - Was the href an anchor.
     */
    scrollIfAnchor: function(href, pushToHistory) {
      var match, rect, anchorOffset;

      if(!this.ANCHOR_REGEX.test(href)) {
        return false;
      }

      match = document.getElementById(href.slice(1));

      if(match) {
        rect = match.getBoundingClientRect();
        anchorOffset = window.pageYOffset + rect.top - this.getFixedOffset();
        window.scrollTo(window.pageXOffset, anchorOffset);

        // Add the state to history as-per normal anchor links
        if(HISTORY_SUPPORT && pushToHistory) {
          history.pushState({}, document.title, location.pathname + href);
        }
      }

      return !!match;
    },

    /**
     * Attempt to scroll to the current location's hash.
     */
    scrollToCurrent: function() {
      this.scrollIfAnchor(window.location.hash);
    },

    /**
     * If the click event's target was an anchor, fix the scroll position.
     */
    delegateAnchors: function(e) {
      var elem = e.target;

      if(
        elem.nodeName === 'A' &&
        this.scrollIfAnchor(elem.getAttribute('href'), true)
      ) {
        e.preventDefault();
      }
    }
  };

  window.addEventListener(
    'DOMContentLoaded', anchorScrolls.init.bind(anchorScrolls)
  );
})(window.document, window.history, window.location);
╭ゆ眷念 2025-01-05 10:02:50

受 Alexander Savin 启发的纯 css 解决方案:

a[name] {
  padding-top: 40px;
  margin-top: -40px;
  display: inline-block; /* required for webkit browsers */
}

如果目标仍然在屏幕之外,您可能需要添加以下内容:

  vertical-align: top;

Pure css solution inspired by Alexander Savin:

a[name] {
  padding-top: 40px;
  margin-top: -40px;
  display: inline-block; /* required for webkit browsers */
}

Optionally you may want to add the following if the target is still off the screen:

  vertical-align: top;
凉城凉梦凉人心 2025-01-05 10:02:50

我的解决方案结合了 CMS 的目标选择器和之前选择器。其他技术不考虑锚点中的文本。将高度和负边距调整为您需要的偏移量...

:target::before {
    content: '';
    display: block;
    height:      180px;
    margin-top: -180px;
}

My solution combines the target and before selectors for our CMS. Other techniques don't account for text in the anchor. Adjust the height and the negative margin to the offset you need...

:target::before {
    content: '';
    display: block;
    height:      180px;
    margin-top: -180px;
}
夜空下最亮的亮点 2025-01-05 10:02:50

这从之前的答案中获取了许多元素,并组合成一个微小的(缩小为 194 字节)匿名 jQuery 函数。调整菜单或阻塞元素的fixedElementHeight高度。

    (function($, window) {
        var adjustAnchor = function() {

            var $anchor = $(':target'),
                    fixedElementHeight = 100;

            if ($anchor.length > 0) {

                $('html, body')
                    .stop()
                    .animate({
                        scrollTop: $anchor.offset().top - fixedElementHeight
                    }, 200);

            }

        };

        $(window).on('hashchange load', function() {
            adjustAnchor();
        });

    })(jQuery, window);

如果您不喜欢动画,请替换

$('html, body')
     .stop()
     .animate({
         scrollTop: $anchor.offset().top - fixedElementHeight
     }, 200);

为:

window.scrollTo(0, $anchor.offset().top - fixedElementHeight);

丑化版本:

 !function(o,n){var t=function(){var n=o(":target"),t=100;n.length>0&&o("html, body").stop().animate({scrollTop:n.offset().top-t},200)};o(n).on("hashchange load",function(){t()})}(jQuery,window);

This takes many elements from previous answers and combines into a tiny (194 bytes minified) anonymous jQuery function. Adjust fixedElementHeight for the height of your menu or blocking element.

    (function($, window) {
        var adjustAnchor = function() {

            var $anchor = $(':target'),
                    fixedElementHeight = 100;

            if ($anchor.length > 0) {

                $('html, body')
                    .stop()
                    .animate({
                        scrollTop: $anchor.offset().top - fixedElementHeight
                    }, 200);

            }

        };

        $(window).on('hashchange load', function() {
            adjustAnchor();
        });

    })(jQuery, window);

If you don't like the animation, replace

$('html, body')
     .stop()
     .animate({
         scrollTop: $anchor.offset().top - fixedElementHeight
     }, 200);

with:

window.scrollTo(0, $anchor.offset().top - fixedElementHeight);

Uglified version:

 !function(o,n){var t=function(){var n=o(":target"),t=100;n.length>0&&o("html, body").stop().animate({scrollTop:n.offset().top-t},200)};o(n).on("hashchange load",function(){t()})}(jQuery,window);
反话 2025-01-05 10:02:50

对于现代浏览器,只需将 CSS3 :target 选择器添加到页面即可。这将自动应用于所有锚点。

:target {
    display: block;    
    position: relative;     
    top: -100px;
    visibility: hidden;
}

For modern browsers, just add the CSS3 :target selector to the page. This will apply to all the anchors automatically.

:target {
    display: block;    
    position: relative;     
    top: -100px;
    visibility: hidden;
}
入画浅相思 2025-01-05 10:02:50

不用js也不用修改html就可以做到。它仅适用于 CSS。

a[id]::before {
    content: '';
    display: block;
    height: 50px;
    margin: -30px 0 0;
}

这将在每个带有 id 的 a 标签之前附加一个伪元素。调整值以匹配标题的高度。

You can do it without js and without altering html. It´s css-only.

a[id]::before {
    content: '';
    display: block;
    height: 50px;
    margin: -30px 0 0;
}

That will append a pseudo-element before every a-tag with an id. Adjust values to match the height of your header.

茶色山野 2025-01-05 10:02:50

我也遇到过类似的问题,不幸的是,在实施上述所有解决方案后,我得出了以下结论。

  1. 我的内部元素具有脆弱的 CSS 结构,并实现相对/绝对位置播放,完全破坏了页面设计。
  2. CSS 不是我的强项。

我编写了这个简单的滚动 js,它解决了由于标题而导致的偏移,并将 div 重新定位在下方约 125 像素处。请根据您的需要使用它。

HTML

<div id="#anchor"></div> <!-- #anchor here is the anchor tag which is on your URL -->

JavaScript

 $(function() {
  $('a[href*=#]:not([href=#])').click(function() {
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') 
&& location.hostname == this.hostname) {

      var target = $(this.hash);
      target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
      if (target.length) {
        $('html,body').animate({
          scrollTop: target.offset().top - 125 //offsets for fixed header
        }, 1000);
        return false;
      }
    }
  });
  //Executed on page load with URL containing an anchor tag.
  if($(location.href.split("#")[1])) {
      var target = $('#'+location.href.split("#")[1]);
      if (target.length) {
        $('html,body').animate({
          scrollTop: target.offset().top - 125 //offset height of header here too.
        }, 1000);
        return false;
      }
    }
});

请参阅此处的实时实现

I had been facing a similar issue, unfortunately after implementing all the solutions above, I came to the following conclusion.

  1. My inner elements had a fragile CSS structure and implementing a position relative / absolute play, was completely breaking the page design.
  2. CSS is not my strong suit.

I wrote this simple scrolling js, that accounts for the offset caused due to the header and relocated the div about 125 pixels below. Please use it as you see fit.

The HTML

<div id="#anchor"></div> <!-- #anchor here is the anchor tag which is on your URL -->

The JavaScript

 $(function() {
  $('a[href*=#]:not([href=#])').click(function() {
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') 
&& location.hostname == this.hostname) {

      var target = $(this.hash);
      target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
      if (target.length) {
        $('html,body').animate({
          scrollTop: target.offset().top - 125 //offsets for fixed header
        }, 1000);
        return false;
      }
    }
  });
  //Executed on page load with URL containing an anchor tag.
  if($(location.href.split("#")[1])) {
      var target = $('#'+location.href.split("#")[1]);
      if (target.length) {
        $('html,body').animate({
          scrollTop: target.offset().top - 125 //offset height of header here too.
        }, 1000);
        return false;
      }
    }
});

See a live implementation here.

风流物 2025-01-05 10:02:50

对于同样的问题,我使用了一个简单的解决方案:在每个锚点上放置 40px 的 padding-top 。

For the same issue, I used an easy solution : put a padding-top of 40px on each anchor.

一梦等七年七年为一梦 2025-01-05 10:02:50

正如 @moeffju 所建议的,这可以通过 CSS 实现。我遇到的问题(令我惊讶的是我没有看到讨论)是用填充或透明边框重叠先前元素的技巧,以防止这些部分底部的悬停和单击操作,因为下面的元素在z 顺序。

我发现的最佳解决方案是将部分内容放置在 z-index: 1 处的 div 中:

// Apply to elements that serve as anchors
.offset-anchor {
  border-top: 75px solid transparent;
  margin: -75px 0 0;
  -webkit-background-clip: padding-box;
  -moz-background-clip: padding;
  background-clip: padding-box;
}

// Because offset-anchor causes sections to overlap the bottom of previous ones,
// we need to put content higher so links aren't blocked by the transparent border.
.container {
  position: relative;
  z-index: 1;
}

As @moeffju suggests, this can be achieved with CSS. The issue I ran into (which I'm surprised I haven't seen discussed) is the trick of overlapping previous elements with padding or a transparent border prevents hover and click actions at the bottom of those sections because the following one comes higher in the z-order.

The best fix I found was to place section content in a div that is at z-index: 1:

// Apply to elements that serve as anchors
.offset-anchor {
  border-top: 75px solid transparent;
  margin: -75px 0 0;
  -webkit-background-clip: padding-box;
  -moz-background-clip: padding;
  background-clip: padding-box;
}

// Because offset-anchor causes sections to overlap the bottom of previous ones,
// we need to put content higher so links aren't blocked by the transparent border.
.container {
  position: relative;
  z-index: 1;
}
铜锣湾横着走 2025-01-05 10:02:50

更改位置属性的解决方案并不总是可行(它可能会破坏布局),因此我建议这样做:

HTML:

<a id="top">Anchor</a>

CSS:

#top {
    margin-top: -250px;
    padding-top: 250px;
}

使用此:

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

最大限度地减少重叠,并将字体大小设置为 1px。空锚点在某些浏览器中不起作用。

Solutions with changing position property are not always possible (it can destroy layout) therefore I suggest this:

HTML:

<a id="top">Anchor</a>

CSS:

#top {
    margin-top: -250px;
    padding-top: 250px;
}

Use this:

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

to minimize overlapping, and set font-size to 1px. Empty anchor will not work in some browsers.

慕巷 2025-01-05 10:02:50

借用此链接给出的答案中的一些代码(未指定作者),您可以为锚点添加一个漂亮的平滑滚动效果,同时使其停在锚点上方 -60px 处,很好地适合固定引导导航栏下方(需要 jQuery):

$(".dropdown-menu a[href^='#']").on('click', function(e) {
   // prevent default anchor click behavior
   e.preventDefault();

   // animate
   $('html, body').animate({
       scrollTop: $(this.hash).offset().top - 60
     }, 300, function(){
     });
});

Borrowing some of the code from an answer given at this link (no author is specified), you can include a nice smooth-scroll effect to the anchor, while making it stop at -60px above the anchor, fitting nicely underneath the fixed bootstrap navigation bar (requires jQuery):

$(".dropdown-menu a[href^='#']").on('click', function(e) {
   // prevent default anchor click behavior
   e.preventDefault();

   // animate
   $('html, body').animate({
       scrollTop: $(this.hash).offset().top - 60
     }, 300, function(){
     });
});
遇见了你 2025-01-05 10:02:50

不要使用与页面其余内容重叠的固定位置导航栏(整个页面主体可滚动),而是考虑使用带有静态导航栏的不可滚动主体,然后将页面内容放在下面绝对定位的可滚动 div。

也就是说,具有这样的 HTML...

<div class="static-navbar">NAVBAR</div>
<div class="scrollable-content">
  <p>Bla bla bla</p>
  <p>Yadda yadda yadda</p>
  <p>Mary had a little lamb</p>
  <h2 id="stuff-i-want-to-link-to">Stuff</h2>
  <p>More nonsense</p>
</div>

... 和这样的 CSS:

.static-navbar {
  height: 100px;
}
.scrollable-content {
  position: absolute;
  top: 100px;
  bottom: 0;
  overflow-y: scroll;
  width: 100%;
}

然而,这种方法有一个显着的缺点,即当页面标题中的元素获得焦点时,用户将无法滚动使用键盘翻页(例如,通过向上和向下箭头或 Page Up 和 Page Down 键)。

这是一个 JSFiddle 演示了这一点。

Instead of having a fixed-position navbar which is underlapped by the rest of the content of the page (with the whole page body being scrollable), consider instead having a non-scrollable body with a static navbar and then having the page content in an absolutely-positioned scrollable div below.

That is, have HTML like this...

<div class="static-navbar">NAVBAR</div>
<div class="scrollable-content">
  <p>Bla bla bla</p>
  <p>Yadda yadda yadda</p>
  <p>Mary had a little lamb</p>
  <h2 id="stuff-i-want-to-link-to">Stuff</h2>
  <p>More nonsense</p>
</div>

... and CSS like this:

.static-navbar {
  height: 100px;
}
.scrollable-content {
  position: absolute;
  top: 100px;
  bottom: 0;
  overflow-y: scroll;
  width: 100%;
}

There is one significant downside to this approach, however, which is that while an element from the page header is focused, the user will not be able to scroll the page using the keyboard (e.g. via the up and down arrows or the Page Up and Page Down keys).

Here's a JSFiddle demonstrating this in action.

被翻牌 2025-01-05 10:02:50

如果您的锚点是表格元素或在表格(行或单元格)内,则上述方法效果不佳。

我必须使用 javascript 并绑定到窗口 hashchange 事件来解决此问题(demo< /a>):

function moveUnderNav() {
    var $el, h = window.location.hash;
    if (h) {
        $el = $(h);
        if ($el.length && $el.closest('table').length) {
            $('body').scrollTop( $el.closest('table, tr').position().top - 26 );
        }
    }
}

$(window)
    .load(function () {
        moveUnderNav();
    })
    .on('hashchange', function () {
        moveUnderNav();
    });

* 注意: hashchange 事件并非在所有浏览器中都可用。

The above methods don't work very well if your anchor is a table element or within a table (row or cell).

I had to use javascript and bind to the window hashchange event to work around this (demo):

function moveUnderNav() {
    var $el, h = window.location.hash;
    if (h) {
        $el = $(h);
        if ($el.length && $el.closest('table').length) {
            $('body').scrollTop( $el.closest('table, tr').position().top - 26 );
        }
    }
}

$(window)
    .load(function () {
        moveUnderNav();
    })
    .on('hashchange', function () {
        moveUnderNav();
    });

* Note: The hashchange event is not available in all browsers.

已下线请稍等 2025-01-05 10:02:50

您可以使用 a[name]:not([href]) css 选择器在没有 ID 的情况下实现此目的。这只是查找具有名称但没有 href 的链接,例如

示例规则可能是:

a[name]:not([href]){
    display: block;    
    position: relative;     
    top: -100px;
    visibility: hidden;
}

You can achieve this without an ID using the a[name]:not([href]) css selector. This simply looks for links with a name and no href e.g. <a name="anc1"></a>

An example rule might be:

a[name]:not([href]){
    display: block;    
    position: relative;     
    top: -100px;
    visibility: hidden;
}
暮年 2025-01-05 10:02:50

这是受到 Shouvik 答案的启发 - 与他的概念相同,只是固定标头的大小没有被硬编码。只要您的固定标头位于第一个标头节点中,这应该“正常工作”

/*jslint browser: true, plusplus: true, regexp: true */

function anchorScroll(fragment) {
    "use strict";
    var amount, ttarget;
    amount = $('header').height();
    ttarget = $('#' + fragment);
    $('html,body').animate({ scrollTop: ttarget.offset().top - amount }, 250);
    return false;
}

function outsideToHash() {
    "use strict";
    var fragment;
    if (window.location.hash) {
        fragment = window.location.hash.substring(1);
        anchorScroll(fragment);
    }
}

function insideToHash(nnode) {
    "use strict";
    var fragment;
    fragment = $(nnode).attr('href').substring(1);
    anchorScroll(fragment);
}

$(document).ready(function () {
    "use strict";
    $("a[href^='#']").bind('click',  function () {insideToHash(this); });
    outsideToHash();
});

This was inspired by the answer by Shouvik - same concept as his, only the size of the fixed header isn't hard coded. As long as your fixed header is in the first header node, this should "just work"

/*jslint browser: true, plusplus: true, regexp: true */

function anchorScroll(fragment) {
    "use strict";
    var amount, ttarget;
    amount = $('header').height();
    ttarget = $('#' + fragment);
    $('html,body').animate({ scrollTop: ttarget.offset().top - amount }, 250);
    return false;
}

function outsideToHash() {
    "use strict";
    var fragment;
    if (window.location.hash) {
        fragment = window.location.hash.substring(1);
        anchorScroll(fragment);
    }
}

function insideToHash(nnode) {
    "use strict";
    var fragment;
    fragment = $(nnode).attr('href').substring(1);
    anchorScroll(fragment);
}

$(document).ready(function () {
    "use strict";
    $("a[href^='#']").bind('click',  function () {insideToHash(this); });
    outsideToHash();
});
挽清梦 2025-01-05 10:02:50

我在 TYPO3 网站中面临这个问题,其中所有“内容元素”都用类似以下内容的内容包裹:

<div id="c1234" class="contentElement">...</div>

我更改了渲染,使其呈现如下所示:

<div id="c1234" class="anchor"></div>
<div class="contentElement">...</div>

这个 CSS:

.anchor{
    position: relative;
    top: -50px;
}

固定顶栏高 40 像素,现在锚点再次工作并从顶栏下方 10px 开始。

这种技术的唯一缺点是您不能再使用 :target

I'm facing this problem in a TYPO3 website, where all "Content Elements" are wrapped with something like:

<div id="c1234" class="contentElement">...</div>

and i changed the rendering so it renders like this:

<div id="c1234" class="anchor"></div>
<div class="contentElement">...</div>

And this CSS:

.anchor{
    position: relative;
    top: -50px;
}

The fixed topbar being 40px high, now the anchors work again and start 10px under the topbar.

Only drawback of this technique is you can no longer use :target.

定格我的天空 2025-01-05 10:02:50

添加到 Ziav 的答案(感谢 Alexander Savin),我需要使用老式的 ... 因为我们在我们的代码中将

...

用于其他目的。我在使用 display: inline-block 时遇到了一些显示问题——每个

元素的第一行都稍微右缩进(在 Webkit 上)和火狐浏览器)。我最终尝试了其他 display 值,并且 display: table-caption 非常适合我。

.anchor {
  padding-top: 60px;
  margin-top: -60px;
  display: table-caption;
}

Adding to Ziav's answer (with thanks to Alexander Savin), I need to be using the old-school <a name="...">...</a> as we're using <div id="...">...</div> for another purpose in our code. I had some display issues using display: inline-block -- the first line of every <p> element was turning out to be slightly right-indented (on both Webkit and Firefox browsers). I ended up trying other display values and display: table-caption works perfectly for me.

.anchor {
  padding-top: 60px;
  margin-top: -60px;
  display: table-caption;
}
恋竹姑娘 2025-01-05 10:02:50

我在每个 h1 元素之前添加了 40px 高度的 .vspace 元素来固定锚点。

<div class="vspace" id="gherkin"></div>
<div class="page-header">
  <h1>Gherkin</h1>
</div>

在 CSS 中:

.vspace { height: 40px;}

效果很好,空间也不拥挤。

I added 40px-height .vspace element holding the anchor before each of my h1 elements.

<div class="vspace" id="gherkin"></div>
<div class="page-header">
  <h1>Gherkin</h1>
</div>

In the CSS:

.vspace { height: 40px;}

It's working great and the space is not chocking.

老旧海报 2025-01-05 10:02:50

带有可链接ID的隐藏span标签提供导航栏的高度怎么样:

#head1 {
  padding-top: 60px;
  height: 0px;
  visibility: hidden;
}


<span class="head1">somecontent</span>
<h5 id="headline1">This Headline is not obscured</h5>

这是小提琴: http://jsfiddle.net /N6f2f/7

how about hidden span tags with linkable IDs that provide the height of the navbar:

#head1 {
  padding-top: 60px;
  height: 0px;
  visibility: hidden;
}


<span class="head1">somecontent</span>
<h5 id="headline1">This Headline is not obscured</h5>

heres the fiddle: http://jsfiddle.net/N6f2f/7

只想待在家 2025-01-05 10:02:50

您还可以使用 follow attr: 添加锚点

(text-indent:-99999px;)
visibility: hidden;
position:absolute;
top:-80px;    

,并为父容器提供相对位置。

非常适合我。

You can also add an anchor with follow attr:

(text-indent:-99999px;)
visibility: hidden;
position:absolute;
top:-80px;    

and give the parent container a position relative.

Works perfect for me.

三五鸿雁 2025-01-05 10:02:50

对 @Jan 的出色答案的进一步转变是将其合并到 #uberbar 固定标头中,该标头使用 jQuery(或 MooTools)。 (http://davidwalsh.name/persistent-header-opacity

我调整了代码因此内容的顶部始终位于固定标题下方,而不是固定标题下方,并且再次添加了 @Jan 的锚点,确保锚点始终位于固定标题下方。

CSS:

#uberbar { 
    border-bottom:1px solid #0000cc; 
    position:fixed; 
    top:0; 
    left:0; 
    z-index:2000; 
    width:100%;
}

a.anchor {
    display: block;
    position: relative;
    visibility: hidden;
}

jQuery(包括对 #uberbar 和锚点方法的调整:

<script type="text/javascript">
$(document).ready(function() {
    (function() {
        //settings
        var fadeSpeed = 200, fadeTo = 0.85, topDistance = 30;
        var topbarME = function() { $('#uberbar').fadeTo(fadeSpeed,1); }, topbarML = function() { $('#uberbar').fadeTo(fadeSpeed,fadeTo); };
        var inside = false;
        //do
        $(window).scroll(function() {
            position = $(window).scrollTop();
            if(position > topDistance && !inside) {
                //add events
                topbarML();
                $('#uberbar').bind('mouseenter',topbarME);
                $('#uberbar').bind('mouseleave',topbarML);
                inside = true;
            }
            else if (position < topDistance){
                topbarME();
                $('#uberbar').unbind('mouseenter',topbarME);
                $('#uberbar').unbind('mouseleave',topbarML);
                inside = false;
            }
        });
        $('#content').css({'margin-top': $('#uberbar').outerHeight(true)});
        $('a.anchor').css({'top': - $('#uberbar').outerHeight(true)});
    })();
});
</script>

最后是 HTML:

<div id="uberbar">
    <!--CONTENT OF FIXED HEADER-->
</div>
....
<div id="content">
    <!--MAIN CONTENT-->
    ....
    <a class="anchor" id="anchor1"></a>
    ....
    <a class="anchor" id="anchor2"></a>
    ....
</div>

也许这对喜欢 #uberbar 淡入淡出的 Dixed 标题的人有用!

A further twist to the excellent answer from @Jan is to incorporate this into the #uberbar fixed header, which uses jQuery (or MooTools). (http://davidwalsh.name/persistent-header-opacity)

I've tweaked the code so the the top of the content is always below not under the fixed header and also added the anchors from @Jan again making sure that the anchors are always positioned below the fixed header.

The CSS:

#uberbar { 
    border-bottom:1px solid #0000cc; 
    position:fixed; 
    top:0; 
    left:0; 
    z-index:2000; 
    width:100%;
}

a.anchor {
    display: block;
    position: relative;
    visibility: hidden;
}

The jQuery (including tweaks to both the #uberbar and the anchor approaches:

<script type="text/javascript">
$(document).ready(function() {
    (function() {
        //settings
        var fadeSpeed = 200, fadeTo = 0.85, topDistance = 30;
        var topbarME = function() { $('#uberbar').fadeTo(fadeSpeed,1); }, topbarML = function() { $('#uberbar').fadeTo(fadeSpeed,fadeTo); };
        var inside = false;
        //do
        $(window).scroll(function() {
            position = $(window).scrollTop();
            if(position > topDistance && !inside) {
                //add events
                topbarML();
                $('#uberbar').bind('mouseenter',topbarME);
                $('#uberbar').bind('mouseleave',topbarML);
                inside = true;
            }
            else if (position < topDistance){
                topbarME();
                $('#uberbar').unbind('mouseenter',topbarME);
                $('#uberbar').unbind('mouseleave',topbarML);
                inside = false;
            }
        });
        $('#content').css({'margin-top': $('#uberbar').outerHeight(true)});
        $('a.anchor').css({'top': - $('#uberbar').outerHeight(true)});
    })();
});
</script>

And finally the HTML:

<div id="uberbar">
    <!--CONTENT OF FIXED HEADER-->
</div>
....
<div id="content">
    <!--MAIN CONTENT-->
    ....
    <a class="anchor" id="anchor1"></a>
    ....
    <a class="anchor" id="anchor2"></a>
    ....
</div>

Maybe this is useful to somebody who likes the #uberbar fading dixed header!

耳根太软 2025-01-05 10:02:50

@AlexanderSavin 的解决方案在 WebKit 浏览器中对我来说效果很好。

我还必须使用 :target 伪类,它将样式应用于选定的锚点来调整 FFOpera 中的填充IE9

a:target {
  padding-top: 40px
}

请注意,此样式不适用于 Chrome / Safari,因此您可能必须使用 css-hacks、条件注释等等。

此外,我还想指出,Alexander 的解决方案之所以有效,是因为目标元素是内联。如果您不需要链接,只需更改 display 属性即可:

<div id="myanchor" style="display: inline">
   <h1 style="padding-top: 40px; margin-top: -40px;">My anchor</h1>
</div>

@AlexanderSavin's solution works great in WebKit browsers for me.

I additionally had to use :target pseudo-class which applies style to the selected anchor to adjust padding in FF, Opera & IE9:

a:target {
  padding-top: 40px
}

Note that this style is not for Chrome / Safari so you'll probably have to use css-hacks, conditional comments etc.

Also I'd like to notice that Alexander's solution works due to the fact that targeted element is inline. If you don't want link you could simply change display property:

<div id="myanchor" style="display: inline">
   <h1 style="padding-top: 40px; margin-top: -40px;">My anchor</h1>
</div>
就是爱搞怪 2025-01-05 10:02:50

这是我们在网站上使用的解决方案。将 headerHeight 变量调整为标题高度。将 js-scroll 类添加到应在单击时滚动的锚点。

// SCROLL ON CLICK
// ---------------------------------------------------------------------
$('.js-scroll').click(function(){
    var headerHeight = 60;

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

Here's the solution that we use on our site. Adjust the headerHeight variable to whatever your header height is. Add the js-scroll class to the anchor that should scroll on click.

// SCROLL ON CLICK
// ---------------------------------------------------------------------
$('.js-scroll').click(function(){
    var headerHeight = 60;

    $('html, body').animate({
        scrollTop: $( $.attr(this, 'href') ).offset().top - headerHeight;
    }, 500);
    return false;
});
柠檬色的秋千 2025-01-05 10:02:50

我遇到了同样的问题,最终手动处理点击事件,例如:

$('#mynav a').click(() ->
  $('html, body').animate({
      scrollTop: $($(this).attr('href')).offset().top - 40
  }, 200
  return false
)

滚动动画当然是可选的。

I ran into this same issue and ended up handling the click events manually, like:

$('#mynav a').click(() ->
  $('html, body').animate({
      scrollTop: $($(this).attr('href')).offset().top - 40
  }, 200
  return false
)

Scroll animation optional, of course.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文