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

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

Eric Olson
quelle
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.

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

Thomas
quelle
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 !

user127091
quelle
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>
Никита Андрейчук
quelle
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);
    }
})();
MK
quelle
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 .

David sagt, Monica wieder einsetzen
quelle
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.

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

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

rppc
quelle
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);
});
Maricar Onggon
quelle
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>
Edalat Mojaveri
quelle
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.

HondaGuy
quelle
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;}
Gero
quelle
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>
dantefff
quelle
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>";
}
MohsenB
quelle
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);
});

Beefsupreme
quelle
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);
});
Carlos A. Ortiz
quelle
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>

Josef Tukachinsky
quelle
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();
    });
Umair Mehmood
quelle
-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>
Sportcanon
quelle
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