Domanda

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

Esiste un modo per utilizzare l'ancoraggio dell'URL (the #fragment part) per far scorrere il browser fino ad un certo punto della pagina, rispettando comunque l'altezza dell'elemento fisso senza l'aiuto di JavaScript?

http://foo.com/#bar
WRONG (but the common behavior):         CORRECT:
+---------------------------------+      +---------------------------------+
| BAR///////////////////// header |      | //////////////////////// header |
+---------------------------------+      +---------------------------------+
| Here is the rest of the Text    |      | BAR                             |
| ...                             |      |                                 |
| ...                             |      | Here is the rest of the Text    |
| ...                             |      | ...                             |
+---------------------------------+      +---------------------------------+
È stato utile?

Soluzione

Ho avuto lo stesso problema. Ho risolto aggiungendo una classe all'elemento di ancoraggio con l'altezza topbar come valore padding-top.

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

E poi semplicemente il css:

.anchor { padding-top: 90px; }

Altri suggerimenti

Se non è possibile o non si desidera impostare una nuova classe, aggiungere un'altezza fissa ::before pseudo-elemento per il :target pseudo-classe CSS:

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

In alternativa scorrere la pagina relativa al :target con jQuery:

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

Io uso questo metodo:

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

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

Si aggiunge un elemento invisibile prima di ogni destinazione. Funziona IE8 +.

Qui ci sono più soluzioni: http://nicolasgallagher.com/jump-links-and-viewport-positioning/

risposta ufficiale Bootstrap Adottato:

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

Credits

Merge

Il modo migliore che ho trovato a gestire questo problema è (sostituire 65px con la tua altezza elemento fisso):

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

Se non ti piace di utilizzare la selettore obiettivo si può anche farlo in questo modo:

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

Nota: questo esempio non funzionerà se l'elemento di destinazione avere un colore backgound che differant 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 del mio bersaglio elemento sovrascriverà il suo elemento rosso genitore 65px. Non ho trovato alcuna soluzione pura CSS per gestire questo problema, ma se non si dispone di un altro colore di sfondo di questa soluzione è la migliore.

Mentre alcune delle soluzioni proposte funziona per i collegamenti di frammento (= link hash) all'interno di nella stessa pagina (come un link menu che scorre verso il basso), ho scoperto che nessuno di loro ha lavorato in corrente Chrome quando si desidera utilizzare i link frammento provenienti in da altre pagine .

Quindi chiamando www.mydomain.com/page.html#foo da zero sarà non compensare il vostro obiettivo in corrente Chrome con una qualsiasi delle date soluzioni CSS o soluzioni JS.

C'è anche un jQuery bug report che descrive alcuni dettagli del problema.

SOLUTION

L'unica opzione che ho trovato finora che funziona davvero in Chrome è JavaScript che non viene chiamato 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 soluzioni di ritardo JS probabilmente funzionerà in Firefox, Internet Explorer, Safari, ma non in Chrome.

Per Chrome / Safari / Firefox si potrebbe aggiungere un display: block e utilizzare un margine negativo per compensare l'offset, come:

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

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

Si può fare questo con jQuery:

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

Si potrebbe provare questo:

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

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

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

Impostare il valore superiore imbottitura per l'altezza effettiva della vostra testata. Ciò introduce un piccolo spazio in più nella parte superiore del vostro colpo di testa, ma sarà visibile solo quando l'utente si sposta l'ancora e poi scorrere verso l'alto. Ho fatto la che soluzione per il mio sito in questo momento, ma si vede solo una piccola barra fissa nella parte superiore della pagina, niente di troppo alta.

Si lavora per me:

HTML LINK Anchor:

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

HTML Ancoraggio:

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

CSS:

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

ho ottenuto lavorando facilmente con CSS e HTML, utilizzando il "ancora: prima di" metodo di cui sopra. Penso che funziona meglio, perché non crea massiccia imbottitura tra le div.

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

Non sembra funzionare per la prima div sulla pagina, ma è possibile contrastare questo con l'aggiunta di imbottitura per quel primo div.

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

Ecco un violino di lavoro: http://jsfiddle.net/FRpHE/24/

Sto usando @ risposta di Jpsy, ma per motivi di prestazioni Sono solo l'impostazione del timer se l'hash è presente nella 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();
      }
  };
html {
  scroll-padding-top: 70px; /* height of sticky header */
}

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

Ci si sente un po 'hacky alla mia mente purista, ma come una soluzione css solo è possibile aggiungere padding all'elemento ancorata attiva utilizzando il selettore :target:

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>

Ho trovato che ho dovuto usare sia MutttenXd 's e Badabam ' s soluzioni CSS 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>
...

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

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

Ho avuto un sacco di problemi con molte delle risposte qui e altrove come le mie ancore segnalibro erano intestazioni di sezione in una pagina di FAQ, in modo da compensare l'intestazione non ha aiutato come il resto del contenuto sarebbe solo rimanere dov'era. Così ho pensato di postare.

Quello che ho finito per fare era un composito di alcune soluzioni:

  1. Il CSS:

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

Dove "120px" è l'altezza di testa fissa (forse più un certo margine).

  1. Il collegamento del segnalibro HTML:

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

    <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 buona di questa soluzione è che l'elemento span non è solo nascosta, è essenzialmente crollato e non lo fa pad out suo sito web.

Non può prendere molto credito per questa soluzione in quanto proviene da un festone di risorse diverse, ma ha funzionato meglio per me nella mia situazione.

È possibile vedere il risultato effettivo qui .

CSS Scroll Snap spec entra in gioco, è facile possibile con la proprietà scroll-margin-top. Attualmente funziona su Chrome e Opera (aprile 2019). Anche Safari 11+ dovrebbe sostenere questo, ma non sono riuscito a farlo funzionare su Safari 11. Probabilmente dobbiamo aspettare per i ragazzi per risolvere il problema overthere.

Codepen esempio

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>

Un approccio mini-invasivo utilizzando jQuery:

Link:

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

Contenuto:

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

Con l'assegnazione della classe di ancoraggio-link per i collegamenti, il comportamento di altri collegamenti (come controlli fisarmonica o tab) non sono interessati.

La questione non vuole javascript ma l'altra domanda più popolare è chiuso a causa di questo e non ho potuto rispondere lì.

Avevo bisogno di qualcosa che funzionasse per i collegamenti in entrata, i collegamenti sulla pagina E che potesse essere preso di mira da JS in modo che la pagina potesse rispondere alle modifiche nell'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: -1 consente ai collegamenti nell'area di riempimento sopra un target di frammento di essere ancora selezionabili, come commentato da @MuttenXd nella sua risposta

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

Non stavo avendo fortuna con la risposta di cui sopra e finito per usare questa soluzione che ha funzionato perfettamente ...

Crea un arco vuota in cui si desidera impostare il vostro ancoraggio.

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

E applicare la seguente classe:

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

Questa soluzione funziona anche se le sezioni hanno diversi sfondi colorati! Ho trovato la soluzione a questo link.

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

Questo codice dovrebbe fare il trucco. Swap fuori 45px per l'altezza della barra di intestazione.

EDIT: Se si utilizza jQuery è un'opzione, ho anche avuto successo utilizzando jQuery.localScroll con un set valore di offset. L'opzione offset è una parte di jQuery.scrollTo, che jQuery.localScroll è costruita su. Una demo è disponibile qui: http://demos.flesler.com/jquery/scrollTo/ (seconda finestra, sotto 'compensati')

Questa è una soluzione completa jquery che funzionerà in IE:

Supponiamo che gli elementi della barra di navigazione sono qualcosa di simile:

<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 il rotolo:

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

    });
}

implementato utilizzando :before funzionato grande fino a quando ci siamo resi conto che l'elemento pseudo era in realtà coprendo e bloccando eventi del puntatore che sedeva nel zona dell'elemento pseudo. Usando qualcosa come pointer-events: none sul :before o anche direttamente sull'ancora non ha avuto effetto.

Quello che abbiamo finito per fare stava facendo del posizionamento assoluto di ancoraggio e quindi regolando la sua posizione per essere l'offset / altezza dell'area fisso.

Offset Anchor senza bloccare Pointer Eventi

.section-marker {

    position: absolute;
    top: -300px;
}

Il valore di questo è che non stiamo bloccando eventuali elementi che potrebbero cadere all'interno di quelli 300px. Lo svantaggio è che afferrando la posizione di tale elemento dal Javascript deve tener conto del fatto che compensato in modo che qualsiasi logica ci doveva essere regolata.

Questo è come ho ottenuto finalmente andare al posto giusto quando si fa clic sulla navigazione. Ho aggiunto un gestore di eventi per i clic di navigazione. Poi si può semplicemente utilizzare "scrollBy" per salire sul offset.

var offset = 90;

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

Ho creato un div con un paio di interruzioni di riga e dato che l'ID, poi ho messo il codice che ho voluto mostrare sotto. Il collegamento sarebbe poi ti fa lo spazio sopra l'immagine e l'intestazione non sarebbe nel modo:

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

Naturalmente, è possibile modificare il numero di interruzioni di riga in base alle proprie esigenze. Questo ha funzionato perfettamente per me, non so se ci sono problemi, però, sto ancora imparando HTML.

Utilizzato questo script

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

    $('html, body').animate({
        scrollTop: $($.attr(this, 'href')).offset().top -140
    }, 1000);
});
// handle hashes when page loads
// <http://stackoverflow.com/a/29853395>
function adjustAnchor() {
  const $anchor = $(':target');
  const fixedElementHeight = $('.navbar-fixed-top').outerHeight();
  if ($anchor.length > 0)
    window.scrollTo(0, $anchor.offset().top - fixedElementHeight);
}
$(window).on('hashchange load', adjustAnchor);
$('body').on('click', "a[href^='#']", function (ev) {
  if (window.location.hash === $(this).attr('href')) {
    ev.preventDefault();
    adjustAnchor();
  }
});

Io uso questo metodo perché per qualche motivo, nessuno degli altri soluzioni proposte in realtà ha lavorato per me. Prometto che provato.

section {
   position: relative;
   border-top: 52px solid transparent; /* navbar height +2 */
   margin: -30px 0 0;
   -webkit-background-clip: padding-box;
   -moz-background-clip: padding;
   background-clip: padding-box;
}

section:before {
   content: "";
   position: absolute;
   top: -2px;
   left: 0;
   right: 0;
   border-top: 2px solid transparent;
}

Sostituire sezione da una classe, se si preferisce.

fonte: link salto e viewport posizionamento

  • Testato su Firefox e Chrome 45 52.
  • Versione bootstrap: 3.3.7

Per chi non mi crede io gentilmente preparato un jsfiddle con la soluzione in esso: SOLUZIONE

trucco CSS sarà una soluzione. Una soluzione adeguata, che funzionerà in tutto lo scenario può essere implementato utilizzando jQuery.

Fare riferimento a https://codepen.io/pikeshmn/pen/mMxEdZ

Approccio:. Otteniamo l'altezza del nav fissa con document.getElementById ( 'colpo di testa') offsetHeight E offset di scorrimento per questo valore.

var jump=function(e){  

e.preventDefault();                        //prevent "hard" jump
  var target = $(this).attr("href");       //get the target

      //perform animated scrolling
      $('html,body').animate(
        {
          scrollTop: $(target).offset().top - document.getElementById('header').offsetHeight - 5  //get top-position of target-element and set it as scroll target
        },1000,function()                  //scrolldelay: 1 seconds
        {
          location.hash = target;          //attach the hash (#jumptarget) to the pageurl
        });
      }

  $(document).ready(function()
  {
    $('a[href*="#"]').bind("click", jump); //get all hrefs
    return false;
  });

P.S:

  • Esso comprende una differenza bel 5 pixel tra intestazione e la destinazione
  • Effetto
  • Scroll non è difficile, piuttosto liscia; Scorrimento
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top