Naprawiono nakładanie się nagłówków stron na kotwice na stronie


358

Jeśli na stronie HTML mam nagłówek nieprzewijający, przymocowany do góry, o określonej wysokości:

Czy istnieje sposób użycia zakotwiczenia adresu URL ( #fragmentczęści), aby przeglądarka przewinęła się do określonego miejsca na stronie, ale nadal szanowała wysokość stałego elementu bez pomocy JavaScript ?

http://foo.com/#bar
ŹLE (ale powszechne zachowanie): PRAWIDŁOWO:
+ --------------------------------- + + -------------- ------------------- +
| BAR ///////////////////// nagłówek | | //////////////////////// header |
+ --------------------------------- + + -------------- ------------------- +
| Oto reszta tekstu | | BAR |
| ... | | |
| ... | | Oto reszta tekstu |
| ... | | ... |
+ --------------------------------- + + -------------- ------------------- +



3
@ax TAK, to najlepsza odpowiedź. Sprawdź także nicolasgallagher.com/jump-links-and-viewport-positioning/demo w nim. To działało najlepiej dla mnie:.dislocate50px, #bar { padding: 50px 0 0; margin: -50px 0 0; -webkit-background-clip: content-box; background-clip: content-box; }
flen

szukam rozwiązania, które * działa na kotwice przychodzące z tej samej strony lub innej strony, * i które dostosowuje naciśnięcie klawisza page-down, aby zawartość nie była przycinana przez nagłówek, * i która pozwala stopce sib-div na przewiń w górę za pomocą content-div. Nie znalazłem jeszcze rozwiązania! Ale muszę powiedzieć, myślę, że właściwy sposób byłby skierowany na całą zawartość div, a nie na każdą pojedynczą kotwicę. stackoverflow.com/questions/51070758/...
John, dlaczego

@topór. CSS-tricks.com ma o wiele lepszy nowszy artykuł na ten temat scroll-padding-top: css-tricks.com/… Odpowiadająca odpowiedź: stackoverflow.com/a/56467997/247696
Flimm

Odpowiedzi:


167

Miałem ten sam problem. Rozwiązałem go, dodając klasę do elementu kotwiczącego o wysokości górnego paska jako wartości dopełnienia.

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

A potem po prostu css:

.anchor { padding-top: 90px; }

19
@Tomalak Należy pamiętać, że dzięki temu rozwiązaniu linki w obszarze wypełnienia są niemożliwe do kliknięcia. Aby to naprawić, musisz użyć indeksu Z i ustawić wartość linków wyższą niż wartość kotwicy. Pamiętaj, że górny pasek powinien mieć najwyższą wartość indeksu Z, aby zawartość strony nie unosiła się na górnym pasku podczas przewijania.
MutttenXd

Nie działał w Chrome v28 z powodu błędu stałego położenia WebKit powodującego znikanie nagłówka. Ta odpowiedź sprawdziła się w mojej sprawie.
Knickedi

2
MuttenXd .. jesteś moim bohaterem. Miałem dziwny problem z linkiem, który nie działał na mojej stronie (niezwiązany z kotwicami) doprowadzał mnie do szaleństwa. Twój niemożliwy do kliknięcia komentarz naprawdę pomógł. Jestem ci coś winien!
zipzit

9
Jak zasugerowano w odpowiedzi Roya Shoa, dodaj, margin-top: -90px;aby zlikwidować lukę utworzoną przez wypełnienie.
Skippy le Grand Gourou

37
Użyłem .anchor:target {padding-top: 90px;}tak, że dodało to dopełnienie tylko wtedy, gdy użyli tagu kotwicy. W ten sposób nie zawsze jest mnóstwo dopełnienia, jeśli strona ładuje się u góry. Tylko wtedy, gdy ładuje określony punkt niżej na stronie.
jimmyplaysdrums

265

Jeśli nie możesz lub nie chcesz ustawić nowej klasy, dodaj ::beforepseudoelement o stałej wysokości do :targetpseudoklasy w CSS:

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

Lub przewiń stronę względem :targetjQuery:

var offset = $(':target').offset();
var scrollto = offset.top - 60; // minus fixed header height
$('html, body').animate({scrollTop:scrollto}, 0);

30
Naprawdę podoba mi się twoje rozwiązanie. To najczystsze rozwiązanie, jakie znalazłem.
Itay Grudev

5
Jest to rozwiązanie, które działało idealnie dla mnie bez upychania czegokolwiek innego w moim układzie strony.
Jamie Carl,

2
Rozwiązanie CSS ma problem, gdy jest używane z listą w WebKit. Spójrz: stackoverflow.com/questions/39547773/…
Mert S. Kaplan

14
Nie będzie działać, jeśli cel ma górne wypełnienie lub ramkę, ponieważ opiera się na zwinięciu marginesu.
krulik

9
:targetbyło po prostu genialne!
Endless

125

Używam tego podejścia:

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

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

Dodaje niewidoczny element przed każdym celem. Działa IE8 +.

Oto więcej rozwiązań: http://nicolasgallagher.com/jump-links-and-viewport-positioning/


spójrz na link podany przez Badabam, istnieje drugie rozwiązanie, którego używam i które działa w Chrome i Firefox
padlinożerca

Przetestowałem to w najnowszym Firefoksie (55.0.3 na PC) i działa teraz. :-)
RachieVee,

46

Oficjalna przyjęta odpowiedź Bootstrap:

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

Kredyty

Łączyć


1
Bardzo dziękuję za uwzględnienie tego, +1 za kompletność.
amjoconn,

2
To rozwiązanie ma problem, gdy jest używane z listą w WebKit. Spójrz: stackoverflow.com/questions/39547773/…
Mert S. Kaplan

Zauważ, że to nie zadziała, jeśli sam element docelowy ma display: flex;lub padding-top. <a name="my_link">{leave this empty}</a>W takich przypadkach używaj dedykowanego elementu kotwiczącego (podobnego ).
WoodrowShigeru,

To nie zadziała, jeśli elementem docelowym jest <tr>
Ivan Gusev

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

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



Pracuje dla mnie. Przechodzę do kotwicy z innej strony. Inni nie działali. Dzięki!
davidloper,

1
Nie działa to w przypadku przewijania całej strony w Edge i Safari ( bugs.webkit.org/show_bug.cgi?id=179379 ).
Juliusz Gonera,

1
Zbawiciel! Proste, w punkcie. Żadne inne rozwiązanie nie działało dla mnie, ponieważ używam display: flex. Dzięki tonie, tak frustrujące było wypróbowanie wszystkich rozwiązań.
Priya Payyavula

To jest PIĘKNE rozwiązanie, użyłem zachowania przewijania: gładkie! Ważne; również do zakotwiczenia, naprawdę proste w dwóch wierszach kodu
yehanny

30

Najlepszym sposobem na rozwiązanie tego problemu jest (zamień 65 pikseli na ustaloną wysokość elementu):

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

Jeśli nie chcesz używać selektora docelowego , możesz to zrobić w ten sposób:

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

Uwaga: ten przykład nie zadziała, jeśli element docelowy ma kolor tła inny niż jego element nadrzędny. na przykład:

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

w tym przypadku zielony kolor elementu my-target nadpisze jego macierzysty czerwony element w rozmiarze 65 pikseli. Nie znalazłem żadnego czystego rozwiązania CSS do obsługi tego problemu, ale jeśli nie masz innego koloru tła, to rozwiązanie jest najlepsze.


2
Spośród wszystkich odpowiedzi jest to jedyna, która dla mnie zadziałała!
Javier Arias,

18

Chociaż niektóre z proponowanych rozwiązań działają w przypadku fragmentarycznych linków (= linków skrótu) na tej samej stronie (np. Linku menu przewijanego w dół), stwierdziłem, że żadne z nich nie działało w bieżącym Chrome, gdy chcesz użyć fragmentów linków pochodzących z innych strony .

Tak więc wywołanie od podstaw www.mydomain.com/page.html#foo NIE zrównoważy celu w obecnym Chrome za pomocą żadnego z podanych rozwiązań CSS lub JS.

Istnieje również raport o błędach jQuery opisujący niektóre szczegóły problemu.

ROZWIĄZANIE

Jedyną dostępną do tej pory opcją, która naprawdę działa w Chrome, jest JavaScript, który nie jest wywoływany onDomReady, ale z opóźnieniem.

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

PODSUMOWANIE

Bez opóźnień JS rozwiązania prawdopodobnie będą działać w Firefox, IE, Safari, ale nie w Chrome.


3
Doszedłem do tego samego wniosku i rozwiązania. Wygląda na to, że każde inne ciało zapomina o zewnętrznych linkach, które używają hashtagów.
AJJ

Mam dzisiaj ten problem i skorzystałem z twojego rozwiązania. Chociaż wydaje się, że nie potrzebujesz limitu czasu. Działa to również jako IIFE.
kwiat1990

1
@ kwiat1990: Tak, to może być możliwe - ale tylko wtedy, gdy JS znajduje się na samym końcu kodu HTML. W przeciwnym razie cel przewijania może nie znajdować się jeszcze w DOM. Właśnie o to chodzi w korzystaniu z onDomReady. Wydaje mi się, że wersja z limitem czasu jest stabilną drogą.
Jpsy,

Ta odpowiedź była jedyną, która działała w przypadku linków zewnętrznych. Jednak dla mnie to nie działa, gdy link jest wywoływany na tej samej stronie :( Wszelkie pomysły?
Augusto Samamé Barrientos

@Augusto znalazłeś rozwiązanie? Mam ten sam problem.
Jesse,

9

Ponieważ specyfikacja CSS Scroll Snap wchodzi do gry, jest to możliwe z scroll-margin-topwłaściwością. Obecnie działa na Chrome i Operze (kwiecień 2019). Również Safari 11+ powinno to obsługiwać, ale nie udało mi się uruchomić go na Safari 11. Prawdopodobnie musimy poczekać, aż faceci to naprawią.

Przykład Codepen

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>


1
To całkiem słodkie. Miejmy nadzieję, że zostanie przyjęty szerzej!
Tomalak,

Jaka jest różnica między scroll-padding-topi scroll-margin-top?
Flimm,

scroll-margin-topw tym przypadku użycia niestety nie jest zaimplementowany w Safari 11-13: bugs.webkit.org/show_bug.cgi?id=189265
fabb

W Safari nazywa się to scroll-snap-margin-top: caniuse.com/#search=scroll-margin-top
Mu-Tsun Tsai

@ Mu-TsunTsai To jest trochę bardziej skomplikowane. To naprawdę istnieje w Safari, ale nie działa z zachowaniem przewijania do fragmentu. Zobacz mój komentarz do wydania dotyczącego kompatybilności przeglądarki
dakur

8

W przypadku Chrome / Safari / Firefox możesz dodać a display: blocki użyć ujemnego marginesu, aby skompensować przesunięcie, na przykład:

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

Zobacz przykład http://codepen.io/swed/pen/RrZBJo


7

Możesz to zrobić za pomocą jQuery:

var offset = $('.target').offset();
var scrollto = offset.top - 50; // fixed_top_bar_height = 50px
$('html, body').animate({scrollTop:scrollto}, 0);

Nie „.target”, powinno być „: target”
Mert S. Kaplan

@ MertS.Kaplan „.target” to klasa „cel”.
webvitaly

7

Właśnie odkryłem inne czyste rozwiązanie CSS, które działało dla mnie jak urok!

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

Znalezione na tej stronie !


2
Kilka innych odkryło to rozwiązanie przed tobą, zobacz odpowiedzi na stronie 1, na przykład stackoverflow.com/a/56467997/18771
Tomalak

Przepraszam, nie zauważyłem! Dzięki!
jamawe,

Nie działa to w przypadku przewijania całej strony w Edge i Safari ( bugs.webkit.org/show_bug.cgi?id=179379 ).
Juliusz Gonera,

5

Możesz spróbować:

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

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

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

Ustaw górną wartość dopełniania na rzeczywistą wysokość nagłówka. Spowoduje to wprowadzenie niewielkiej dodatkowej przerwy w górnej części nagłówka, ale będzie widoczne tylko wtedy, gdy użytkownik wskoczy na kotwicę, a następnie przewinie w górę. Właśnie wymyśliłem to rozwiązanie dla mojej witryny, ale pokazuje tylko mały stały pasek u góry strony, nic zbyt wysokiego.


Mh Nieźle, ale wciąż dość hack (i niestety nie działa w IE).
Tomalak

5

Mam go łatwo współpracować z CSS i HTML, używając wyżej wspomnianej metody „anchor: before”. Myślę, że działa najlepiej, ponieważ nie tworzy masywnego wypełnienia między twoimi divami.

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

Wydaje się, że nie działa dla pierwszego div na stronie, ale możesz temu przeciwdziałać, dodając dopełnianie do tego pierwszego diva.

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

Oto działające skrzypce: http://jsfiddle.net/FRpHE/24/


5

Mi to pasuje:

HTML LINK to Anchor:

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

Kotwica HTML:

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

CSS:

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

4

Korzystam z odpowiedzi @ Jpsy, ale ze względu na wydajność ustawiam timer tylko wtedy, gdy skrót znajduje się w adresie URL.

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

OP poprosił, aby nie używać javascript.
Giulio Caccin,

Działa z linkami zewnętrznymi, ale nie z linkami na stronie.
przyciągnąć

4

Miałem wiele problemów z wieloma odpowiedziami tutaj i gdzie indziej, ponieważ moje zakotwiczone zakładki były nagłówkami sekcji na stronie często zadawanych pytań, więc przesunięcie nagłówka nie pomogło, ponieważ reszta treści pozostanie tam, gdzie była. Więc pomyślałem, że opublikuję.

Skończyło się na kilku rozwiązaniach:

  1. CSS:

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

Gdzie „120px” to ustalona wysokość nagłówka (może plus margines).

  1. Link do zakładki HTML:

    <a href="#01">What is your FAQ question again?</a>
  2. Kod HTML treści z zakładkami:

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

Zaletą tego rozwiązania jest to, że span element jest nie tylko ukryty, ale przede wszystkim jest zwinięty i nie usuwa zawartości.

Nie mogę liczyć na duże uznanie za to rozwiązanie, ponieważ pochodzi ono z różnych zasobów, ale w mojej sytuacji najlepiej się sprawdzało.

Rzeczywisty wynik można zobaczyć tutaj .


1
Dziękuję bardzo za udostępnienie! Choć wątek jest stary, wydaje się, że nie ma jednego kanonicznego rozwiązania tego problemu.
Tomalak,

1
+ SteveCinq Czytasz mi w myślach - miałem do czynienia z tymi samymi problemami, w których wspólne rozwiązania nie działały zgodnie z przewidywaniami. Dodanie <span>z kotwicą w przęsle, wraz z dopełnieniem i marginesem działało dla mnie. Dziękujemy bardzo za poświęcenie czasu na przesłanie tej odpowiedzi, pomimo wieku wątku!
twknab

4

Nie miałem szczęścia z powyższą odpowiedzią i ostatecznie skorzystałem z tego rozwiązania, które działało idealnie ...

Utwórz pusty zakres, w którym chcesz ustawić kotwicę.

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

I zastosuj następującą klasę:

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

To rozwiązanie będzie działać, nawet jeśli sekcje mają różne kolorowe tła! Znalazłem rozwiązanie pod tym linkiem.


1
Czy nie jest to dokładnie ta sama metoda, którą Guillaume Le Mière i kilka innych osób pokazało w tym wątku?
Tomalak,

Jest bardzo podobny, ale myślę, że łatwiej go zrozumieć i uzyskać bardziej szczegółową odpowiedź z jeszcze głębszym łączem do zewnętrznego źródła.
Matt Underwood,

To jest to samo rozwiązanie, ale mogę je łatwo zrozumieć i zastosować. Inni nie udzielili mi wystarczających informacji.
MacroMan

3

Moim purystycznym umysłom wydaje się to nieco nieprzyzwoite, ale jako rozwiązanie dostępne tylko w css można dodać dopełnienie do aktywnego zakotwiczonego elementu za pomocą :targetselektora:

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>


1
To wcale nie jest zuchwałe! Niezłe rozwiązanie.
Tomalak

3

Odkryłem, że musiałem używać zarówno rozwiązań CSS firmy MutttenXd, jak i Badabam , ponieważ pierwszy nie działał w Chrome, a drugi w Firefox:

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

3

Sposób, w jaki uważam się za najczystszego, jest następujący:

  #bar::before {
    display: block;
    content: " ";
    margin-top: -150px;
    height: 150px;
    visibility: hidden;
    pointer-events: none;
  }

2

Minimalnie inwazyjne podejście przy użyciu jQuery:

Połączyć:

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

Zadowolony:

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

Scenariusz:

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

Przypisując do linków klasę anchor-link, nie ma to wpływu na zachowanie innych linków (takich jak kontrolki akordeonu lub tabulatorów).

Pytanie nie chce javascript, ale inne popularne pytanie jest zamknięte z tego powodu i nie mogłem tam odpowiedzieć.


2

Potrzebowałem czegoś, co działa na linki przychodzące, linki na stronie ORAZ i może być celem JS, aby strona mogła reagować na zmiany wysokości nagłówka

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

z-index: -1Pozwala linki w „obszaru dopełnienia” powyżej fragmentu docelowymi aby nadal być klikalne, jak komentował @MuttenXd na jego odpowiedź

Nie znalazłem jeszcze problemu w IE 11, Edge 15+, Chrome 38+, FF 52+ lub Safari 9.1+


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

Ten kod powinien załatwić sprawę. Zamień 45px na wysokość paska nagłówka.

EDYCJA: Jeśli korzystasz z jQuery jest opcją, również odniosłem sukces używając jQuery.localScroll z ustawioną wartością przesunięcia. Opcja offset jest częścią jQuery.scrollTo, na której zbudowano jQuery.localScroll. Demo jest dostępne tutaj: http://demos.flesler.com/jquery/scrollTo/ (drugie okno, pod „offsetem”)


to rozwiązanie działa rzeczywiście, ale to nie jest kuloodporny i wymaga dużo dostrajanie dla różnych przeglądarek :( wspaniałą okazję thoug szukam rozwiązania bez dodatkowych znaczników..
Vlad SALING

Szkoda, że ​​jest tak bałaganiarski, że nie możesz po prostu używać identyfikatorów. Chciałbym znaleźć rozwiązanie, próbowałem różnych rzeczy.
teoretuje

1

Oto kompletne rozwiązanie jquery, które będzie działać w IE:

Załóżmy, że elementy paska nawigacji wyglądają mniej więcej tak:

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

Aby przesunąć przewijanie, możesz użyć następującego fragmentu jquery:

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

    });
}

Byłem w stanie użyć nieco zmodyfikowanej wersji tego kodu z Thunder. Wypróbowałem wiele prostych i CSS-owych rozwiązań na tej stronie i na stackoverflow.com/questions/10732690/... oraz na stackoverflow.com/questions/10732690/…, ale nie były one użyteczne z powodu moich wymagań. Strona jest często zadawanym pytaniem z wieloma kotwicami do pozycjonowania, zarówno na stronie, jak i poza nią, więc może mieć wiele pustych miejsc. Kontynuacja w następnym komentarzu ....
Jeffrey Simon

1
Aby działało to dla mnie, oto kilka drobnych zmian: (1) zmień „<=” w wierszu href.index na „<”, aby umożliwić nawigację na stronie; (2) zmień „a. Nawigację”, która musiała być „#faq a” dla mojego użytku; (3) zmień var z Top = 250 na trójskładnikowy na podstawie window.innerWidth dla różnic między urządzeniami mobilnymi a komputerowymi; (4) zmień 400 w animacji na 1, ponieważ animacja nie jest pożądana, a 0 nie działa; (5) dodaj if ($ ('my-page-selector'). Długość przed wywołaniem offSetScrollFromLocation w funkcji anonimowej, aby zapobiec niepotrzebnym wywołaniom na stronach, gdzie nie są potrzebne.
Jeffrey Simon

1

Wdrożenie przy użyciu :beforedziałało świetnie, dopóki nie zdaliśmy sobie sprawy, że pseudoelement faktycznie zakrywa i blokuje zdarzenia wskaźnika znajdujące się w obszarze pseudoelementu. Używanie czegoś pointer-events: nonena :beforekotwicy lub nawet bezpośrednio na kotwicy nie miało wpływu.

Skończyło się na tym, że położenie kotwicy było absolutne, a następnie dostosowanie jego pozycji, aby było przesunięciem / wysokością ustalonego obszaru.

Przesunięcie kotwicy bez blokowania zdarzeń wskaźnika

.section-marker {

    position: absolute;
    top: -300px;
}

Wartość tego polega na tym, że nie blokujemy żadnych elementów, które mogłyby mieścić się w tych 300px. Minusem jest to, że pobieranie pozycji tego elementu z Javascript musi uwzględniać to przesunięcie, więc wszelkie logiki muszą zostać dostosowane.


1

W ten sposób udało mi się w końcu przejść do właściwego miejsca po kliknięciu nawigacji. Dodałem moduł obsługi zdarzeń dla kliknięć nawigacji. Następnie możesz po prostu użyć „scrollBy”, aby przejść w górę o przesunięcie.

var offset = 90;

 $('.navbar li a').click(function(event) {
    event.preventDefault();
    $($(this).attr('href'))[0].scrollIntoView();
    scrollBy(0, -offset);
 });

2
Rozwiązuje problem, ale nie część „bez pomocy Javascript” ...
Tomalak

1

Utworzyłem div z kilkoma podziałami linii i podałem ten identyfikator, a następnie umieściłem poniżej kod, który chciałem pokazać. Link zabierze Cię następnie do miejsca nad obrazem, a nagłówek nie będzie już przeszkadzał:

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

Oczywiście możesz zmienić liczbę podziałów linii w zależności od potrzeb. Działa to dla mnie idealnie, nie jestem pewien, czy są jakieś problemy, wciąż uczę się HTML.


Pragmatyczny, ale ma pewną wadę - działa tylko w przypadku pierwszego nagłówka na stronie. Jeśli jest więcej nagłówków, zaczniesz widzieć duże przerwy w tekście z powodu <br>znaczników przed każdym nagłówkiem.
Tomalak,

1

Użyłem tego skryptu

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

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

Spróbuj wyjaśnić, dlaczego według ciebie ten skrypt rozwiązałby problem
Ali Kanat

1

Myślę, że to podejście jest bardziej przydatne:

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.