Pregunta

Si tengo una cabecera sin desplazamiento en una página HTML, fijado a la parte superior, que tiene una altura definida:

¿Hay una manera de utilizar el ancla URL (la parte #fragment) para que el desplazamiento del navegador hasta cierto punto de la página, pero aún así respetar la altura del elemento fijo sin la ayuda 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    |
| ...                             |      | ...                             |
+---------------------------------+      +---------------------------------+
¿Fue útil?

Solución

Yo tenía el mismo problema. Lo resuelto mediante la adición de una clase para el elemento de anclaje con la altura barra superior como el valor padding-top.

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

Y entonces simplemente el CSS:

.anchor { padding-top: 90px; }

Otros consejos

Si usted no puede o no desea establecer una nueva clase, agregue una altura fija ::before pseudo-elemento a la :target pseudo-clase en el CSS:

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

O desplazarse por la página relativa a :target con jQuery:

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

Yo uso este enfoque:

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

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

Se añade un elemento invisible antes de cada objetivo. Funciona IE8 +.

Aquí hay más soluciones: http://nicolasgallagher.com/jump-links-and-viewport-positioning/

Bootstrap respuesta oficial adoptado:

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

Créditos

Combinar

Mientras que algunas de las soluciones propuestas trabajan para los enlaces de fragmentos (= Enlaces de hash) dentro de la misma página (como un enlace del menú que se desplaza hacia abajo), he encontrado que ninguno de ellos trabajaba en la corriente de Chrome cuando que desea utilizar enlaces de fragmentos procedentes de desde otras páginas .

Así que llamar www.mydomain.com/page.html#foo desde cero no compensar su objetivo en la corriente Chrome con cualquiera de las soluciones dadas CSS o JS soluciones.

También hay un jQuery informe de error describir algunos detalles del problema.

SOLUCIÓN

La única opción que he encontrado hasta ahora que realmente funciona en Chrome es de JavaScript que no se llama onDomReady pero con un retraso.

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

Resumen

Sin lugar a soluciones de retardo JS probablemente funcionará en Firefox, IE, Safari, pero no en Chrome.

Para Chrome / Safari / Firefox se podría añadir un display: block y utilizar un margen negativo para compensar el desplazamiento, como:

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

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

Se puede hacer esto con jQuery:

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

Usted podría intentar esto:

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

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

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

Establecer el valor de relleno superior a la altura real de la cabecera. Esto introducirá un pequeño espacio extra en la parte superior de la cabecera, pero sólo será visible cuando el usuario salta al ancla y luego se desplaza hacia arriba. He hecho de que la solución para mi sitio en este momento, pero sólo muestra una pequeña barra fija en la parte superior de la página, nada demasiado alto.

A mí me funciona:

HTML LINK para Ancla:

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

anclaje HTML:

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

CSS:

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

Tengo que trabajar fácilmente con CSS y HTML, usando el "ancla: antes de" método mencionado anteriormente. Creo que funciona mejor, ya que no crea masiva relleno entre su divs.

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

No parece funcionar por primera div en la página, pero se puede contrarrestar mediante la adición de que el relleno a la primera div.

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

Aquí hay un violín de trabajo: http://jsfiddle.net/FRpHE/24/

Estoy usando @ respuesta de Jpsy, pero por razones de rendimiento sólo estoy de ajustar el temporizador si el hash está presente en la 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 */
}

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

Se siente un poco hacky a mi mente purista sino como una solución CSS sólo se puede agregar relleno al elemento anclado activa con el selector :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>

Me di cuenta de que tenía que usar ambos MutttenXd 's y Badabam ' s soluciones CSS juntos, como la primera no funcionó en Chrome y el segundo no funcionaba en 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 forma en que me parece ser la más limpia es la siguiente:

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

Yo tenía un montón de problemas con muchas de las respuestas aquí y en otros lugares como mis anclas marcadas fueron encabezados de sección en una página de preguntas frecuentes, por lo que la compensación de la cabecera no ayudó a que el resto de los contenidos sería simplemente quedarse donde estaba. Así que pensé que había puesto.

Lo que terminé haciendo fue una combinación de algunas soluciones:

  1. El CSS:

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

Donde "120px" es su altura cabecera fija (tal vez más algún margen).

  1. El vínculo al marcador HTML:

    <a href="#01">What is your FAQ question again?</a>
    
  2. El marcada contenido 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>
    

Lo bueno de esta solución es que el elemento span no sólo se oculta, es esencialmente colapsó y no lo hace almohadilla a cabo su contenido.

No puede tomar mucho crédito por esta solución ya que proviene de un botín de diferentes recursos, pero funcionó mejor para mí en mi situación.

Se puede ver el resultado real aquí .

CSS desplazamiento Snap especificación entra en juego, es fácil es posible con la propiedad scroll-margin-top. Actualmente funciona en Chrome y Opera (abril de 2019). También Safari 11+ debería apoyar esto, pero fue incapaz de ejecutarlo en Safari 11. Es probable que tengamos que esperar a que los chicos lo resuelvan mal por allí.

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

Un enfoque mínimamente invasivo utilizando jQuery:

Enlace:

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

Contenido:

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

Guión:

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

Mediante la asignación de la clase de ancla enlace para los enlaces, el comportamiento de otros enlaces (como los controles de acordeón o pestaña) no se ven afectadas.

La pregunta no quiere javascript pero la otra pregunta más populares está cerrado a causa de éste y que no podía responder allí.

Yo necesitaba algo que funcione para enlaces entrantes, enlaces de la página, y que puede ser objetivo de JS para que la página pueda responder a los cambios en la altura del encabezado

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

El z-index: -1 permite enlaces en el 'área de relleno' por encima de un fragmento diana de estar todavía puede hacer clic, como se ha comentado por @MuttenXd en su respuesta

No he encontrado todavía un problema en IE 11, Edge 15+, 38+ Chrome, FF 52+, o Safari 9.1 +

que no estaba teniendo suerte con la respuesta indicada más arriba y terminé usando esta solución que funcionaba perfectamente ...

Crear un lapso en blanco en la que desea establecer su ancla.

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

Y aplicar la siguiente clase:

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

Esta solución funcionará incluso de las secciones tienen diferentes ámbitos de colores! He encontrado la solución en este enlace.

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

Este código debe hacer el truco. Intercambiar 45 píxeles para la altura de la barra de encabezado.

EDIT: Si se utiliza jQuery es una opción, yo también he tenido éxito usando jQuery.localScroll con un conjunto de valores de desplazamiento. La opción de desplazamiento es una parte de jQuery.scrollTo, que se basa en jQuery.localScroll. Una demo está disponible aquí: http://demos.flesler.com/jquery/scrollTo/ (segunda ventana, debajo de 'compensar')

Aquí es una solución completa jquery que funciona en IE:

Supongamos que los elementos de la barra de navegación son algo como esto:

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

Se puede utilizar el siguiente fragmento de jQuery para compensar el desplazamiento:

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

    });
}

implementan utilizando :before funcionó muy bien hasta que nos dimos cuenta de que el elemento de pseudo realidad estaba cubriendo y el bloqueo de los eventos de puntero que se sentaron en área del elemento seudo. Usando algo como pointer-events: none en el :before o incluso directamente sobre el ancla no tuvo ningún efecto.

Lo que terminamos haciendo era hacer del anclaje de posicionamiento absoluto y luego ajustar su posición para ser el offset / altura del área fija.

Offset ancla sin bloquear Pointer Eventos

.section-marker {

    position: absolute;
    top: -300px;
}

El valor de esto es que no estamos bloqueando todo elemento que pueda caer dentro de los 300 px. La desventaja es que la posición que ase de ese elemento de Javascript tiene que tener en cuenta que compensado por lo que cualquier lógica tenía que ser ajustado.

Esta es la forma en que lo tengo para ir finalmente al lugar apropiado cuando se hace clic en la barra de navegación. He añadido un controlador de eventos para los clics de navegación. A continuación, sólo puede utilizar "scrollBy" para moverse hacia arriba en el offset.

var offset = 90;

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

He creado un div con unos saltos de línea y se entregó a que la identificación, que entonces se quería mostrar debajo. El enlace sería entonces lo lleve al espacio por encima de la imagen y la cabecera ya no estaría en la forma:

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

Por supuesto, puede cambiar el número de saltos de línea para satisfacer sus necesidades. Esto funcionó perfectamente para mí, no estoy seguro si hay algún problema, sin embargo, todavía estoy aprendiendo HTML.

Se utiliza este 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();
  }
});

Yo uso este método porque por alguna razón, ninguna de las otras soluciones propuestas no funcionaba para mí. Prometo que probé.

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

Reemplazar sección por una clase, si lo prefiere.

fuente: enlaces salto y ventana gráfica posicionamiento

  • Probado en Firefox y Chrome 45 52.
  • versión de arranque: 3.3.7

Para los que no me cree que amablemente preparó un jsFiddle con la solución en ella: SOLUCIÓN

truco CSS será una solución temporal. Una solución adecuada, que funcione en todos los escenarios se puede implementar utilizando jQuery.

Consulte https://codepen.io/pikeshmn/pen/mMxEdZ

Enfoque:. Obtenemos la altura del nav fijo utilizando document.getElementById ( 'cabecera') offsetHeight Y compensar el desplazamiento a este valor.

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:

  • Incluye una diferencia agradable 5 píxeles entre encabezado y objetivo
  • efecto
  • desplazamiento no es difícil, más suave; Desplazamiento suave
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top