Question

Si j'ai un en-tête de non-défilement dans une page HTML, fixée au sommet, ayant une hauteur définie:

Y at-il un moyen d'utiliser l'ancre d'URL (la partie de #fragment) pour avoir le défilement du navigateur jusqu'à un certain point dans la page, mais toujours respecter la hauteur de l'élément fixe sans l'aide de 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    |
| ...                             |      | ...                             |
+---------------------------------+      +---------------------------------+
Était-ce utile?

La solution

J'ai eu le même problème. Je résolu en ajoutant une classe à l'élément d'ancrage avec la hauteur de la barre supérieure que la valeur-dessus rembourrage.

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

Et puis simplement le css:

.anchor { padding-top: 90px; }

Autres conseils

Si vous ne pouvez pas ou ne voulez pas définir une nouvelle classe, ajoutez une hauteur fixe ::before pseudo-élément :target pseudo-classe CSS:

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

Ou faire défiler la page par rapport à :target avec jQuery:

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

J'utilise cette approche:

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

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

Il ajoute un élément invisible avant chaque cible. Il fonctionne IE8 +.

Voici plus de solutions: http://nicolasgallagher.com/jump-links-and-viewport-positioning/

Bootstrap officiel Adopté Réponse:

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

Crédits

fusion

La meilleure façon que je trouve de traiter cette question est (remplacer 65px avec la hauteur de votre élément fixe):

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

Si vous ne aimez pas utiliser le sélecteur cible vous pouvez aussi le faire dans ce façon:

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

Note: cet exemple ne fonctionnera pas si l'élément cible ont une couleur de backgound qui differant de son parent. par exemple:

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

dans ce cas, la couleur verte de ma cible élément écrasera son élément parent rouge 65px. Je n'ai pas trouvé une solution pure CSS pour gérer ce problème, mais si vous ne disposez pas d'une autre couleur de fond cette solution est la meilleure.

Bien que certaines des solutions proposées fonctionnent pour des liens fragment (= liens de hachage) dans les la même page (comme un lien de menu qui défile vers le bas), je trouve qu'aucun d'entre eux a travaillé dans Chrome en cours lorsque vous voulez utiliser des liens fragment à venir d'autres pages .

Donc, appeler www.mydomain.com/page.html#foo à partir de zéro sera pas compenser votre cible dans Chrome en cours avec une des solutions CSS données ou solutions JS.

Il y a aussi un rapport de bogue jQuery décrivant des détails du problème.

SOLUTION

La seule option que je trouve à ce jour qui fonctionne vraiment dans Chrome est JavaScript qui n'est pas appelé onDomReady mais avec un retard.

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

SOMMAIRE

Sans une solution de retard JS ne fonctionnera probablement dans Firefox, IE, Safari, mais pas dans Chrome.

Pour Chrome / Safari / Firefox vous pouvez ajouter un display: block et utiliser une marge négative pour compenser le décalage, comme:

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

Voir par exemple http://codepen.io/swed/pen/RrZBJo

Vous pouvez le faire avec jQuery:

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

Vous pouvez essayer ceci:

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

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

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

Régler la valeur de remplissage supérieure à la hauteur réelle de votre tête. Cela introduit un léger écart supplémentaire au sommet de votre tête, mais il ne sera visible que lorsque l'utilisateur passe à l'ancre, puis défiler vers le haut. J'ai pris cette solution pour mon site en ce moment, mais il ne montre qu'une petite barre fixe en haut de la page, rien de trop élevé.

Il fonctionne pour moi:

HTML LINK Anchor:

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

HTML Anchor:

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

CSS:

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

Je l'ai travailler facilement avec CSS et HTML, en utilisant le « point d'ancrage: avant » méthode mentionnée ci-dessus. Je pense que cela fonctionne le mieux, car il ne crée pas un rembourrage massif entre vos divs.

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

Il ne semble pas fonctionner pour la première div sur la page, mais vous pouvez contrer cela en ajoutant un rembourrage à cette première div.

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

Voici un violon de travail: http://jsfiddle.net/FRpHE/24/

J'utilise @ réponse de Jpsy, mais pour des raisons de performance, je suis mise que la minuterie si le hachage est présent dans l'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 */
}

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

Il se sent un peu hacky à mon esprit puriste mais comme une solution css seulement vous pouvez ajouter un rembourrage à l'élément actif ancré à l'aide du sélecteur de :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>

J'ai trouvé que je devais utiliser deux MutttenXd s et Badabam 'Les solutions CSS ensemble, comme le premier n'a pas fonctionné dans Chrome et le second n'a pas fonctionné dans 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>
...

La façon que je trouve être le plus propre est la suivante:

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

J'ai eu beaucoup de mal avec la plupart des réponses ici et d'ailleurs que mes ancres bookmarked étaient têtes de section dans une page FAQ, donc compenser l'en-tête n'a pas aidé que le reste du contenu serait tout simplement rester là où il était. Donc, je pensais que je poste.

Ce que je fini par faire était un composite de quelques solutions:

  1. Le CSS:

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

Où "120px" est votre taille d'en-tête fixe (peut-être plus une certaine marge).

  1. Le lien du signet HTML:

    <a href="#01">What is your FAQ question again?</a>
    
  2. Le contenu HTML bookmarked:

    <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 bonne chose à propos de cette solution est que l'élément de span est non seulement caché, il est essentiellement effondré et ne pad pas votre contenu.

Je ne peux pas prendre beaucoup de crédit pour cette solution car il provient d'un butin de différentes ressources, mais il a le mieux fonctionné pour moi dans ma situation.

Vous pouvez voir le résultat réel .

CSS défilement Aligner les spécifications entre en jeu, il est facilement possible avec propriété scroll-margin-top. fonctionne actuellement sur Chrome et Opera (Avril 2019). Aussi Safari 11+ devrait soutenir, mais je n'a pas pu l'exécuter sur Safari 11. Probablement que nous devons attendre les gars pour le fixer overthere.

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

Une approche moins intrusive possible en utilisant jQuery:

Lien:

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

Contenu:

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

En attribuant la classe ancre lien vers les liens, le comportement des autres liens (comme les contrôles d'accordéon ou onglet) ne sont pas concernés.

La question ne veut pas javascript mais l'autre question plus populaire est fermé à cause de celui-ci et je ne pouvais pas répondre là-bas.

Je besoin de quelque chose qui fonctionne pour des liens entrants, liens à la page, et qui peuvent être visés par JS pour que la page peut répondre aux changements de la hauteur d'en-tête

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

Le z-index: -1 permet des liens dans la « zone de remplissage » au-dessus d'un fragment cible à être encore cliquable, comme commenté par @MuttenXd sur sa réponse

Je n'ai pas encore trouvé un problème dans IE 11, bord 15+, Chrome 38+, 52+ FF ou Safari 9.1 +

Je n'avais pas eu de chance avec la réponse ci-dessus et a fini par utiliser cette solution qui a fonctionné parfaitement ...

Créer une période de vide où vous souhaitez définir votre point d'ancrage.

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

Et appliquer la classe suivante:

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

Cette solution fonctionnera même si les sections ont une couleur différente! J'ai trouvé la solution à ce lien.

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

Ce code devrait faire l'affaire. Swap sur 45px pour la hauteur de la barre d'en-tête.

EDIT: Si vous utilisez jQuery est une option, j'ai également réussi en utilisant jQuery.localScroll avec un jeu de valeur de décalage. L'option de décalage est une partie de jQuery.scrollTo, qui est construit sur jQuery.localScroll. Une démo est disponible ici: http://demos.flesler.com/jquery/scrollTo/ (deuxième fenêtre, dans le 'offset')

Voici une solution complète jquery qui fonctionnera dans IE:

Supposons que les éléments de la barre de navigation sont quelque chose comme ceci:

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

Vous pouvez utiliser l'extrait de jquery suivant pour compenser le défilement:

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

    });
}

Mis en œuvre à l'aide :before fonctionnait très bien jusqu'à ce que nous avons réalisé que l'élément pseudo couvrait en fait et le blocage des événements qui se sont assis pointeur dans les zone de l'élément pseudo. En utilisant quelque chose comme pointer-events: none sur le :before ou même directement sur l'ancre n'a eu aucun effet.

Ce que nous avons fini par faire a été fait l'absolu d'ancrage positionnement et réglage de la position de ce à l'offset / hauteur de la zone fixe.

Décalage d'ancrage sans blocage des événements du pointeur

.section-marker {

    position: absolute;
    top: -300px;
}

La valeur est ce que nous ne sommes pas bloquer les éléments qui pourraient tomber au sein de ces 300px. L'inconvénient est que saisir la position de cet élément de Javascript doit prendre en compte, il fallait régler ce décalage de sorte que toute logique.

Voici comment je l'ai eu pour aller enfin à la place lorsque vous cliquez sur la barre de navigation. J'ai ajouté un gestionnaire d'événements pour les clics de navigation. Ensuite, vous pouvez utiliser « scrollBy » pour se déplacer sur le décalage.

var offset = 90;

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

Je créé un div avec quelques sauts de ligne et a donné que l'identifiant, je mets alors le code que je voulais montrer en dessous. Le lien serait alors vous amène à l'espace au-dessus de l'image et l'en-tête ne serait plus dans la façon suivante:

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

Bien sûr, vous pouvez modifier le nombre de sauts de ligne pour répondre à vos besoins. Cela a parfaitement fonctionné pour moi, ne sais pas s'il y a des problèmes bien, je suis encore à apprendre HTML.

Utilisé ce 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();
  }
});

J'utilise cette méthode parce que, pour une raison quelconque, aucune des autres solutions proposées réellement travaillé pour moi. Je promets que j'ai essayé.

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

Remplacer section par une classe si vous préférez.

source: liens de saut et viewport positionnement

  • Testé sur Firefox 45 et Chrome 52.
  • version bootstrap: 3.3.7

Pour ceux qui ne me croient pas que je gentiment préparé un jsFiddle avec la solution en elle: SOLUTION

trick CSS sera une solution de contournement. Une bonne solution qui fonctionnera dans tous les scénarios peuvent être mis en œuvre en utilisant jQuery.

Reportez-vous à https://codepen.io/pikeshmn/pen/mMxEdZ

Approche:. Nous obtenons la hauteur de navigation fixe en utilisant document.getElementById ( 'tête') offsetHeight Et compenser le défilement à cette valeur.

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:

  • Il comprend une belle 5 pixels différence entre la tête et la cible
  • effet de défilement n'est pas difficile, plutôt lisse; Lissez Scrolling
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top