javascript - html錨點滑動 - js錨點
抵消一個html錨點以調整固定標題 (19)
這個問題在這裡已經有了答案:
- 固定頁面標題與頁內定位符重疊 25個答案
我正在努力清理錨桿的工作方式。 我有一個固定在頁面頂部的標題,所以當你鏈接到頁面其他地方的一個錨點時,頁面跳轉,所以錨點位於頁面的頂部,將內容留在固定標題後面(我希望這就說得通了)。 我需要一種方法將標題的高度偏移25px。 我更喜歡HTML或CSS,但Javascript也可以接受。
你可以做到這一點沒有js和沒有改變HTML。 這只是CSS而已。
a[id]:before {
content:"";
display:block;
height:50px;
margin:-30px 0 0;
}
這將在每個帶有id的a-tag之前附加一個偽元素。 調整值以匹配標題的高度。
@ AlexanderSavin的解決方案對我來說在WebKit
瀏覽器中效果很好。
我還必須使用:目標偽類,它將選擇的錨點的樣式應用於FF
, Opera
和IE9
調整填充:
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>
你也可以添加一個跟隨attr的錨點:
(text-indent:-99999px;)
visibility: hidden;
position:absolute;
top:-80px;
並給父容器一個相對位置。
對我來說很完美。
你可以在沒有任何JavaScript的情況下使用CSS。
給你的主持人上課:
<a class="anchor" id="top"></a>
然後,您可以通過將錨點放置在比它實際出現在頁面上的位置更高或更低的位置,使其成為塊元素並將其定位。 -250px將定位錨點250px
a.anchor {
display: block;
position: relative;
top: -250px;
visibility: hidden;
}
借用這個鏈接給出的答案中的一些代碼(沒有指定作者),可以在錨點上包含一個很好的平滑滾動效果,同時使其停留在錨點上方-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(){
});
});
如果您的錨點是表格元素或表格(行或單元格),上述方法不能很好地工作。
我必須使用javascript並綁定到窗口hashchange
事件來解決這個( 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();
});
*注意: hashchange事件在所有瀏覽器中都不可用。
對於現代瀏覽器,只需將CSS3:target選擇器添加到頁面即可。 這將自動適用於所有錨點。
:target {
display: block;
position: relative;
top: -100px;
visibility: hidden;
}
從@Jan得到的優秀答案的另一個轉折是將它加入到使用jQuery(或MooTools)的#uberbar固定頭文件中。 ( 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褪色混合頭的人是有用的!
我也在尋找解決方案。 在我的情況下,這很容易。
我有一個包含所有鏈接的列表菜單:
<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;}
更改頂部值以匹配固定標題的高度(或更多)。 現在我認為這也適用於其他元素。
我在一個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 name="myanchor">
<h1 style="padding-top: 40px; margin-top: -40px;">My anchor</h1>
</a>
這並不會在內容上產生任何差距,而且鏈接鏈接非常好。
我遇到了同樣的問題,並最終手動處理了點擊事件,例如:
$('#mynav a').click(() ->
$('html, body').animate({
scrollTop: $($(this).attr('href')).offset().top - 40
}, 200
return false
)
當然,滾動動畫可選。
改變位置屬性的解決方案並不總是可能的(它可以破壞佈局),因此我建議:
HTML:
<a id="top">Anchor</a>
CSS:
#top {
margin-top: -250px;
padding-top: 250px;
}
用這個:
<a id="top"> </a>
最大限度地減少重疊,並設置字體大小為1px。 空錨在某些瀏覽器中不起作用。
由於這是演示的關注點,純粹的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 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);
而不是有一個固定位置的導航欄與頁面內容的其餘部分不一致(整個頁面正文可滾動),請考慮改為使用靜態導航欄不可滾動的正文,然後將頁面內容放入下面是絕對定位的可滾動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%;
}
這以直截了當的方式達到了預期的效果。 這和上面提出的一些聰明的CSS hack之間的行為唯一的區別在於,滾動條(在呈現一個的瀏覽器中)將被附加到內容div而不是整個頁面的高度。 你可能會也可能不會考慮這個理想。
這是我們在網站上使用的解決方案。 將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;
});
這需要從以前的答案中的許多元素,並結合成一個小(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);
Uglified版本:
!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);
除了Ziav的回答(感謝Alexander Savin)之外,我還需要使用舊學校的<a name="...">...</a>
因為我們使用的是<div id="...">...</div>
用於我們的代碼中的另一個目的。 我在使用display: inline-block
遇到了一些顯示問題display: inline-block
- 每個<p>
元素的第一行display: inline-block
為稍微右移(在Webkit和Firefox瀏覽器上)。 我最終嘗試了其他display
值並display: table-caption
完美地適用於我。
.anchor {
padding-top: 60px;
margin-top: -60px;
display: table-caption;
}