web-dev-qa-db-ja.com

アンカーリンクをリンク先の数ピクセル上に移動します

この質問を尋ねる/検索する最善の方法がわからない:

アンカーリンクをクリックすると、ページのそのセクションに移動し、リンク先の領域がページの最上部に表示されます。アンカーリンクを使用してページのその部分に移動したいのですが、上部にスペースが必要です。のように、VERY TOPでリンク先のパーツに送られたくないので、そこに100ピクセル程度のスペースが必要です。

これは理にかなっていますか?これは可能ですか?

コードを表示するように編集されました-それは単なるアンカータグです:

<a href="#anchor">Click me!</a>

<p id="anchor">I should be 100px below where I currently am!</p>
98
damon
window.addEventListener("hashchange", function () {
    window.scrollTo(window.scrollX, window.scrollY - 100);
});

これにより、ブラウザがアンカーにジャンプする作業を実行できるようになり、その位置を使用してオフセットします。

編集1:

@erbが指摘したように、これはハッシュが変更されている間にページを開いている場合にのみ機能します。 URLに既に#somethingが含まれているページを入力しても、上記のコードでは機能しません。これを処理する別のバージョンを次に示します。

// The function actually applying the offset
function offsetAnchor() {
    if(location.hash.length !== 0) {
        window.scrollTo(window.scrollX, window.scrollY - 100);
    }
}

// This will capture hash changes while on the page
window.addEventListener("hashchange", offsetAnchor);

// This is here so that when you enter the page with a hash,
// it can provide the offset in that case too. Having a timeout
// seems necessary to allow the browser to jump to the anchor first.
window.setTimeout(offsetAnchor, 1); // The delay of 1 is arbitrary and may not always work right (although it did in my testing).

注:jQueryを使用するには、例のwindow.addEventListener$(window).onに置き換えるだけで済みます。 @Neonに感謝します。

編集2:

いくつか指摘したように、オフセットを強制するhashchangeイベントがないため、同じアンカーリンクを連続して2回以上クリックすると、上記は失敗します。

このソリューションは、@ Maveからの提案をわずかに修正したバージョンであり、簡単にするためにjQueryセレクターを使用しています

// The function actually applying the offset
function offsetAnchor() {
  if (location.hash.length !== 0) {
    window.scrollTo(window.scrollX, window.scrollY - 100);
  }
}

// Captures click events of all <a> elements with href starting with #
$(document).on('click', 'a[href^="#"]', function(event) {
  // Click events are captured before hashchanges. Timeout
  // causes offsetAnchor to be called after the page jump.
  window.setTimeout(function() {
    offsetAnchor();
  }, 0);
});

// Set the offset when entering page with hash present in the url
window.setTimeout(offsetAnchor, 0);

この例のJSFiddleは here です

126
Eric Olson

Cssのみを使用して、アンカー要素にパディングを追加できます(上記のソリューションのように)不要な空白を避けるために、同じ高さの負のマージンを追加できます。

#anchor {
    padding-top: 50px;
    margin-top: -50px;
}

これがいずれにせよ最良の解決策であるかどうかはわかりませんが、私にとってはうまくいきます。

72
user3364768

さらに優れたソリューション:

<p style="position:relative;">
    <a name="anchor" style="position:absolute; top:-100px;"></a>
    I should be 100px below where I currently am!
</p>

<a>タグを、相対位置のオブジェクト内に絶対位置で配置するだけです。

ページに入るとき、またはページ内のハッシュの変更を通じて機能します。

51
Thomas

ベストソリューション

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

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

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

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

これは、jQueryなしで、ページのロード時に機能します。

(function() {
    if (document.location.hash) {
        setTimeout(function() {
            window.scrollTo(window.scrollX, window.scrollY - 100);
        }, 10);
    }
})();
9
M K

要素にリンクし、純粋なCSSを使用して、ページの上部から任意の距離にその要素を「配置」するには、padding-topを使用する必要があります。 itが表示されます、目に見えるように、ビューポートの上部からある程度の距離に配置されます、例えば:

<a href="#link1">Link one</a>
<a href="#link2">Link two</a>

<div id="link1">
    The first.
</div>

<div id="link2">
    The second.
</div>

CSS:

div {
    /* just to force height, and window-scrolling to get to the elements.
       Irrelevant to the demo, really */
    margin-top: 1000px;
    height: 1000px;
}

#link2 {
    /* places the contents of the element 100px from the top of the view-port */
    padding-top: 100px;
}

JS Fiddle demo

単純なJavaScriptアプローチを使用するには:

function addMargin() {
    window.scrollTo(0, window.pageYOffset - 100);
}

window.addEventListener('hashchange', addMargin);

JS Fiddle demo

4
David Thomas

エリックの答えは素晴らしいですが、あなたは本当にそのタイムアウトを必要としません。 jQueryを使用している場合は、ページがロードされるのを待つことができます。したがって、コードを次のように変更することをお勧めします。

// The function actually applying the offset
function offsetAnchor() {
    if (location.hash.length !== 0) {
        window.scrollTo(window.scrollX, window.scrollY - 100);
    }
}

// This will capture hash changes while on the page
$(window).on("hashchange", function () {
    offsetAnchor();
});

// Let the page finish loading.
$(document).ready(function() {
    offsetAnchor();
});

これにより、その任意の要素も排除されます。

3
rppc

これは動作するはずです:

    $(document).ready(function () {
    $('a').on('click', function (e) {
        // e.preventDefault();

        var target = this.hash,
            $target = $(target);

       $('html, body').stop().animate({
        'scrollTop': $target.offset().top-49
    }, 900, 'swing', function () {
    });

        console.log(window.location);

        return false;
    });
});

.top-49をアンカーリンクに適合するものに変更するだけです。

3
dMehta

次のような明示的なアンカー名を使用する場合、

<a name="sectionLink"></a>
<h1>Section<h1>

その後、CSSでは、単に設定することができます

A[name] {
    padding-top:100px;
}

これは、HREFアンカータグがNAME属性も指定しない限り機能します

3
Mespr

このコードを試してください。リンクをクリックすると、すでにスムーズなアニメーションになっています。

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

    $('html, body').animate({
        scrollTop: $($.attr(this, 'href')).offset().top - 100
    }, 500);
});
2
Maricar Onggon

Thomasのソリューションの変形:CSS element> elementselectors はここで便利です:

CSS

.paddedAnchor{
  position: relative;
}
.paddedAnchor > a{
  position: absolute;
  top: -100px;
}

HTML

<a href="#myAnchor">Click Me!</a>

<span class="paddedAnchor"><a name="myAnchor"></a></span>

リンクをクリックすると、paddedAnchorのクラスを持つ要素が配置されている場所のどこでも、スクロール位置が上の100ピクセルに移動します。

IE以外のブラウザ、およびバージョン9のIEでサポートされています。IE 7および8でサポートするには、<!DOCTYPE>を宣言する必要があります。

1
HondaGuy

簡単な解決策を見つけました。マージントップが15pxだった

HTML

<h2 id="Anchor">Anchor</h2>

CSS

h2{margin-top:-60px; padding-top:75px;}
1
Gero

最も簡単な解決策:

CSS

#link {
    top:-120px; /* -(some pixels above) */
    position:relative;
    z-index:5;
}

HTML

<body>
    <a href="#link">Link</a>
    <div>
        <div id="link"></div> /*this div should placed inside a target div in the page*/
        text
        text
        text
    <div>
</body>
1
Edalat Mojaveri

同じ問題があります。 pixedされたnavがあり、angkorがnavの下で開始されるようにします。 window.addEventListener...の解決策は、ページをscroll-behavior:smoothに設定し、オフセット代わりに angkorにスクロールするため、うまくいきません。 setTimeout()は、最後までスクロールするには時間が十分にあるが、まだ見栄えが悪い場合に機能します。したがって、私の解決策は、height:[the height of the nav]bottom:100%を使用して、絶対的なdivをアンコールに追加することでした。この場合、このdivはアンコール要素の上部で終了し、アンコールをスクロールする位置から開始します。今、私がすることはすべて、この絶対的なdivへのアンコールリンクを設定し、完了しました:)

html,body{
    margin:0;
    padding:0;
    scroll-behavior:smooth;
}

nav {
    height:30px;
    width:100%;
    font-size:20pt;
    text-align:center;
    color:white;
    background-color:black;
    position:relative;
}

#my_nav{
    position:fixed;
    z-index:3;
}
#fixer_nav{
    position:static;
}

#angkor{
    position:absolute;
    bottom:100%;
    height:30px;
}
<nav id="my_nav"><a href="#angkor">fixed position nav<a/></nav>
<nav id="fixer_nav"></nav>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nec lacus vel eros rutrum volutpat. Cras ultrices enim sit amet odio dictum, eget consectetur mi pellentesque. Sed mollis gravida nulla, eu euismod turpis efficitur id. Integer pretium posuere fringilla. Aenean laoreet, augue non pharetra elementum, lectus massa congue orci, a imperdiet neque enim ut dui. Praesent commodo orci bibendum leo suscipit viverra. Nunc fermentum semper eleifend. Pellentesque suscipit nulla aliquet, egestas lectus sed, egestas dui. Vivamus scelerisque maximus nibh, ac dignissim nunc tempor a. Praesent facilisis non lacus et aliquam. Proin ultricies lacus vitae nibh ullamcorper gravida. Proin elit arcu, convallis eget posuere quis, placerat id augue. Fusce ex risus, tempus nec orci vitae, feugiat faucibus quam. Integer risus metus, ornare et rhoncus vitae, accumsan a urna.
</p>

<nav><div id="angkor"></div>The angkor</nav>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nec lacus vel eros rutrum volutpat. Cras ultrices enim sit amet odio dictum, eget consectetur mi pellentesque. Sed mollis gravida nulla, eu euismod turpis efficitur id. Integer pretium posuere fringilla. Aenean laoreet, augue non pharetra elementum, lectus massa congue orci, a imperdiet neque enim ut dui. Praesent commodo orci bibendum leo suscipit viverra. Nunc fermentum semper eleifend. Pellentesque suscipit nulla aliquet, egestas lectus sed, egestas dui. Vivamus scelerisque maximus nibh, ac dignissim nunc tempor a. Praesent facilisis non lacus et aliquam. Proin ultricies lacus vitae nibh ullamcorper gravida. Proin elit arcu, convallis eget posuere quis, placerat id augue. Fusce ex risus, tempus nec orci vitae, feugiat faucibus quam. Integer risus metus, ornare et rhoncus vitae, accumsan a urna.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nec lacus vel eros rutrum volutpat. Cras ultrices enim sit amet odio dictum, eget consectetur mi pellentesque. Sed mollis gravida nulla, eu euismod turpis efficitur id. Integer pretium posuere fringilla. Aenean laoreet, augue non pharetra elementum, lectus massa congue orci, a imperdiet neque enim ut dui. Praesent commodo orci bibendum leo suscipit viverra. Nunc fermentum semper eleifend. Pellentesque suscipit nulla aliquet, egestas lectus sed, egestas dui. Vivamus scelerisque maximus nibh, ac dignissim nunc tempor a. Praesent facilisis non lacus et aliquam. Proin ultricies lacus vitae nibh ullamcorper gravida. Proin elit arcu, convallis eget posuere quis, placerat id augue. Fusce ex risus, tempus nec orci vitae, feugiat faucibus quam. Integer risus metus, ornare et rhoncus vitae, accumsan a urna.

</p>
0

私はこれが少し遅いことを知っていますが、BootstrapのScrollspyを使用している場合は、コードに入れることが非常に重要であることがわかりました。 ( http://getbootstrap.com/javascript/#scrollspy

これは私を何時間も夢中にさせていました。

スクロールスパイのオフセットは、window.scrollYと一致する必要があります。一致しない場合、次のリスクが発生します。

  1. スクロール時に奇妙なフリッカー効果を得る
  2. アンカーをクリックすると、そのセクションに着陸しますが、スクロールスパイはあなたがその上のセクションであると想定します。
 var body = $('body');
    body.scrollspy({
        'target': '#nav',
        'offset': 100 //this must match the window.scrollY below or you'll have a bad time mmkay
});

$(window).on("hashchange", function () {
        window.scrollTo(window.scrollX, window.scrollY - 100);
});
0
beefsupreme

@Eric Olson solution に基づいて、具体的に行きたいアンカー要素を含めるために少し修正する

// Function that actually set offset
function offsetAnchor(e) {
    // location.hash.length different to 0 to ignore empty anchor (domain.me/page#)
    if (location.hash.length !== 0) {
        // Get the Y position of the element you want to go and place an offset
        window.scrollTo(0, $(e.target.hash).position().top - 150);
    }
}

// Catch the event with a time out to perform the offset function properly
$(document).on('click', 'a[href^="#"]', function (e) {
    window.setTimeout(function () {
        // Send event to get the target id later
        offsetAnchor(e);
    }, 10);
});
0
Carlos A. Ortiz

以前はcssのみを使用し、カバーされていてクリックできないコンテンツに問題はありません(これのポイントは、ポインターイベント:なしです)。

CSS

.anchored::before {
    content: '';
    display: block;
    position: relative;
    width: 0;
    height: 100px;
    margin-top: -100px;
}

HTML

<a href="#anchor">Click me!</a>
<div style="pointer-events:none;">
<p id="anchor" class="anchored">I should be 100px below where I currently am!</p>
</div>
0
dantefff

私は同様の問題に直面しており、次のコードを使用して解決しました

$(document).on('click', 'a.page-scroll', function(event) {
        var $anchor = $(this);
        var desiredHeight = $(window).height() - 577;
        $('html, body').stop().animate({
            scrollTop: $($anchor.attr('href')).offset().top - desiredHeight
        }, 1500, 'easeInOutExpo');
        event.preventDefault();
    });
0
Umair Mehmood