Stellen Sie sicher, dass der Ankerlink einige Pixel über der Stelle liegt, mit der er verknüpft ist


123

Ich bin mir nicht sicher, wie ich diese Frage am besten stellen / suchen kann:

Wenn Sie auf einen Ankerlink klicken, gelangen Sie zu dem Abschnitt der Seite mit dem verknüpften Bereich, der sich jetzt ganz oben auf der Seite befindet. Ich möchte, dass der Ankerlink mich zu diesem Teil der Seite schickt, aber ich möchte oben etwas Platz. Wie in, ich möchte nicht, dass es mich zu dem verknüpften Teil damit an der SEHR TOP schickt, ich möchte dort ungefähr 100 Pixel Platz.

Macht das Sinn? Ist das möglich?

Bearbeitet, um Code anzuzeigen - es ist nur ein Ankertag:

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

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


Antworten:


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

Auf diese Weise kann der Browser für uns zum Anker springen und diese Position zum Versetzen verwenden.

EDIT 1:

Wie von @erb hervorgehoben, funktioniert dies nur, wenn Sie sich auf der Seite befinden, während der Hash geändert wird. Das Aufrufen der Seite mit einer #somethingbereits in der URL enthaltenen Funktion funktioniert mit dem obigen Code nicht. Hier ist eine andere Version, um das zu handhaben:

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

HINWEIS: Um jQuery zu verwenden, können Sie einfach ersetzen window.addEventListenermit $(window).onin den Beispielen. Danke @Neon.

EDIT 2:

Wie bereits von einigen erwähnt, schlägt das oben Gesagte fehl, wenn Sie zweimal oder mehrmals hintereinander auf denselben Ankerlink klicken, da kein hashchangeEreignis vorhanden ist, um den Versatz zu erzwingen.

Diese Lösung ist eine geringfügig modifizierte Version des Vorschlags von @Mave und verwendet der Einfachheit halber jQuery-Selektoren

// 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 für dieses Beispiel ist hier


1
Dies funktioniert nur , wenn der Benutzer bereits auf der Seite ist, es nicht zum Beispiel , wenn der Benutzer besucht example.com/#anchoraus example.com/about/.
Erb

7
Danke @erb. Die Frage des OP erforderte diesen Fall nicht, aber um anderen zu helfen, fügte ich eine andere Version der Implementierung hinzu.
Eric Olson

2
Es fehlt noch ein kleines Detail. Wenn Sie auf einen Anker klicken, dann nach oben scrollen und erneut auf denselben Anker klicken, gibt es keine Hash-Änderung, sodass der Versatz nicht verwendet wird. Ideen?
Teo Maragakis

Du könntest gehen $('a[href^="#"]').on('click', function() { offsetAnchor(); });. Auf diese Weise rufen Sie dieselbe Funktion auf , wenn das hrefeines aElements mit a beginnt #.
Mave

2
Keine Notwendigkeit, jQuery - ersetzen Sie einfach $(window).on("hashchange",mitwindow.addEventListener("hashchange",
Neon

89

Wenn Sie nur mit CSS arbeiten, können Sie dem verankerten Element einen Abstand hinzufügen (wie in der obigen Lösung). Um unnötige Leerzeichen zu vermeiden, können Sie einen negativen Rand mit derselben Höhe hinzufügen:

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

Ich bin mir nicht sicher, ob dies auf jeden Fall die beste Lösung ist, aber es funktioniert gut für mich.


3
Wenn es einen Link innerhalb von 50px darüber gibt, kann er vertuscht und unklickbar gemacht werden, glaube ich
Andrew

@ Andrew Das scheint auf IE10 oder Chrome kein Problem zu sein.
Unheimlicher Bart

11
Sie können dasselbe mit der position: relativeCSS-Eigenschaft tun . So wäre es wieposition: relative; top: -50px;
Aleks Dorohovich

@AleksDorohovich - Sie können dies als separate Antwort veröffentlichen, da es nur für die vorhandenen Antworten gilt.
BSMP

Meine Seite wurde wild ... * _ *

64

Noch bessere Lösung:

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

Positionieren Sie das <a>Tag einfach mit absoluter Position innerhalb eines relativ positionierten Objekts.

Funktioniert beim Eingeben der Seite oder durch eine Hash-Änderung innerhalb der Seite.


4
Ich bevorzuge Ihre Lösung, weil sie kein Javascript verwendet. Vielen Dank!
Rosario Russo

1
Ich verstehe diese Antwort nicht. Verweisen Sie auf diesen Link zum Objekt oder zum Objekt selbst?
CZorio

3
Sehr nützlich mit Bootstrap-Navigationsleisten mit festem Verdeck
Outside_Box

1
@CZorio Wenn ich es richtig verstanden habe, erstellt es (genial) ein Ankerelement (könnte etwas anderes sein, wie "span" anstelle von "a") und positioniert es relativ darunter, so dass der Anker mit href="#anchor"darin darauf zeigt. anstatt <p>direkt auf das Element zu zeigen. Aber eine Warnung: Verwenden Sie idanstelle von namein HTML5, siehe: stackoverflow.com/questions/484719/html-anchors-with-name-or-id
flen

1
Wirklich eine bessere Lösung :)
Bobby Axe

21

Hier ist die Antwort für 2020:

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

Weil es weit verbreitet ist !


1
Downvoted, weil dies zwar nett wäre, aber NICHT allgemein unterstützt wird. Weder Opera Mobile / Mini noch Safari Browser / iOS, nicht einmal der erste Edge unterstützt dies vollständig.
Beda Schmid

1
Etwas weniger als 90% aller Browser (einschließlich iOS mit Scroll-Snap-Rand-Top) sollten ausreichen, um eine Javascript-Lösung zu deaktivieren, insbesondere wenn die Auswirkungen auf den Benutzer nur das Scrollen erfordern. Aber hey, lasst uns diesen Ansatz ablehnen, bevor er jemandem schadet.
user127091

So eine einfache und funktionierende Antwort. Wird bald genug 100% der Unterstützung (für moderne Browser) erreichen.
Leonel Becerra

17

Beste Lösung

<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
Warum ist das die beste Lösung? Es ist auch viel hilfreicher, wenn Sie eine Erklärung / Argumentation mit einer Antwort geben.
Phill Healey

Da Sie HTML hinzufügen, um einen Anker zu erstellen, unterscheidet sich das Hinzufügen eines Bereichs nicht wesentlich. Wenn Sie dann nur ein wenig CSS hinzufügen, können Sie dieses Problem lösen, ohne Fehler zu bekommen. wie einige andere Lösungen tun können.
Sondre

11

Dies funktioniert ohne jQuery und beim Laden der Seite.

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

1
Funktioniert für mich und hat gegenüber der CSS-Methode den Vorteil, dass sie für alle Hash-Positionen auf einer Seite gilt, sodass Sie nicht mit jedem enthaltenen Hash einen Stil schreiben müssen und daran denken, den Stil zu ändern, wenn Sie einen weiteren Absatz mit hinzufügen ein neuer Hash. Es ermöglicht auch, das Ziel mit einer Hintergrundfarbe zu gestalten, ohne dass diese 100px (oder was auch immer) oben erweitert wird, wie in der Antwort von @ user3364768, obwohl es einen Weg gibt, dies zu umgehen.
David

4

Um eine Verknüpfung zu einem Element herzustellen und dieses Element dann mit reinem CSS in einem beliebigen Abstand vom oberen Rand der Seite zu positionieren, müssen Sie es verwenden padding-top. Auf diese Weise befindet sich das Element immer noch am oberen Rand des Fensters, aber es scheint sichtbar in einiger Entfernung von der Oberseite des Sichtfensters positioniert zu sein, zum Beispiel:

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

So verwenden Sie einen einfachen JavaScript-Ansatz:

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

window.addEventListener('hashchange', addMargin);

JS Fiddle Demo .


1
Das einzige Problem dabei ist, dass das tatsächliche Div jetzt weiter unten auf der Seite verschoben wird. Im Idealfall würde die Ankerverbindung nur 100 Pixel weniger nach unten gehen als normalerweise. Ich bin bereit, JS oder jQuery zu verwenden, wenn dies erforderlich ist.
damon

3
Dies löst das Problem nicht, sondern fügt einfach Leerzeichen vor dem Element hinzu.
XCS

user1925805: Siehe die aktualisierte Antwort für eine JavaScript-Lösung. @Cristy: Ich weiß , ich habe dies in der Antwort selbst ausdrücklich angegeben: Das Element befindet sich immer noch oben im Fenster, aber es scheint sichtbar in einiger Entfernung von oben positioniert zu sein .
David sagt, Monica

Beste, saubere Lösung mit Ihrem JS. Danke, es funktioniert sehr gut für mich!
DanielaB67

Dies funktioniert nur, wenn innerhalb der Seite Hash-Änderungen vorgenommen wurden. Aber Verwendung wurde mit ID umgeleitet, dann funktioniert dies nicht
Rohan Khude

4

Das sollte funktionieren:

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

Ändern Sie einfach die .top-49 so, dass sie zu Ihrem Ankerlink passt.


3

Wenn Sie explizite Ankernamen verwenden, wie z.

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

dann können Sie in CSS einfach einstellen

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

Dies funktioniert so lange, wie Ihre HREF-Ankertags kein NAME-Attribut angeben


Vielen Dank. Dies ist die einzige Lösung aus dieser Liste, die für mich funktioniert hat.
MikeyBunny

3

Erics Antwort ist großartig, aber du brauchst diese Auszeit wirklich nicht. Wenn Sie jQuery verwenden, können Sie einfach warten, bis die Seite geladen ist. Daher würde ich vorschlagen, den Code zu ändern in:

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

Dies befreit uns auch von diesem willkürlichen Faktor.


3

Versuchen Sie diesen Code, es hat bereits eine glatte Animation, wenn Sie auf den Link klicken.

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

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

1

Die einfachste Lösung:

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

Eine Variante der Lösung von Thomas: CSS- Element> Element- Selektoren können hier nützlich sein:

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>

Durch Klicken auf den Link wird die Bildlaufposition auf 100 Pixel über dem Element mit einer Klasse von verschoben paddedAnchor befindet.

Unterstützt in Nicht-IE-Browsern und in IE ab Version 9. Für die Unterstützung in IE 7 und 8 <!DOCTYPE>muss a deklariert werden.


1

Ich habe gerade eine einfache Lösung für mich gefunden. Hatte einen Rand von 15px

HTML

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

CSS

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

1

Verwenden Sie nur CSS und haben Sie zuvor keine Probleme mit abgedeckten und nicht anklickbaren Inhalten (der Punkt dabei sind die Zeigerereignisse: keine):

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

Setzen Sie dies in Stil:

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

und verwenden Sie diese Klasse in einem separaten divTag vor den Links, Beispiel:

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

oder benutze diesen PHP-Code für das Echo Link Tag:

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

0

Ich weiß, dass dies etwas spät ist, aber ich habe etwas sehr Wichtiges gefunden, das Sie in Ihren Code einfügen können, wenn Sie Bootstraps Scrollspy verwenden. ( http://getbootstrap.com/javascript/#scrollspy )

Das hat mich stundenlang verrückt gemacht.

Der Versatz für den Bildlaufspion MUSS mit dem window.scrollY übereinstimmen, sonst besteht die Gefahr, dass:

  1. Beim Scrollen einen seltsamen Flickereffekt erzielen
  2. Wenn Sie auf Anker klicken, landen Sie in diesem Abschnitt, aber Scroll Spy geht davon aus, dass Sie sich in einem Abschnitt darüber befinden.

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


Nur js im Snippet? Es wird nicht funktionieren, egal was

0

Basierend auf der @ Eric Olson- Lösung ändern Sie nur ein wenig, um das Ankerelement einzuschließen , auf das ich speziell eingehen möchte

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

Ich habe nur das gleiche Problem. Ich habe ein Navi pixiert und ich möchte, dass der Angkor unter dem Navi startet. Die Lösung window.addEventListener...funktioniert bei mir nicht, weil ich meine Seite scroll-behavior:smoothso eingestellt habe, dass sie den Versatz einstellt. Scrollen Sie stattdessen zum Angkor. die setTimeout()Arbeit, wenn die Zeit ausreicht, um bis zum Ende zu scrollen, aber es sieht immer noch nicht gut aus. Meine Lösung bestand also darin, ein gesetztes absolutes Div im Angkor mit height:[the height of the nav]und hinzuzufügen bottom:100%. In diesem Fall endete dieses Div oben im Angkor-Element und begann an der Position, zu der Sie das Angkor scrollen möchten. Jetzt setze ich nur noch den Angkor-Link zu diesem absoluten Div und die Arbeit erledigt :)

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

Ich war mit dem ähnlichen Problem konfrontiert und habe es mithilfe des folgenden Codes gelöst

$(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
Das ist im Wesentlichen die gleiche Antwort wie diese . Wenn Sie Antworten auf alte Fragen veröffentlichen, versuchen Sie, etwas Neues hinzuzufügen. Zum Beispiel könnten Sie beschreiben, warum das funktioniert.
Artjom B.

1
Ich würde argumentieren, dass jede Antwort eine Beschreibung haben sollte, warum sie funktioniert. ;-)
Phill Healey
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.