L'intestazione di pagina fissa si sovrappone alle ancore in-page


358

Se ho un'intestazione senza scorrimento in una pagina HTML, fissata in alto, con un'altezza definita:

C'è un modo per usare l'ancoraggio URL (la #fragmentparte) per far scorrere il browser fino a un certo punto della pagina, ma rispettare comunque l'altezza dell'elemento fisso senza l'aiuto di JavaScript ?

http://foo.com/#bar
SBAGLIATO (ma il comportamento comune): CORRETTO:
+ --------------------------------- + + -------------- ------------------- +
| BAR ///////////////////// header | | //////////////////////// |
+ --------------------------------- + + -------------- ------------------- +
| Ecco il resto del testo | | BAR |
| ... | | |
| ... | | Ecco il resto del testo |
| ... | | ... |
+ --------------------------------- + + -------------- ------------------- +



3
@ax YES, questa è la risposta migliore. Controlla anche nicolasgallagher.com/jump-links-and-viewport-positioning/demo al suo interno. Questo ha funzionato meglio per me:.dislocate50px, #bar { padding: 50px 0 0; margin: -50px 0 0; -webkit-background-clip: content-box; background-clip: content-box; }
flen

sto cercando una soluzione che * funzioni per ancore provenienti dalla stessa pagina o altra pagina * e che regola la pressione del tasto di scorrimento della pagina in modo che il contenuto non venga troncato dall'intestazione * e che consenta al piè di pagina di sib-div di scorrere verso l'alto con content-div. Non ho ancora trovato una soluzione! Ma devo dire che penso che il modo giusto mirerebbe all'intero div contenuto e non a ogni singola ancora. stackoverflow.com/questions/51070758/...
Johny perché

@ascia. CSS-tricks.com ha un articolo molto meglio più recente su scroll-padding-topqui: css-tricks.com/... risposta corrispondente: stackoverflow.com/a/56467997/247696
Flimm

Risposte:


167

Ho avuto lo stesso problema. L'ho risolto aggiungendo una classe all'elemento di ancoraggio con l'altezza della barra superiore come valore di riempimento superiore.

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

E poi semplicemente il css:

.anchor { padding-top: 90px; }

19
@Tomalak Tenere presente che questa soluzione rende i collegamenti all'interno dell'area di riempimento non selezionabili. Per risolvere questo problema è necessario utilizzare z-index e impostare il valore dei collegamenti su un valore superiore a quello dell'ancora. Ricorda che la barra superiore dovrebbe avere il valore z-index più alto, quindi il contenuto della pagina non galleggia sopra la barra superiore durante lo scorrimento.
MutttenXd

Non ha funzionato in Chrome v28 a causa di un bug di posizione fissa WebKit che faceva scomparire l'intestazione. Questa risposta ha funzionato nel mio caso.
Knickedi,

2
MuttenXd .. sei il mio eroe. Ho avuto uno strano problema di collegamento non funzionale sul mio sito (non correlato alle ancore) che mi stava facendo impazzire. Il tuo commento non cliccabile ha davvero aiutato. Ti devo un grande!
zipzit

9
Come suggerito nella risposta di Roy Shoa, aggiungi margin-top: -90px;per contrastare il gap creato dall'imbottitura.
Skippy le Grand Gourou,

37
L'ho usato in .anchor:target {padding-top: 90px;}modo che aggiungesse l'imbottitura solo quando utilizzavano il tag anchor. In questo modo non c'è sempre un sacco di riempimento se la pagina viene caricata in alto. Solo quando carica un punto specifico in basso nella pagina.
jimmyplaysdrums,

265

Se non puoi o non vuoi impostare una nuova classe, aggiungi uno ::beforepseudo-elemento ad altezza fissa alla :targetpseudo-classe in CSS:

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

Oppure scorri la pagina rispetto a :targetcon jQuery:

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

30
Mi piace molto la tua soluzione. È la soluzione più pulita che ho trovato.
Itay Grudev,

5
Questa è la soluzione che ha funzionato perfettamente per me senza riempire nient'altro nel mio layout di pagina.
Jamie Carl,

2
La soluzione CSS ha un problema quando viene utilizzata con l'elenco in WebKit. Guarda: stackoverflow.com/questions/39547773/…
Mert S. Kaplan,

14
Non funzionerà se il bersaglio ha un'imbottitura o un bordo superiore poiché si basa sul margine di collasso.
Krulik,

9
:targetera semplicemente geniale!
Endless il

125

Uso questo approccio:

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

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

Aggiunge un elemento invisibile prima di ogni target. Funziona IE8 +.

Ecco altre soluzioni: http://nicolasgallagher.com/jump-links-and-viewport-positioning/


guarda il link fornito da Badabam, c'è una seconda soluzione, che uso e che funziona in Chrome e Firefox
scavenger

Ho provato questo sull'ultimo Firefox (55.0.3 su PC) e funziona ora. :-)
RachieVee,

46

Risposta adottata Bootstrap ufficiale:

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

Crediti

Merge


1
Grazie mille per aver incluso questo, +1 per completezza.
amjoconn,

2
Questa soluzione presenta un problema se utilizzata con l'elenco in WebKit. Guarda: stackoverflow.com/questions/39547773/…
Mert S. Kaplan,

Si noti che questo non funzionerà se l'elemento target stesso ha display: flex;o padding-top. Usa un elemento di ancoraggio dedicato (come <a name="my_link">{leave this empty}</a>) in quei casi.
Woodrow Shigeru,

Questo non funzionerà se l'elemento target è <tr>
Ivan Gusev il

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

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



Per me va bene. Sto navigando verso l'ancora da un'altra pagina. Altri non hanno funzionato. Grazie!
davidloper,

1
Questo non funziona per lo scorrimento dell'intera pagina in Edge e Safari ( bugs.webkit.org/show_bug.cgi?id=179379 ).
Juliusz Gonera il

1
Salvatore! Semplice, puntuale. Nessuna delle altre soluzioni ha funzionato per me perché sto usando display: flex. Grazie mille, è stato così frustrante provare tutte le soluzioni.
Priya Payyavula

Questa è una BELLA soluzione, ho usato il comportamento a scorrimento: liscio! Importante; anche per andare all'ancora, davvero semplice in due righe di codice
yehanny

30

Il modo migliore che ho trovato per gestire questo problema è (sostituire 65 px con l'altezza dell'elemento fisso):

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

Se non ti piace utilizzare il selettore di destinazione , puoi farlo anche in questo modo:

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

Nota: questo esempio non funzionerà se l'elemento target ha un colore di backgound diverso dal suo genitore. per esempio:

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

in questo caso il colore verde dell'elemento my-target sovrascriverà l'elemento rosso padre in 65px. Non ho trovato alcuna soluzione CSS pura per gestire questo problema, ma se non hai un altro colore di sfondo questa soluzione è la migliore.


2
Tra tutte le risposte, questa è l'unica che ha funzionato per me!
Javier Arias,

18

Mentre alcune delle soluzioni proposte funzionano per collegamenti a frammenti (= collegamenti hash) all'interno della stessa pagina (come un collegamento a menu che scorre verso il basso), ho scoperto che nessuna di loro ha funzionato nell'attuale Chrome quando si desidera utilizzare collegamenti a frammenti provenienti da altri pagine .

Quindi, chiamare www.mydomain.com/page.html#foo da zero NON compenserà il tuo obiettivo nell'attuale Chrome con nessuna delle soluzioni CSS o JS fornite.

C'è anche una segnalazione di bug jQuery che descrive alcuni dettagli del problema.

SOLUZIONE

L'unica opzione che ho trovato finora che funziona davvero in Chrome è JavaScript che non si chiama onDomReady ma con un ritardo.

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

SOMMARIO

Senza un ritardo JS, le soluzioni funzioneranno probabilmente in Firefox, IE, Safari, ma non in Chrome.


3
Sono giunto alla stessa conclusione e soluzione. Sembra che ogni altro corpo stia dimenticando i collegamenti esterni che usano gli hashtag.
AJJ,

Ho questo problema oggi e ho usato la tua soluzione. Anche se sembra che non sia necessario il timeout. Funziona anche come IIFE.
kwiat1990,

1
@ kwiat1990: Sì, potrebbe essere possibile, ma solo se il tuo JS è posizionato alla fine del codice HTML. In caso contrario, la destinazione di scorrimento potrebbe non essere ancora nel DOM. In realtà questo è il punto centrale dell'utilizzo di onDomReady. Quindi immagino che la versione di timeout sia la strada stabile da percorrere.
Jpsy

Questa risposta è stata l'unica che ha funzionato per i collegamenti esterni. Tuttavia non funziona per me quando il link viene chiamato nella stessa pagina :( Qualche idea?
Augusto Samamé Barrientos,

@Augusto hai trovato una soluzione? Sto avendo lo stesso problema.
Jesse,

9

Quando le specifiche CSS Snap Snap entrano in gioco, è facilmente possibile con la scroll-margin-topproprietà. Attualmente funziona su Chrome e Opera (aprile 2019). Anche Safari 11+ dovrebbe supportare questo, ma non sono stato in grado di eseguirlo su Safari 11. Probabilmente dobbiamo aspettare che i ragazzi lo riparino lì.

Esempio 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
È piuttosto dolce. Speriamo che venga adottato più ampiamente!
Tomalak,

Qual è la differenza tra scroll-padding-tope scroll-margin-top?
Flimm,

scroll-margin-topper questo caso d'uso purtroppo non è implementato in Safari 11-13: bugs.webkit.org/show_bug.cgi?id=189265
fabb

In Safari si chiama scroll-snap-margin-top: caniuse.com/#search=scroll-margin-top
Mu-Tsun Tsai

@ Mu-TsunTsai È un po 'più complicato. Questo esiste davvero su Safari, ma non funziona con il comportamento da scorrimento a frammento. Vedi il mio commento nel problema dei dati compatibili con il browser: github.com/mdn/browser-compat-data/issues/…
dakur

8

Per Chrome / Safari / Firefox è possibile aggiungere un display: blocke utilizzare un margine negativo per compensare l'offset, come:

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

Vedi esempio http://codepen.io/swed/pen/RrZBJo


7

Puoi farlo con jQuery:

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

Non ".target", dovrebbe essere ": target"
Mert S. Kaplan,

@ MertS.Kaplan ".target" è la classe "target".
webvitaly,

7

Ho appena scoperto un'altra soluzione CSS pura che ha funzionato come un incanto per me!

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

Trovato su questo sito !


2
Alcuni altri hanno scoperto questa soluzione prima di voi, vedere le risposte a pagina 1, per esempio stackoverflow.com/a/56467997/18771
Tomalak

Scusa, non l'ho notato! Grazie!
jamawe,

Questo non funziona per lo scorrimento dell'intera pagina in Edge e Safari ( bugs.webkit.org/show_bug.cgi?id=179379 ).
Juliusz Gonera il

5

Puoi provare questo:

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

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

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

Imposta il valore di riempimento superiore all'altezza effettiva dell'intestazione. Ciò introdurrà un leggero spazio aggiuntivo nella parte superiore dell'intestazione, ma sarà visibile solo quando l'utente salterà sull'ancora e quindi scorrerà verso l'alto. Ho inventato quella soluzione per il mio sito in questo momento, ma mostra solo una piccola barra fissa nella parte superiore della pagina, niente di troppo alto.


Mh. Non male, ma ancora piuttosto un trucco (e non funziona in IE, purtroppo).
Tomalak,

5

Ho funzionato facilmente con CSS e HTML, usando il metodo "anchor: before" di cui sopra. Penso che funzioni al meglio, perché non crea imbottiture enormi tra i tuoi div.

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

Non sembra funzionare per il primo div sulla pagina, ma puoi contrastarlo aggiungendo il riempimento al primo div.

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

Ecco un violino funzionante: http://jsfiddle.net/FRpHE/24/


5

Per me funziona:

HTML LINK to Anchor:

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

Ancora HTML:

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

CSS:

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

4

Sto usando la risposta di @ Jpsy, ma per motivi di prestazioni sto impostando il timer solo se l'hash è presente nell'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 ha chiesto di non utilizzare JavaScript.
Giulio Caccin,

Funziona con collegamenti esterni ma non con collegamenti in-page.
scatto il

4

Ho avuto molti problemi con molte delle risposte qui e altrove poiché le mie ancore con segnalibri erano intestazioni di sezione in una pagina FAQ, quindi compensare l'intestazione non ha aiutato in quanto il resto del contenuto sarebbe rimasto dove si trovava. Quindi ho pensato di pubblicare un post.

Quello che ho finito per fare è stato un insieme di alcune soluzioni:

  1. Il CSS:

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

Dove "120px" è l'altezza della testata fissa (forse più un po 'di margine).

  1. Il link del segnalibro HTML:

    <a href="#01">What is your FAQ question again?</a>
  2. Il contenuto HTML con segnalibro:

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

La cosa positiva di questa soluzione è che l' spanelemento non è solo nascosto, è essenzialmente collassato e non riempie i tuoi contenuti.

Non posso prendere molto credito per questa soluzione poiché proviene da una serie di risorse diverse, ma ha funzionato meglio per me nella mia situazione.

Puoi vedere il risultato reale qui .


1
Grazie mille per averlo condiviso! Per quanto vecchio sia il thread, non sembra esserci ancora una soluzione canonica a questo problema.
Tomalak,

1
+ SteveCinq Mi hai letto: stavo affrontando gli stessi problemi in cui le soluzioni condivise non funzionavano come previsto. Aggiungendo il <span>con l'ancora nello span, insieme con l'aggiunta dell'imbottitura e del margine ha funzionato per me. Grazie mille per il tempo dedicato a inviare questa risposta nonostante l'età della discussione!
twknab,

4

Non ho avuto fortuna con la risposta sopra elencata e ho finito per usare questa soluzione che ha funzionato perfettamente ...

Crea un intervallo vuoto in cui desideri impostare l'ancora.

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

E applica la seguente classe:

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

Questa soluzione funzionerà anche se le sezioni hanno sfondi di colore diverso! Ho trovato la soluzione a questo link.


1
Non è esattamente lo stesso metodo che Guillaume Le Mière e pochi altri hanno mostrato in questa discussione?
Tomalak,

È molto simile ma penso che sia più facile da capire e una risposta più dettagliata con un collegamento ancora più approfondito a una fonte esterna.
Matt Underwood,

È la stessa soluzione, ma posso capire e seguirla facilmente. Gli altri non mi hanno dato abbastanza informazioni.
MacroMan

3

Mi sembra un po 'confuso per la mia mente purista ma come soluzione solo per CSS puoi aggiungere imbottitura all'elemento ancorato attivo usando il :targetselettore:

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
Non è per niente strano! Bella soluzione.
Tomalak,

3

Ho trovato ho dovuto usare sia MutttenXd 's e Badabam ' soluzioni CSS s insieme, come il primo non ha funzionato in Chrome e la seconda non ha funzionato in 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

Il modo in cui trovo di essere il più pulito è il seguente:

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

2

Un approccio minimamente invadente utilizzando jQuery:

link:

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

Soddisfare:

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

script:

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

Assegnando la classe anchor-link ai collegamenti, il comportamento di altri collegamenti (come fisarmonica o controlli tab) non viene influenzato.

La domanda non vuole JavaScript, ma l'altra domanda più popolare è chiusa a causa di questa e non ho potuto rispondere lì.


2

Avevo bisogno di qualcosa che funzioni per i collegamenti in entrata, i collegamenti a pagina e che possano essere scelti come target da JS in modo che la pagina possa rispondere alle modifiche dell'altezza dell'intestazione

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

Il z-index: -1permette collegamenti nella 'zona padding' sopra un frammento-bersaglio di essere ancora cliccabile, come commentato da @MuttenXd sulla sua risposta

Non ho ancora riscontrato un problema in IE 11, Edge 15+, Chrome 38+, FF 52+ o Safari 9.1+


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

Questo codice dovrebbe fare il trucco. Scambia 45px per l'altezza della barra dell'intestazione.

EDIT: se usare jQuery è un'opzione, ho anche avuto successo usando jQuery.localScroll con un set di valori di offset. L'opzione offset fa parte di jQuery.scrollTo, su cui si basa jQuery.localScroll. Una demo è disponibile qui: http://demos.flesler.com/jquery/scrollTo/ (seconda finestra, sotto 'offset')


questa soluzione funziona davvero, ma non è a prova di proiettile e richiede molti perfezionamenti per i diversi browser :( buon tentativo thoug. Sto cercando una soluzione senza markup extra.
Vlad Saling

Peccato che sia così disordinato, significa che non puoi semplicemente usare gli ID. Mi piacerebbe trovare una soluzione, ho provato ogni sorta di cose.
teorizza il

1

Ecco una soluzione jquery completa che funzionerà in IE:

Supponiamo che gli elementi della barra di navigazione siano qualcosa del genere:

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

È possibile utilizzare il seguente frammento jquery per compensare lo scorrimento:

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

    });
}

Sono stato in grado di utilizzare una versione leggermente modificata di questo codice da Thunder. Ho provato molte delle soluzioni CSS e più semplici su questa pagina e su stackoverflow.com/questions/10732690/… e su stackoverflow.com/questions/10732690/… ma non erano utilizzabili a causa delle mie esigenze. La pagina è una pagina FAQ con molte ancore su cui posizionarsi, sia da dentro che fuori dalla pagina, quindi potrebbe avere molti spazi vuoti. Continua nel prossimo commento ....
Jeffrey Simon,

1
Per farlo funzionare per me, ecco le modifiche minori: (1) cambia "<=" nella riga href.index in "<" per consentire la navigazione in-page; (2) modifica "a.navigation" che doveva essere "#faq a" per il mio uso; (3) cambia var da Top = 250 a un ternario basato su window.innerWidth per le differenze tra mobile e desktop; (4) cambia 400 nell'animato in 1, poiché l'animazione non è desiderata e 0 non funziona; (5) aggiungi if ($ ('my-page-selector'). Lunghezza prima della chiamata a offSetScrollFromLocation nella funzione anonima per impedire chiamate non necessarie su pagine dove non necessarie.
Jeffrey Simon

1

Implementato usando :beforefunzionava alla grande fino a quando non ci siamo resi conto che lo pseudo elemento stava effettivamente coprendo e bloccando eventi puntatore che si trovavano all'interno dell'area dello pseudo elemento. Usando qualcosa di simile pointer-events: nonesul :beforeo anche direttamente sull'ancora non ha avuto effetto.

Ciò che abbiamo finito per fare è stato rendere assoluto il posizionamento dell'ancora e quindi regolare la sua posizione in modo che fosse l'offset / altezza dell'area fissa.

Ancoraggio offset senza bloccare gli eventi del puntatore

.section-marker {

    position: absolute;
    top: -300px;
}

Il valore è che non stiamo bloccando alcun elemento che potrebbe rientrare in quei 300 pixel. Il rovescio della medaglia è che afferrare la posizione di quell'elemento da Javascript deve tener conto dell'offset, quindi ogni logica deve essere modificata.


1

Questo è come l'ho ottenuto per andare finalmente nel posto giusto quando fai clic sulla navigazione. Ho aggiunto un gestore eventi per i clic di navigazione. Quindi puoi semplicemente usare "scrollBy" per spostarti verso l'alto sull'offset.

var offset = 90;

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

2
Risolve il problema, ma non la parte "senza l'aiuto di Javascript" ...
Tomalak,

1

Ho creato un div con alcune interruzioni di riga e ho dato l'id, quindi ho messo il codice che volevo mostrare sotto. Il link ti porterebbe quindi nello spazio sopra l'immagine e l'intestazione non sarebbe più in mezzo:

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

Naturalmente, puoi modificare il numero di interruzioni di riga in base alle tue esigenze. Questo ha funzionato perfettamente per me, non sono sicuro che ci siano problemi, sto ancora imparando HTML.


Pragmatico, ma c'è un aspetto negativo: funziona solo per il primo titolo di una pagina. Se ci sono più titoli, inizierai a vedere grandi lacune nel testo a causa dei <br>tag prima di ogni titolo.
Tomalak,

1

Usato questo script

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

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

Per favore, prova a spiegare perché pensi che questo script risolva il problema
Ali Kanat

1

Penso che questo approccio sia più utile:

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.