抵消一个html锚来调整固定的标题

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

817558 次浏览

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

我找到了这个解决方案:

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

这不会在内容和锚点链接中产生任何差距,效果非常好。

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

我找到的最好的修复方法是将部分内容放在z-index: 1div中:

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

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

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

当然,滚动动画是可选的。

由于这是一个演示的问题,一个纯CSS解决方案是理想的。然而,这个问题是在2012年提出的,尽管已经提出了相对定位/负边距解决方案,但这些方法似乎相当老土,造成潜在的流程问题,并且不能动态响应DOM/视口的变化。

考虑到这一点,我相信使用JavaScript是仍然(2017年2月)的最佳方法。下面是一个vanilla-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 linksif(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);

我也在寻找解决这个问题的方法。就我而言,这很容易。

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

<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的跨度标签。

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

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

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

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

您可以在没有任何javascript的情况下使用CSS。

给你的主播一个类:

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

然后,您可以将锚点定位为高于或低于它实际出现在页面上的偏移量,方法是使其成为块元素并相对定位它。-250px将锚点定位为250px

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

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

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

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

  vertical-align: top;

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

我还必须使用:目标伪类,它将样式应用于所选锚点以调整FFOperaIE9中的填充:

a:target {padding-top: 40px}

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

此外,我想注意到亚历山大的解决方案之所以有效,是因为目标元素是inline。如果你不想要链接,你可以简单地更改display属性:

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

加上Ziav的回答(感谢Alexander Savin),我需要使用老式的<a name="...">...</a>,因为我们在代码中使用<div id="...">...</div>有另一个目的。我在使用display: inline-block时遇到了一些显示问题——每个<p>元素的第一行都被证明是稍微右缩进的(在Webkit和Firefox浏览器上)。最后我尝试了其他display值,display: table-caption对我来说非常合适。

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

我在TYPO3网站上遇到了这个问题,其中所有“内容元素”都包含以下内容:

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

我改变了渲染,所以它呈现成这样:

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

这个CSS:

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

固定的顶栏高40px,现在锚再次工作并在顶栏下开始10px。

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

我在每个h1元素之前添加了40px-高度.vspace元素来保持锚点。

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

在CSS中:

.vspace { height: 40px;}

它工作得很好,空间没有堵塞。

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

超文本标记语言:

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

css:

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

使用这个:

<a id="top">&nbsp;</a>

以尽量减少重叠,并将font-size设置为1px。空锚点在某些浏览器中不起作用。

您可以在没有js和不更改html的情况下完成它。它只是css。

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

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

如何使用具有可链接ID的隐藏跨度标签来提供导航栏的高度:

#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

我一直面临着类似的问题,不幸的是,在实施了上述所有解决方案后,我得出了以下结论。

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

我写了这个简单的滚动js,它解释了由于标题引起的偏移,并将div重新定位在下面大约125像素。请在您认为合适的情况下使用它。

超文本标记语言

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

现场实施在这里

你也可以添加一个锚点跟随attr:

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

并给父容器一个相对位置。

对我来说很完美。

如果您的锚点是表元素或在表(行或单元格)中,则上述方法不能很好地工作。

我不得不使用javascript并绑定到windowshashchange事件来解决这个问题(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();});

*注意:哈希变化事件并非在所有浏览器中都可用。

您可以使用a[name]:not([href]) css选择器在没有ID的情况下实现这一点。这只是查找带有名称而没有href的链接,例如<a name="anc1"></a>

一个示例规则可能是:

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

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

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

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

$(".dropdown-menu a[href^='#']").on('click', function(e) {// prevent default anchor click behaviore.preventDefault();
// animate$('html, body').animate({scrollTop: $(this.hash).offset().top - 60}, 300, function(){});});

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

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

FWIW这对我有用:

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

来自@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() {//settingsvar 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 eventstopbarML();$('#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>

最后是超文本标记语言:

<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褪色拨号头的人有用!

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

这是我们在网站上使用的解决方案。将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;});

与其有一个固定位置的导航栏,它被页面的其余内容(整个页面主体是可滚动的)覆盖,不如考虑有一个带有静态导航栏的不可滚动主体,然后将页面内容放在下面一个绝对定位的可滚动div中。

也就是说,有这样的超文本标记语言…

<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演示了这一点。

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

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