Feste Seitenüberschriften überlappen die Seitenanker

358

Wenn ich in einer HTML-Seite einen nicht scrollenden Header habe, der oben fixiert ist und eine definierte Höhe hat:

Gibt es eine Möglichkeit, den URL-Anker (das #fragmentTeil) zu verwenden, um den Browser zu einem bestimmten Punkt auf der Seite zu scrollen, aber die Höhe des festen Elements ohne die Hilfe von JavaScript zu berücksichtigen ?

http://foo.com/#bar
FALSCH (aber das übliche Verhalten): RICHTIG:
+ --------------------------------- + + -------------- ------------------- +
| BAR /////////////////////// header | | /////////////////////////// header |
+ --------------------------------- + + -------------- ------------------- +
| Hier ist der Rest des Textes | | BAR |
| ... | | |
| ... | | Hier ist der Rest des Textes |
| ... | | ... |
+ --------------------------------- + + -------------- ------------------- +
Tomalak
quelle
3
Siehe auch
0fnt
3
@ax JA, das ist die beste Antwort. Überprüfen Sie auch nicolasgallagher.com/jump-links-and-viewport-positioning/demo darin. Dies funktionierte am besten für mich:.dislocate50px, #bar { padding: 50px 0 0; margin: -50px 0 0; -webkit-background-clip: content-box; background-clip: content-box; }
flen
Ich suche nach einer Lösung, die * für Anker funktioniert, die von derselben Seite oder einer anderen Seite eingehen * und die das Drücken der Seite nach unten so anpasst, dass der Inhalt nicht durch die Kopfzeile abgeschnitten wird * und die es der sib-div-Fußzeile ermöglicht mit content-div nach oben scrollen. Ich habe noch keine Lösung gefunden! Aber ich muss sagen, ich denke, der richtige Weg würde auf den gesamten Inhaltsbereich abzielen und nicht auf jeden einzelnen Anker. stackoverflow.com/questions/51070758/…
Johny warum
@Axt. CSS-tricks.com hat einen viel besseren neueren Artikel über scroll-padding-tophier: css-tricks.com/… Entsprechende Antwort: stackoverflow.com/a/56467997/247696
Flimm

Antworten:

167

Ich hatte das gleiche Problem. Ich habe es gelöst, indem ich dem Ankerelement eine Klasse mit der Höhe der oberen Leiste als Füllwert hinzugefügt habe.

<h1><a class="anchor" name="barlink">Bar</a></h1>

Und dann einfach das CSS:

.anchor { padding-top: 90px; }
MutttenXd
quelle
19
@Tomalak Beachten Sie, dass diese Lösung Links innerhalb des Auffüllbereichs nicht anklickbar macht. Um dies zu beheben, müssen Sie den Z-Index verwenden und den Link-Wert höher als den des Ankers einstellen. Denken Sie daran, dass die obere Leiste den höchsten Z-Index-Wert haben sollte, damit der Inhalt der Seite beim Scrollen nicht über der oberen Leiste schwebt.
MutttenXd
Funktionierte in Chrome v28 aufgrund eines WebKit- Fehlers mit fester Position nicht, wodurch der Header verschwand. Diese Antwort hat den Trick in meinem Fall gemacht.
Knickedi
2
MuttenXd .. du bist mein Held. Ich hatte ein seltsames Problem mit nicht funktionierenden Links auf meiner Website (unabhängig von Ankern), das mich verrückt gemacht hat. Ihr nicht anklickbarer Kommentar hat wirklich geholfen. Ich schulde dir viel!
Zipzit
9
Fügen Sie, wie in Roy Shoas Antwort vorgeschlagen, hinzu margin-top: -90px;, um der durch Polsterung entstandenen Lücke entgegenzuwirken.
Skippy le Grand Gourou
37
Ich habe es .anchor:target {padding-top: 90px;}so verwendet , dass es nur die Polsterung hinzufügte, wenn sie das Ankertag verwendeten. Auf diese Weise wird nicht immer viel aufgefüllt, wenn die Seite oben geladen wird. Nur wenn ein bestimmter Punkt auf der Seite geladen wird.
Jimmyplaysdrums
265

Wenn Sie keine neue Klasse festlegen können oder möchten, fügen Sie ::beforeder :targetPseudoklasse in CSS ein Pseudoelement mit fester Höhe hinzu :

:target::before {
  content: "";
  display: block;
  height: 60px; /* fixed header height*/
  margin: -60px 0 0; /* negative fixed header height */
}

Oder scrollen Sie :targetmit jQuery relativ zu :

var offset = $(':target').offset();
var scrollto = offset.top - 60; // minus fixed header height
$('html, body').animate({scrollTop:scrollto}, 0);
Adrian Garner
quelle
30
Ihre Lösung gefällt mir sehr gut. Es ist die sauberste Lösung, die ich gefunden habe.
Itay Grudev
5
Dies ist die Lösung, die perfekt für mich funktioniert hat, ohne etwas anderes in meinem Seitenlayout zu verstopfen.
Jamie Carl
2
Die CSS-Lösung hat ein Problem, wenn sie mit der Liste in WebKit verwendet wird. Schauen Sie: stackoverflow.com/questions/39547773/…
Mert S. Kaplan
14
Es funktioniert nicht, wenn das Ziel eine obere Polsterung oder einen oberen Rand hat, da es auf dem Randkollaps beruht.
Krulik
9
:targetwar einfach nur brillant!
Endlos
125

Ich benutze diesen Ansatz:

/* add class="jumptarget" to all targets. */

.jumptarget::before {
  content:"";
  display:block;
  height:50px; /* fixed header height*/
  margin:-50px 0 0; /* negative fixed header height */
}

Vor jedem Ziel wird ein unsichtbares Element hinzugefügt. Es funktioniert IE8 +.

Hier sind weitere Lösungen: http://nicolasgallagher.com/jump-links-and-viewport-positioning/

Jeremias Erbs
quelle
Schauen Sie sich den Link Badabam zur Verfügung, es gibt eine zweite Lösung, die ich benutze und die in Chrome und Firefox funktioniert
Scavenger
Getestet auf dem neuesten Firefox (55.0.3 auf dem PC) und es funktioniert jetzt. :-)
RachieVee
46

Offizieller Bootstrap Angenommene Antwort:

*[id]:before { 
  display: block; 
  content: " "; 
  margin-top: -75px; // Set the Appropriate Height
  height: 75px; // Set the Appropriate Height
  visibility: hidden; 
}

Credits

Verschmelzen

blnc
quelle
1
Vielen Dank für die Aufnahme, +1 für die Vollständigkeit.
Amjoconn
2
Diese Lösung weist ein Problem auf, wenn sie mit list in WebKit verwendet wird. Schauen Sie: stackoverflow.com/questions/39547773/…
Mert S. Kaplan
Beachten Sie, dass dies nicht funktioniert, wenn das Zielelement selbst zufällig über display: flex;oder verfügt padding-top. Verwenden Sie <a name="my_link">{leave this empty}</a>in diesen Fällen ein spezielles Ankerelement (wie ).
WoodrowShigeru
Dies funktioniert nicht, wenn das
Ivan Gusev
42
html {
  scroll-padding-top: 70px; /* height of sticky header */
}

von: https://css-tricks.com/fixed-headers-on-page-links-and-overlapping-content-oh-my/

François Romain
quelle
Funktioniert bei mir. Ich navigiere von einer anderen Seite zum Anker. Andere haben nicht funktioniert. Vielen Dank!
Davidloper
1
Dies funktioniert nicht beim Scrollen der gesamten Seite in Edge und Safari ( bugs.webkit.org/show_bug.cgi?id=179379 ).
Juliusz Gonera
1
Retter! Einfach, auf den Punkt. Keine der anderen Lösungen hat bei mir funktioniert, da ich display: flex verwende. Vielen Dank, es war so frustrierend, alle Lösungen auszuprobieren.
Priya Payyavula
Dies ist eine SCHÖNE Lösung, ich habe das Scroll-Verhalten verwendet: glatt! Wichtig; auch vor Anker gehen, ganz einfach in zwei Codezeilen
yehanny
30

Der beste Weg, um dieses Problem zu lösen, ist (ersetzen Sie 65px durch Ihre feste Elementhöhe):

div:target {
  padding-top: 65px; 
  margin-top: -65px;
}

Wenn Sie nicht , wie das verwenden Zielwähler können Sie es auch auf diese Weise tun:

.my-target {
    padding-top: 65px;
    margin-top: -65px;
}

Hinweis: Dieses Beispiel funktioniert nicht, wenn das Zielelement eine von seinem übergeordneten Element abweichende Hintergrundfarbe aufweist. zum Beispiel:

<div style="background-color:red;height:100px;"></div>
<div class="my-target" style="background-color:green;height:100px;"></div>

In diesem Fall überschreibt die grüne Farbe meines Zielelements sein übergeordnetes rotes Element in 65px. Ich habe keine reine CSS-Lösung gefunden, um dieses Problem zu beheben. Wenn Sie jedoch keine andere Hintergrundfarbe haben, ist diese Lösung die beste.

Roy Shoa
quelle
2
Von allen Antworten ist dies die einzige, die für mich funktioniert hat!
Javier Arias
18

Während einige der vorgeschlagenen Lösungen für Fragment-Links (= Hash-Links) auf derselben Seite funktionieren (wie ein Menü-Link, der nach unten rollt), habe ich festgestellt, dass keiner von ihnen in aktuellem Chrome funktioniert, wenn Sie Fragment-Links verwenden möchten, die von anderen stammen Seiten .

Wenn Sie also www.mydomain.com/page.html#foo von Grund auf neu aufrufen, wird dies NICHT der Fall sein Ihr Ziel in aktuellem Chrome mit einer der angegebenen CSS- oder JS-Lösungen versetzt.

Es gibt auch einen jQuery-Fehlerbericht, der einige Details des Problems beschreibt.

LÖSUNG

Die einzige Option, die ich bisher gefunden habe und die wirklich in Chrome funktioniert, ist JavaScript, das nicht onDomReady heißt, sondern verzögert.

// set timeout onDomReady
$(function() {
    setTimeout(delayedFragmentTargetOffset, 500);
});

// add scroll offset to fragment target (if there is one)
function delayedFragmentTargetOffset(){
    var offset = $(':target').offset();
    if(offset){
        var scrollto = offset.top - 95; // minus fixed header height
        $('html, body').animate({scrollTop:scrollto}, 0);
    }
}

ZUSAMMENFASSUNG

Ohne JS-Verzögerung funktionieren Lösungen wahrscheinlich in Firefox, IE, Safari, aber nicht in Chrome.

Jpsy
quelle
3
Ich bin zu dem gleichen Schluss und der gleichen Lösung gekommen. Es scheint, als würde jeder andere Körper externe Links vergessen, die die Hashtags verwenden.
AJJ
Ich habe dieses Problem heute und ich habe Ihre Lösung verwendet. Obwohl es scheint, dass Sie keine Zeitüberschreitung benötigen. Dies funktioniert auch als IIFE.
Kwiat1990
1
@ kwiat1990: Ja, das ist möglicherweise möglich - aber nur, wenn Ihr JS ganz am Ende des HTML-Codes steht. Andernfalls befindet sich Ihr Bildlaufziel möglicherweise noch nicht im DOM. Eigentlich ist das der springende Punkt bei der Verwendung von onDomReady. Ich denke, die Timeout-Version ist der stabile Weg.
Jpsy
Diese Antwort war die einzige, die für externe Links funktionierte. Es funktioniert jedoch nicht für mich, wenn der Link auf derselben Seite aufgerufen wird :( Irgendwelche Ideen?
Augusto Samamé Barrientos
@Augusto hast du eine Lösung gefunden? Ich habe das gleiche Problem.
Jesse
9

Wenn die CSS Scroll Snap-Spezifikation ins Spiel kommt, ist dies mit der scroll-margin-topEigenschaft leicht möglich . Läuft derzeit auf Chrome und Opera (April 2019). Auch Safari 11+ sollte dies unterstützen, aber ich konnte es auf Safari 11 nicht ausführen. Wahrscheinlich müssen wir warten, bis die Jungs es dort reparieren.

Codepen Beispiel

body {
  padding: 0;
  margin: 0;
}

h1,
p {
  max-width: 40rem;
  margin-left: auto;
  margin-right: auto;
}
h1 {
  scroll-margin-top: 6rem; /* One line solution. :-) */
}
.header {
  position: sticky;
  top: 0;
  background-color: red;
  text-align: center;
  padding: 1rem;
}
.header .scroll {
  display: block;
  color: white;
  margin-bottom: 0.5rem;
}
.header .browsers {
  color: black;
  font-size: 0.8em;
}
<header class="header">
  <a class="scroll" href="#heading">Scroll to heading</a>
  <span class="browsers" >Chrome 69+, Opera 56+ and Safari 11+ only</span>
</header>
<p>
  Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
</p>
<h1 id="heading">What is Lorem Ipsum?</h1>
<p>
  Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
</p>
<p>
  

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent pulvinar eleifend dolor, in cursus augue interdum quis. Morbi volutpat pulvinar nisl et condimentum. Quisque elit lacus, egestas non ante sit amet, hendrerit commodo dui. Nunc ac sagittis dolor. Proin iaculis ante non est pharetra, et ullamcorper nisl accumsan. Aenean quis leo vel sapien eleifend aliquam. Pellentesque finibus dui ex, blandit tristique risus vestibulum vitae. Nam a quam ac turpis porta eleifend. Sed at hendrerit risus, ac efficitur ante. Aenean pretium justo feugiat condimentum consectetur. Etiam mattis urna id porta hendrerit.
</p>
<p>
Mauris venenatis quam sed egestas auctor. Fusce lacus eros, condimentum nec quam vel, malesuada gravida libero. Praesent vel sollicitudin justo. Donec mattis nisl id mauris scelerisque, quis placerat lectus scelerisque. Ut id justo a magna mattis luctus. Suspendisse massa est, pretium vel suscipit sit amet, iaculis at mi. Aenean vulputate ipsum non consectetur sodales. Proin aliquet erat nec mi eleifend, eu dapibus enim ultrices. Sed fringilla tortor ac rhoncus consectetur. Aliquam aliquam orci ultrices tortor bibendum facilisis.
</p>
<p>
Donec ultrices diam quam, non tincidunt purus scelerisque aliquam. Nam pretium interdum lacinia. Donec sit amet diam odio. Donec eleifend nibh ut arcu dictum, in vulputate magna malesuada. Nam id dignissim tortor. Suspendisse commodo, nunc sit amet blandit laoreet, turpis nibh rhoncus mi, et finibus nisi diam sed erat. Vivamus diam arcu, placerat in ultrices eu, porta ut tellus. Aliquam vel nisi nisi.
</p>
<p>
Integer ornare finibus sem, eget vulputate lacus ultrices ac. Vivamus aliquam arcu sit amet urna facilisis consectetur. Sed molestie dolor et tortor elementum, nec bibendum tortor cursus. Nulla ipsum nulla, luctus nec fringilla id, sagittis et sem. Etiam at dolor in libero pharetra consequat. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Suspendisse quis turpis non diam mattis varius. Praesent at gravida mi. Etiam suscipit blandit dolor, nec convallis lectus mattis vitae. Mauris placerat erat ipsum, vitae interdum mauris consequat quis. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</p>
<p>
Nunc efficitur scelerisque elit. Integer ac massa ipsum. Cras volutpat nulla purus, quis molestie dolor iaculis eget. Maecenas ut ex nulla. Pellentesque sem augue, ornare ut arcu eu, porttitor consectetur orci. Aenean iaculis blandit quam, in efficitur justo sodales auctor. Vivamus dignissim pellentesque risus eget consequat. Pellentesque sit amet nisi in urna convallis egestas vitae nec mauris. 
</p>

Dakur
quelle
1
Das ist ziemlich süß. Hoffen wir, dass es weiter verbreitet wird!
Tomalak
Was ist der Unterschied zwischen scroll-padding-topund scroll-margin-top?
Flimm
scroll-margin-topfür diesen Anwendungsfall ist in Safari 11-13 leider nicht implementiert: bugs.webkit.org/show_bug.cgi?id=189265
fabb
In Safari heißt es scroll-snap-margin-top: caniuse.com/#search=scroll-margin-top
Mu-Tsun Tsai
@ Mu-TsunTsai Es ist etwas komplizierter. Dies ist in Safari tatsächlich vorhanden, funktioniert jedoch nicht mit dem Scroll-to-Fragment-Verhalten. Siehe meinen Kommentar im Problem mit browserkompatiblen Daten: github.com/mdn/browser-compat-data/issues/…
dakur
8

Für Chrome / Safari / Firefox können Sie einen hinzufügen display: blockund einen negativen Rand verwenden, um den Versatz zu kompensieren, wie:

a[name] {
    display: block;
    padding-top: 90px;
    margin-top: -90px;
}

Siehe Beispiel http://codepen.io/swed/pen/RrZBJo

MrSwed
quelle
7

Sie können dies mit jQuery tun:

var offset = $('.target').offset();
var scrollto = offset.top - 50; // fixed_top_bar_height = 50px
$('html, body').animate({scrollTop:scrollto}, 0);
Webvitaly
quelle
Nicht ".target", sollte ": target" sein
Mert S. Kaplan
@ MertS.Kaplan ".target" ist die Klasse 'target'.
Webvitaly
7

Habe gerade eine andere reine CSS-Lösung entdeckt, die für mich wie ein Charme funktioniert hat!

html {
  scroll-padding-top: 80px; /* height of your sticky header */
}

Auf dieser Seite gefunden !

jamawe
quelle
2
Einige andere haben diese Lösung bereits vor Ihnen entdeckt. Lesen
Tomalak,
Sorry, habe es nicht bemerkt! Vielen Dank!
Jamawe
Dies funktioniert nicht beim Scrollen der gesamten Seite in Edge und Safari ( bugs.webkit.org/show_bug.cgi?id=179379 ).
Juliusz Gonera
5

Sie könnten dies versuchen:

<style>
h1:target { padding-top: 50px; }
</style>

<a href="#bar">Go to bar</a>

<h1 id="bar">Bar</h1>

Stellen Sie den oberen Füllwert auf die tatsächliche Höhe Ihres Headers ein. Dies führt zu einer kleinen zusätzlichen Lücke am oberen Rand Ihres Headers, die jedoch nur sichtbar ist, wenn der Benutzer zum Anker springt und dann einen Bildlauf nach oben durchführt. Ich habe diese Lösung gerade für meine Website entwickelt, aber sie zeigt nur einen kleinen festen Balken oben auf der Seite, nichts zu hoch.

ygoe
quelle
Mh. Nicht schlecht, aber immer noch ein ziemlicher Hack (und funktioniert leider nicht im IE).
Tomalak
5

Ich habe es leicht mit CSS und HTML zu tun, mit der oben erwähnten Methode "anchor: before". Ich denke, es funktioniert am besten, weil es keine massive Polsterung zwischen Ihren Divs erzeugt.

.anchor:before {
  content:"";
  display:block;
  height:60px; /* fixed header height*/
  margin:-60px 0 0; /* negative fixed header height */
}

Es scheint nicht für das erste Div auf der Seite zu funktionieren, aber Sie können dem entgegenwirken, indem Sie diesem ersten Div Padding hinzufügen.

#anchor-one{padding-top: 60px;}

Hier ist eine funktionierende Geige: http://jsfiddle.net/FRpHE/24/

Eric Wood
quelle
5

Für mich geht das:

HTML-LINK zum Anker:

<a href="#security">SECURITY</a>

HTML-Anker:

<a name="security" class="anchor"></a>

CSS:

.anchor::before {
    content: "";
    display: block;
    margin-top: -50px;
    position: absolute;
}
Avila
quelle
4

Ich verwende die Antwort von @ Jpsy, aber aus Leistungsgründen stelle ich den Timer nur ein, wenn der Hash in der URL vorhanden ist.

$(function() {
      // Only set the timer if you have a hash
      if(window.location.hash) {
        setTimeout(delayedFragmentTargetOffset, 500);
      }
  });

function delayedFragmentTargetOffset(){
      var offset = $(':target').offset();
      if(offset){
          var scrollto = offset.top - 80; // minus fixed header height
          $('html, body').animate({scrollTop:scrollto}, 0);
          $(':target').highlight();
      }
  };
sandre89
quelle
OP hat darum gebeten, kein Javascript zu verwenden.
Giulio Caccin
Funktioniert mit externen Links, jedoch nicht mit In-Page-Links.
Snap
4

Ich hatte große Probleme mit vielen der Antworten hier und anderswo, da meine mit Lesezeichen versehenen Anker Abschnittsüberschriften auf einer FAQ-Seite waren. Das Versetzen der Überschrift half also nicht, da der Rest des Inhalts einfach dort blieb, wo er war. Also dachte ich, ich würde posten.

Am Ende habe ich einige Lösungen zusammengestellt:

  1. Das CSS:

    .bookmark {
        margin-top:-120px;
        padding-bottom:120px; 
        display:block;
    }

Wobei "120px" Ihre feste Headerhöhe ist (möglicherweise plus etwas Rand).

  1. Der Lesezeichen-Link HTML:

    <a href="#01">What is your FAQ question again?</a>
  2. Der mit Lesezeichen versehene HTML-Inhalt:

    <span class="bookmark" id="01"></span>
    <h3>What is your FAQ question again?</h3>
    <p>Some FAQ text, followed by ...</p>
    <p>... some more FAQ text, etc ...</p>

Das Gute an dieser Lösung ist, dass das spanElement nicht nur ausgeblendet ist, sondern im Wesentlichen reduziert ist und Ihren Inhalt nicht ausfüllt.

Ich kann diese Lösung nicht sehr würdigen, da sie aus einer Vielzahl unterschiedlicher Ressourcen stammt, aber sie hat in meiner Situation am besten für mich funktioniert.

Das tatsächliche Ergebnis sehen Sie hier .

SteveCinq
quelle
1
Vielen Dank für das Teilen! So alt der Thread auch ist, es scheint immer noch keine kanonische Lösung für dieses Problem zu geben.
Tomalak
1
+ SteveCinq Sie haben meine Gedanken gelesen - ich hatte dieselben Probleme, bei denen gemeinsame Lösungen nicht wie vorhergesagt funktionierten. Das Hinzufügen des <span>mit dem Anker in der Spannweite zusammen mit dem Hinzufügen der Polsterung und des Randes funktionierte für mich. Vielen Dank, dass Sie sich die Zeit genommen haben, diese Antwort trotz des Alters des Threads einzureichen!
Twknab
4

Ich hatte kein Glück mit der oben aufgeführten Antwort und habe diese Lösung verwendet, die perfekt funktioniert hat ...

Erstellen Sie eine leere Spanne, in der Sie Ihren Anker setzen möchten.

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

Und wenden Sie die folgende Klasse an:

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

Diese Lösung funktioniert auch, wenn die Abschnitte unterschiedlich farbige Hintergründe haben! Ich habe die Lösung unter diesem Link gefunden.

Matt Underwood
quelle
1
Ist das nicht genau die gleiche Methode, die Guillaume Le Mière und einige andere in diesem Thread gezeigt haben?
Tomalak
Es ist sehr ähnlich, aber ich denke, es ist einfacher zu verstehen und eine detailliertere Antwort mit einem noch tieferen Link zu einer externen Quelle.
Matt Underwood
Es ist die gleiche Lösung, aber ich kann diese leicht verstehen und befolgen. Die anderen gaben mir nicht genug Informationen.
MacroMan
3

Für meinen puristischen Verstand fühlt es sich etwas hackig an, aber als reine CSS-Lösung können Sie dem aktiven verankerten Element mithilfe des :targetSelektors eine Auffüllung hinzufügen :

html, body {height:100%; min-height:100%; margin:0;}
body {min-height:200%;}
header {display:inline-block; position:fixed; font-size:1.5em; height:100px; top:0; left:0; right:0; line-height:100px; background:black; text-align:center;}
header a {color:#fff;}
section {padding:30px; margin:20px;}
section:first-of-type, section:target {padding-top:130px;}
<header><a href="#one">#One</a> <a href="#two">#two</a> <a href="#three">#three</a></header>
<section id="one"><h1>One</h1>Aenean lacinia bibendum nulla sed consectetur. Nullam id dolor id nibh ultricies vehicula ut id elit. Integer posuere erat a ante venenatis dapibus posuere velit aliquet.</section>
<section id="two"><h1>Two</h1>Aenean lacinia bibendum nulla sed consectetur. Nullam id dolor id nibh ultricies vehicula ut id elit. Integer posuere erat a ante venenatis dapibus posuere velit aliquet.</section>
<section id="three"><h1>Three</h1>Aenean lacinia bibendum nulla sed consectetur. Nullam id dolor id nibh ultricies vehicula ut id elit. Integer posuere erat a ante venenatis dapibus posuere velit aliquet.</section>

Moob
quelle
1
Das ist überhaupt nicht hacky! Schöne Lösung.
Tomalak
3

Ich musste sowohl die CSS-Lösungen von MutttenXd als auch von Badabam zusammen verwenden, da die erste in Chrome nicht funktionierte und die zweite in Firefox nicht funktionierte:

a.anchor { 
  padding-top: 90px;
}

a.anchor:before { 
  display: block;
  content: "";
  height: 90px;
  margin-top: -90px;
}

<a class="anchor" name="shipping"></a><h2>Shipping (United States)</h2>
...
Tshalif
quelle
3

Die Art und Weise, wie ich am saubersten finde, ist die folgende:

  #bar::before {
    display: block;
    content: " ";
    margin-top: -150px;
    height: 150px;
    visibility: hidden;
    pointer-events: none;
  }
Guillaume Le Mière
quelle
2

Ein minimal aufdringlicher Ansatz mit jQuery:

Verknüpfung:

<a href="#my-anchor-1" class="anchor-link">Go To Anchor 1</a>

Inhalt:

<h3 id="my-anchor-1">Here is Anchor 1</a>

Skript:

$(".anchor-link").click(function() {
    var headerHeight = 120;
    $('html, body').stop(true, true).animate({
        scrollTop: $(this.hash).offset().top - headerHeight
    }, 750);
    return false;
});

Durch Zuweisen der Anker-Link-Klasse zu den Links wird das Verhalten anderer Links (wie Akkordeon- oder Tab-Steuerelemente) nicht beeinflusst.

Die Frage will kein Javascript, aber die andere populärere Frage ist wegen dieser geschlossen und ich konnte sie dort nicht beantworten.

Hüseyin Yağlı
quelle
2

Ich brauchte etwas, das für eingehende Links, Links auf der Seite UND für JS geeignet ist, damit die Seite auf Änderungen in der Headerhöhe reagieren kann

HTML

<ul>
  <li><a href="#ft_who">Who?</a></li>
  <li><a href="#ft_what">What?</a></li>
  <li><a href="#ft_when">When?</a></li>
</ul>
...
<h2 id="ft_who" class="fragment-target">Who?</h2> 
...
<a href="#">Can I be clicked?</a>
<h2 id="ft_what" class="fragment-target">What?</h2>
...
<h2 id="ft_when" class="fragment-target">When?</h2> 

CSS

.fragment-target {
    display: block;
    margin-top: -HEADER_HEIGHTpx;
    padding-top: HEADER_HEIGHTpx;
    z-index: -1;
}

Das z-index: -1ermöglicht Links in der ‚Füll - Bereich‘ über einem Fragment-Ziel noch anklickbar zu sein, wie @MuttenXd auf seine Antwort kommentiert

Ich habe noch kein Problem in IE 11, Edge 15+, Chrome 38+, FF 52+ oder Safari 9.1+ gefunden

Arth
quelle
1
<div style="position:relative; top:-45px;">
    <a name="fragment"> </a>
</div>

Dieser Code sollte den Trick machen. Tauschen Sie 45px gegen die Höhe Ihrer Kopfleiste aus.

BEARBEITEN: Wenn die Verwendung von jQuery eine Option ist, habe ich auch jQuery.localScroll mit einem festgelegten Offsetwert erfolgreich verwendet. Die Offset-Option ist Teil von jQuery.scrollTo, auf dem jQuery.localScroll basiert. Eine Demo finden Sie hier: http://demos.flesler.com/jquery/scrollTo/ (zweites Fenster unter "Offset")

Fourk
quelle
Diese Lösung funktioniert zwar, ist aber nicht kugelsicher und erfordert viel Feinabstimmung für verschiedene Browser :( Guter Versuch. Ich suche nach einer Lösung ohne zusätzliches Markup.
Vlad Saling
Schade, dass dies so chaotisch ist, dass Sie nicht nur IDs verwenden können. Würde gerne eine Lösung finden, habe ich alle möglichen Dinge ausprobiert.
Theorie
1

Hier ist eine vollständige jquery-Lösung, die im IE funktioniert:

Angenommen, die Elemente der Navigationsleiste sehen ungefähr so ​​aus:

<ul>
    <li><a class="navigation" href="/#contact-us">Contact us</a></li>
    <li><a class="navigation" href="/#about-us">About us</a></li>
</ul>

Sie können das folgende jquery-Snippet verwenden, um den Bildlauf zu versetzen:

$(function() {
    $("a.navigation").click(function(event) {
        event.preventDefault();
        offSetScroll($(this));
    });
    offSetScrollFromLocation(window.location.href.toLowerCase());
});

function offSetScroll(anchor) {
    var href = anchor.attr("href");
    offSetScrollFromLocation(href);
}

function offSetScrollFromLocation(href) {
    //Change this according to the height of the navigation bar
    var fromTop = 250;
    if(href.indexOf("#")<=0)
        return;
    var hash=href.substring(href.indexOf("#"));
    var targetOffset = $(hash).offset().top-fromTop;
    $('html, body').animate({scrollTop: targetOffset}, 400, function(e) {

    });
}
Donner
quelle
Ich konnte eine leicht modifizierte Version dieses Codes von Thunder verwenden. Ich habe viele der reinen CSS-Lösungen und einfacheren Lösungen auf dieser Seite und auf stackoverflow.com/questions/10732690/… und auf stackoverflow.com/questions/10732690/… ausprobiert, aber sie waren aufgrund meiner Anforderungen nicht verwendbar. Die Seite ist eine FAQ-Seite mit vielen Ankern, auf denen sowohl von als auch außerhalb der Seite positioniert werden kann, sodass möglicherweise viele leere Stellen vorhanden sind. Fortsetzung im nächsten Kommentar ....
Jeffrey Simon
1
Damit es für mich funktioniert, sind hier die geringfügigen Änderungen: (1) Ändern Sie "<=" in der Zeile href.index in "<", um die Navigation auf der Seite zu ermöglichen. (2) "a.navigation" ändern, das für meine Verwendung "#faq a" sein musste; (3) Ändern Sie var von Top = 250 in einen ternären Wert basierend auf window.innerWidth für Unterschiede zwischen Mobilgeräten und Desktops. (4) Ändern Sie 400 in der Animation in 1, da die Animation nicht erwünscht ist und 0 nicht funktioniert; (5) Fügen Sie in der anonymen Funktion if ($ ('my-page-selector'). Länge vor dem Aufruf von offSetScrollFromLocation in der anonymen Funktion hinzu, um unnötige Aufrufe auf Seiten zu vermeiden, die nicht benötigt werden.
Jeffrey Simon
1

Die Implementierung mit :beforefunktionierte hervorragend, bis wir feststellten, dass das Pseudoelement tatsächlich Zeigerereignisse abdeckte und blockierte, die sich im Bereich des Pseudoelements befanden. Die Verwendung von etwas wie pointer-events: noneam :beforeoder sogar direkt am Anker hatte keine Auswirkungen.

Am Ende haben wir die Position des Ankers absolut gemacht und dann seine Position so angepasst, dass sie dem Versatz / der Höhe des festen Bereichs entspricht.

Versetzter Anker ohne Blockieren von Zeigerereignissen

.section-marker {

    position: absolute;
    top: -300px;
}

Der Wert dabei ist, dass wir keine Elemente blockieren, die unter diese 300px fallen könnten. Der Nachteil ist, dass beim Abrufen der Position dieses Elements aus Javascript dieser Versatz berücksichtigt werden muss, sodass die dortige Logik angepasst werden musste.

skabob11
quelle
1

So habe ich es geschafft, endlich an die richtige Stelle zu gelangen, wenn Sie auf die Navigation klicken. Ich habe einen Ereignishandler für die Navigationsklicks hinzugefügt. Dann können Sie einfach "scrollBy" verwenden, um den Versatz nach oben zu verschieben.

var offset = 90;

 $('.navbar li a').click(function(event) {
    event.preventDefault();
    $($(this).attr('href'))[0].scrollIntoView();
    scrollBy(0, -offset);
 });
Meile Mijatović
quelle
2
Löst das Problem, aber nicht den Teil "ohne die Hilfe von Javascript" ...
Tomalak
1

Ich habe ein Div mit ein paar Zeilenumbrüchen erstellt und diesem die ID gegeben. Dann habe ich den Code, den ich anzeigen wollte, darunter platziert. Der Link würde Sie dann zu dem Bereich über dem Bild führen und der Header würde nicht mehr im Weg sein:

<a href="#image">Image</a>
<div id="image"><br><br></div>
<img src="Image.png">

Natürlich können Sie die Anzahl der Zeilenumbrüche an Ihre Bedürfnisse anpassen. Dies hat perfekt für mich funktioniert, ich bin mir nicht sicher, ob es irgendwelche Probleme gibt, aber ich lerne immer noch HTML.

Anonym
quelle
Pragmatisch, aber es gibt einen Nachteil - es funktioniert nur für die erste Überschrift auf einer Seite. Wenn mehr Überschriften vorhanden sind, werden aufgrund der <br>Tags vor jeder Überschrift große Lücken im Text angezeigt.
Tomalak
1

Hat dieses Skript verwendet

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

    $('html, body').animate({
        scrollTop: $($.attr(this, 'href')).offset().top -140
    }, 1000);
});
Aadil Memon
quelle
Bitte versuchen Sie zu erklären, warum Sie glauben, dass dieses Skript das Problem lösen würde
Ali Kanat
1

Ich denke, dieser Ansatz ist nützlicher:

<h2 id="bar" title="Bar">Bar</h2>

[id]:target {
    display: block;
    position: relative;
    top: -120px;
    visibility: hidden;
}

[id]:target::before {
    content: attr(title);
    top: 120px;
    position: relative;
    visibility: visible;
}
Enes Shahin
quelle