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


123

この質問をする/検索する最良の方法はわかりません:

アンカーリンクをクリックすると、リンク先領域がページの非常に上部にあるページのセクションに移動します。アンカーリンクでページのその部分に移動したいのですが、上部にスペースを確保してください。のように、リンク先のパーツに非常に上部に移動したくないので、そこに100ピクセル程度のスペースが必要です。

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

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

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

<p id="anchor">I should be 100px below where I currently am!</p>

重複していますか?stackoverflow.com/questions/11386807/...
XCS

回答:


156
window.addEventListener("hashchange", function () {
    window.scrollTo(window.scrollX, window.scrollY - 100);
});

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

編集1:

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

// 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は、例ので置き換えるだけです。@ネオンに感謝します。

編集2:

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

このソリューションは、@ 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はここにあります


1
これは、ユーザーが既にページにいる場合にのみ機能します。たとえば、ユーザーがexample.com/#anchorからアクセスした場合は機能しませんexample.com/about/
erb 2014年

7
ありがとう@erb。OPの質問ではそのようなケースは必要ありませんでしたが、他の人を助けるために別のバージョンの実装を追加しました。
エリックオルソン

2
まだ細部が不足しています。アンカーをクリックしてから上にスクロールしてから同じアンカーをクリックすると、ハッシュ変更が行われないため、オフセットは使用されません。アイデア?
Teo Maragakis 2015年

あなたは行くことができます$('a[href^="#"]').on('click', function() { offsetAnchor(); });。このようhrefに、a要素のがで始まる#場合、同じ関数を呼び出します。
Mave

2
jQueryを使用する必要はありません。次のものに置き換え$(window).on("hashchange",てくださいwindow.addEventListener("hashchange",
Neon

89

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

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

これがいずれの場合でも最善の解決策かどうかはわかりませんが、私にとってはうまくいきます。


3
その上の50px以内にリンクがある場合、それが隠されてクリックできなくなる可能性があります
Andrew

@Andrew IE10やChromeでは問題ないようです。
Sinister Beard

11
position: relativecssプロパティを使用して同じことを行うことができます。したがって、それは次のようになりますposition: relative; top: -50px;
Aleks Dorohovich

@AleksDorohovich-既存の回答とは異なるため、別の回答として投稿できます。
BSMP

ページが乱暴になりました... * _ *

64

さらに良い解決策:

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

<a>相対的に配置されたオブジェクト内に絶対配置でタグを配置するだけです。

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


4
JavaScriptを使用しないため、私はあなたのソリューションを好みます。ありがとう!
Rosario Russo

1
この答えがわかりません。このリンクをオブジェクトまたはオブジェクト自体に参照していますか?
CZorio 2016年

3
ブートストラップ固定トップナビゲーションバーで非常に便利
Outside_Box

1
@CZorio私が正しく理解した場合、それはアンカー要素(「a」の代わりに「span」のようなものである可能性があります)を(真剣に)作成し、それを比較的下に配置して、その中のアンカーhref="#anchor"がそこを指すようにします。<p>要素を直接指す代わりに。しかし、一つの警告:使用idの代わりに、nameHTML5では、以下を参照してください。stackoverflow.com/questions/484719/html-anchors-with-name-or-id
FLEN

1
本当に良い解決策:)
Bobby Axe

21

これに対する2020年の答えは次のとおりです:

#anchor {
  scroll-margin-top: 100px;
}

なぜなら、それは広くサポートされます


1
これは良いことですが、広くサポートされていないため、反対投票されました。opera mobile / miniも、safari browser / iosも、最初のEdgeもこれを完全にサポートしていません。
Beda Schmid

1
特にユーザーへの影響がスクロールしなければならない場合は、JavaScriptソリューションをオプトアウトするには、すべてのブラウザー(iOSにscroll-snap-margin-topを含む)の90%未満で十分です。しかし、ねえ、誰かに害を与える前にこのアプローチを反対投票しましょう。
user127091

そのようなシンプルで実用的な答え。十分に早く(最新のブラウザーの場合)サポートの100%に到達します。
Leonel Becerra

17

最良のソリューション

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

8
なぜこれが最善の解決策なのですか?また、ある程度の説明と推論を回答に加えれば、はるかに役立ちます。
Phill Healey、

とにかくHTMLを追加してアンカーを作成するので、スパンを追加してもそれほど違いはありません。次に、CSSを少し追加するだけで、バグを発生させることなくこの問題を解決できます。他のいくつかのソリューションと同じように。
Sondre

11

これは、jQueryがなくてもページの読み込み時に機能します。

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

1
私にとってはうまくいき、ページ上のすべてのハッシュの場所に適用されるというcssメソッドよりも優れているので、各ハッシュを含むスタイルを記述し、別のパラを追加するときにスタイルを変更することを忘れないでください。新しいハッシュ。また、@ user3364768からの回答のように、上記の100px(またはそれ以上)を拡張せずに背景色でターゲットのスタイルを設定することもできますが、その方法はあります。
David

4

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

<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デモ

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

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

window.addEventListener('hashchange', addMargin);

JS Fiddleデモ


1
これに関する唯一の問題は、実際のdivがページのさらに下にプッシュされることです。理想的には、アンカーリンクは通常よりも100px小さくなります。これを達成する必要がある場合は、JSまたはjQueryを使用してもかまいません。
デーモン2013

3
これは問題を解決しません、これは単に要素の前に空白を追加するだけです。
XCS 2013

user1925805:JavaScriptソリューションの最新の回答をご覧ください。@Cristy:私は知っています、私は答え自体で要素を明示的に述べました:要素はまだウィンドウの上部に配置されていますが、見たところ、上部から少し離れた位置にあるように見えます。
デビッドはモニカ

JSを使用した最適でクリーンなソリューション。ありがとうございます。
DanielaB67 2017

これは、ページ内で発生したハッシュ変更のみが機能します。しかし、IDでリダイレクトが使用されると、これは機能し
ません

4

これはうまくいくはずです:

    $(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

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

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

その後、CSSで簡単に設定できます

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

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


ありがとう。これは私のために働いたこのリストからの唯一の解決策です。
MikeyBunny、2016

3

エリックの答えは素晴らしいですが、本当にそのタイムアウトは必要ありません。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

このコードを試してみると、リンクをクリックしたときにすでにスムーズなアニメーションが表示されています。

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

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

1

最も簡単なソリューション:

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

Thomasのソリューションの変形:CSS 要素>要素セレクターはここで便利です。

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>

リンクをクリックすると、クラスがの要素が配置されている場所のスクロール位置が100px上に移動しますpaddedAnchor

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


1

私は自分のための簡単な解決策を見つけました。マージン上部が15pxだった

HTML

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

CSS

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

1

cssのみを使用し、以前にカバーされたクリックできないコンテンツに問題がないこと(これのポイントは、pointer-events:noneです):

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>

1

これをスタイルに入れます:

.hash_link_tag{margin-top: -50px; position: absolute;}

このクラスをdivリンクの前に別のタグで使用します。例:

<div class="hash_link_tag" id="link1"></div> 
<a href="#link1">Link1</a>

または、このphpコードをエコーリンクタグに使用します。

function HashLinkTag($id)
{
    echo "<div id='$id' class='hash_link_tag'></div>";
}

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


スニペットのjsだけですか?何があっても機能しません

0

@Eric Olson ソリューションに基づいて、少し変更して、具体的に行きたいアンカー要素を含めます

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

私は同じ問題を抱えています。私はnavをpixedに配置しており、アンコールをnavの下で開始したいと思います。溶液window.addEventListener...私のためではない仕事は私はあることを私のページを設定するのでscroll-behavior:smooth、それはオフセットを設定して代わりにアンコールにスクロール。setTimeout()終わりまでスクロールするのに十分な時間があればまだうまくいかない場合の作業。したがって、私の解決策は、とheight:[the height of the nav]を使用して、アンコールにポジティブ絶対divを追加することでしたbottom:100%。この場合、このdivはangkor要素の上部で終了し、スクロールする先のアンコールの位置から始まります。今私がしていることはすべて、angkorリンクをこの絶対divに設定し、worを実行することです:)

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

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

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

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

<div style="margin-top: -100px; padding-top: 100px;" id="anchor"></div>
<p>I should be 100px below where I currently am!</p>

4
それは本質的に同じ答えだ、この1。古い質問への回答を投稿する場合は、何か新しいものを追加してみてください。たとえば、それが機能する理由を説明できます。
Artjom B.

1
なぜそれが機能するのかについては、どのような回答にも何らかの説明が必要です。;-)
Phill Healey、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.