with tag javascript html css anchor offset

javascript - tag - compensar un ancla html para ajustar el encabezado fijo



anchor padding (28)

Puedes hacerlo sin js y sin alterar html. Es solo CSS.

a[id]:before { content:""; display:block; height:50px; margin:-30px 0 0; }

Eso agregará un pseudo-elemento antes de cada una de las etiquetas con una identificación. Ajuste los valores para que coincidan con la altura de su encabezado.

Esta pregunta ya tiene una respuesta aquí:

Estoy tratando de limpiar la forma en que funcionan mis anclajes. Tengo un encabezado que está fijo en la parte superior de la página, así que cuando se vincula a un anclaje en otra parte de la página, la página salta de modo que el anclaje está en la parte superior de la página, dejando el contenido detrás del encabezado fijo (espero eso tiene sentido). Necesito una manera de compensar el ancla por 25px desde la altura del encabezado. Preferiría HTML o CSS, pero Javascript también sería aceptable.


¿Qué hay de las etiquetas de span ocultas con ID enlazables que proporcionan la altura de la barra de navegación?

#head1 { padding-top: 60px; height: 0px; visibility: hidden; } <span class="head1">somecontent</span> <h5 id="headline1">This Headline is not obscured</h5>

aquí está el violín: http://jsfiddle.net/N6f2f/7


Agregando a la respuesta de Ziav (con agradecimientos a Alexander Savin), necesito usar el <a name="...">...</a> la vieja escuela, ya que estamos usando <div id="...">...</div> para otro fin en nuestro código. Tuve algunos problemas de visualización al usar display: inline-block : la primera línea de cada elemento <p> estaba ligeramente indentada (en los navegadores Webkit y Firefox). Terminé probando otros valores de display y display: table-caption funciona perfectamente para mí.

.anchor { padding-top: 60px; margin-top: -60px; display: table-caption; }


Como esta es una preocupación de la presentación, una solución pura de CSS sería ideal. Sin embargo, esta pregunta se planteó en 2012, y aunque se han sugerido soluciones de posicionamiento relativo / margen negativo, estos enfoques parecen bastante extravagantes, crean problemas de flujo potencial y no pueden responder dinámicamente a los cambios en el DOM / viewport.

Con esto en mente, creo que usar JavaScript sigue siendo (febrero de 2017) el mejor enfoque. A continuación se muestra una solución vanilla-JS que responderá tanto a los clics de anclaje como a la resolución del hash de la página al cargarse (consulte JSFiddle) . Modifique el método .getFixedOffset() si se requieren cálculos dinámicos. Si está utilizando jQuery, aquí hay una solución modificada con una mejor delegación de eventos y un desplazamiento suave .

(function(document, history, location) { var HISTORY_SUPPORT = !!(history && history.pushState); var anchorScrolls = { ANCHOR_REGEX: /^#[^ ]+$/, OFFSET_HEIGHT_PX: 50, /** * Establish events, and fix initial scroll position if a hash is provided. */ init: function() { this.scrollToCurrent(); window.addEventListener(''hashchange'', this.scrollToCurrent.bind(this)); document.body.addEventListener(''click'', this.delegateAnchors.bind(this)); }, /** * Return the offset amount to deduct from the normal scroll position. * Modify as appropriate to allow for dynamic calculations */ getFixedOffset: function() { return this.OFFSET_HEIGHT_PX; }, /** * If the provided href is an anchor which resolves to an element on the * page, scroll to it. * @param {String} href * @return {Boolean} - Was the href an anchor. */ scrollIfAnchor: function(href, pushToHistory) { var match, rect, anchorOffset; if(!this.ANCHOR_REGEX.test(href)) { return false; } match = document.getElementById(href.slice(1)); if(match) { rect = match.getBoundingClientRect(); anchorOffset = window.pageYOffset + rect.top - this.getFixedOffset(); window.scrollTo(window.pageXOffset, anchorOffset); // Add the state to history as-per normal anchor links if(HISTORY_SUPPORT && pushToHistory) { history.pushState({}, document.title, location.pathname + href); } } return !!match; }, /** * Attempt to scroll to the current location''s hash. */ scrollToCurrent: function() { this.scrollIfAnchor(window.location.hash); }, /** * If the click event''s target was an anchor, fix the scroll position. */ delegateAnchors: function(e) { var elem = e.target; if( elem.nodeName === ''A'' && this.scrollIfAnchor(elem.getAttribute(''href''), true) ) { e.preventDefault(); } } }; window.addEventListener( ''DOMContentLoaded'', anchorScrolls.init.bind(anchorScrolls) ); })(window.document, window.history, window.location);


Como sugiere @moeffju, esto se puede lograr con CSS . El problema que encontré (que me sorprende que no haya visto antes) es el truco de superponer elementos anteriores con relleno o un borde transparente que evita acciones de desplazamiento y clic en la parte inferior de esas secciones porque el siguiente viene más arriba en el orden Z.

La mejor solución que encontré fue colocar el contenido de la sección en un div que está en z-index: 1 :

// Apply to elements that serve as anchors .offset-anchor { border-top: 75px solid transparent; margin: -75px 0 0; -webkit-background-clip: padding-box; -moz-background-clip: padding; background-clip: padding-box; } // Because offset-anchor causes sections to overlap the bottom of previous ones, // we need to put content higher so links aren''t blocked by the transparent border. .container { position: relative; z-index: 1; }


En lugar de tener una barra de navegación de posición fija subpuesta por el resto del contenido de la página (con todo el cuerpo de la página desplazándose), considere tener un cuerpo no desplazable con una barra de navegación estática y luego tener el contenido de la página en una div desplazable en posición absoluta a continuación.

Es decir, tener HTML como este ...

<div class="static-navbar">NAVBAR</div> <div class="scrollable-content"> <p>Bla bla bla</p> <p>Yadda yadda yadda</p> <p>Mary had a little lamb</p> <h2 id="stuff-i-want-to-link-to">Stuff</h2> <p>More nonsense</p> </div>

... y CSS así:

.static-navbar { height: 100px; } .scrollable-content { position: absolute; top: 100px; bottom: 0; overflow-y: scroll; width: 100%; }

Esto logra el resultado deseado de una manera directa, no hacky. La única diferencia en el comportamiento entre esto y algunos de los hacks CSS más sofisticados sugeridos anteriormente es que la barra de desplazamiento (en los navegadores que rinden uno) se adjuntará al contenido div en lugar de al alto completo de la página. Puede o no considerar esto deseable.

Aquí hay un JSFiddle que demuestra esto en acción.


Encontré esta solución:

<a name="myanchor"> <h1 style="padding-top: 40px; margin-top: -40px;">My anchor</h1> </a>

Esto no crea ningún espacio en el contenido y los enlaces de anclaje funcionan muy bien.


Esta es la solución que usamos en nuestro sitio. Ajuste la variable headerHeight a cualquiera que sea la altura del encabezado. Agregue la clase js-scroll al anclaje que debe desplazarse al hacer clic.

// SCROLL ON CLICK // -------------------------------------------------------------------------- $(''.js-scroll'').click(function(){ var headerHeight = 60; $(''html, body'').animate({ scrollTop: $( $.attr(this, ''href'') ).offset().top - headerHeight }, 500); return false; });


Estaba buscando una solución a esto también. En mi caso, fue bastante fácil.

Tengo un menú de lista con todos los enlaces:

<ul> <li><a href="#one">one</a></li> <li><a href="#two">two</a></li> <li><a href="#three">three</a></li> <li><a href="#four">four</a></li> </ul>

Y debajo de eso, los títulos a donde debería ir.

<h3>one</h3> <p>text here</p> <h3>two</h3> <p>text here</p> <h3>three</h3> <p>text here</p> <h3>four</h3> <p>text here</p>

Ahora, porque tengo un menú fijo en la parte superior de la página, no puedo hacer que vaya a mi etiqueta porque eso estaría detrás del menú.

En cambio, puse una etiqueta span dentro de mi etiqueta con la identificación adecuada.

<h3><span id="one"></span>one</h3>

Ahora usa 2 líneas de CSS para ubicarlas correctamente.

h3{ position:relative; } h3 span{ position:absolute; top:-200px;}

Cambie el valor superior para que coincida con la altura de su encabezado fijo (o más). Ahora supongo que esto funcionaría con otros elementos también.


Esto fue inspirado por la respuesta de Shouvik, el mismo concepto que el suyo, solo el tamaño del encabezado fijo no está codificado. Siempre que su encabezado fijo esté en el primer nodo de encabezado, esto debería "solo funcionar"

/*jslint browser: true, plusplus: true, regexp: true */ function anchorScroll(fragment) { "use strict"; var amount, ttarget; amount = $(''header'').height(); ttarget = $(''#'' + fragment); $(''html,body'').animate({ scrollTop: ttarget.offset().top - amount }, 250); return false; } function outsideToHash() { "use strict"; var fragment; if (window.location.hash) { fragment = window.location.hash.substring(1); anchorScroll(fragment); } } function insideToHash(nnode) { "use strict"; var fragment; fragment = $(nnode).attr(''href'').substring(1); anchorScroll(fragment); } $(document).ready(function () { "use strict"; $("a[href^=''#'']").bind(''click'', function () {insideToHash(this); }); outsideToHash(); });


Esto toma muchos elementos de las respuestas anteriores y se combina en una función jQuery anónima minúscula (194 bytes). Ajuste fixedElementHeight para la altura de su menú o elemento de bloqueo.

(function($, window) { var adjustAnchor = function() { var $anchor = $('':target''), fixedElementHeight = 100; if ($anchor.length > 0) { $(''html, body'') .stop() .animate({ scrollTop: $anchor.offset().top - fixedElementHeight }, 200); } }; $(window).on(''hashchange load'', function() { adjustAnchor(); }); })(jQuery, window);

Si no te gusta la animación, reemplaza

$(''html, body'') .stop() .animate({ scrollTop: $anchor.offset().top - fixedElementHeight }, 200);

con:

window.scrollTo(0, $anchor.offset().top - fixedElementHeight);

Versión Uglified:

!function(o,n){var t=function(){var n=o(":target"),t=100;n.length>0&&o("html, body").stop().animate({scrollTop:n.offset().top-t},200)};o(n).on("hashchange load",function(){t()})}(jQuery,window);


FWIW esto funcionó para mí:

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


He estado enfrentando un problema similar, lamentablemente después de implementar todas las soluciones anteriores, llegué a la siguiente conclusión.

  1. Mis elementos internos tenían una estructura de CSS frágil y la implementación de una posición relativa / juego absoluto, estaba rompiendo completamente el diseño de la página.
  2. CSS no es mi fuerte.

Escribí este desplazamiento simple js, que explica el desplazamiento causado por el encabezado y reubicó el div alrededor de 125 píxeles a continuación. Por favor, úsalo como mejor te parezca.

El HTML

<div id="#anchor"></div> <!-- #anchor here is the anchor tag which is on your URL -->

El JavaScript

$(function() { $(''a[href*=#]:not([href=#])'').click(function() { if (location.pathname.replace(/^///,'''') == this.pathname.replace(/^///,'''') && location.hostname == this.hostname) { var target = $(this.hash); target = target.length ? target : $(''[name='' + this.hash.slice(1) +'']''); if (target.length) { $(''html,body'').animate({ scrollTop: target.offset().top - 125 //offsets for fixed header }, 1000); return false; } } }); //Executed on page load with URL containing an anchor tag. if($(location.href.split("#")[1])) { var target = $(''#''+location.href.split("#")[1]); if (target.length) { $(''html,body'').animate({ scrollTop: target.offset().top - 125 //offset height of header here too. }, 1000); return false; } } });

Vea una implementación en vivo aquí .


La solución de @ AlexanderSavin funciona muy bien en los navegadores WebKit para mí.

Además tuve que usar : pseudo-clase de destino que aplica estilo al anclaje seleccionado para ajustar el relleno en FF , Opera e IE9 :

a:target { padding-top: 40px }

Tenga en cuenta que este estilo no es para Chrome / Safari por lo que probablemente tenga que usar css-hacks, comentarios condicionales, etc.

También me gustaría notar que la solución de Alexander funciona debido al hecho de que el elemento específico está en inline . Si no desea un enlace, simplemente puede cambiar la propiedad de display :

<div id="myanchor" style="display: inline"> <h1 style="padding-top: 40px; margin-top: -40px;">My anchor</h1> </div>


Las soluciones con propiedades de posición cambiantes no siempre son posibles (puede destruir el diseño), por lo tanto, sugiero esto:

HTML:

<a id="top">Anchor</a>

CSS:

#top { margin-top: -250px; padding-top: 250px; }

Utilizar esta:

<a id="top">&nbsp;</a>

para minimizar la superposición y establecer el tamaño de fuente en 1px. El ancla vacía no funcionará en algunos navegadores.


Los métodos anteriores no funcionan muy bien si su ancla es un elemento de tabla o dentro de una tabla (fila o celda).

Tuve que usar javascript y vincularme al evento hashchange la ventana para evitar esto ( demo ):

function moveUnderNav() { var $el, h = window.location.hash; if (h) { $el = $(h); if ($el.length && $el.closest(''table'').length) { $(''body'').scrollTop( $el.closest(''table, tr'').position().top - 26 ); } } } $(window) .load(function () { moveUnderNav(); }) .on(''hashchange'', function () { moveUnderNav(); });

* Nota: El evento hashchange no está disponible en todos los navegadores.


Me encontré con este mismo problema y terminé manejando los eventos de clic manualmente, como:

$(''#mynav a'').click(() -> $(''html, body'').animate({ scrollTop: $($(this).attr(''href'')).offset().top - 40 }, 200 return false )

Animación de desplazamiento opcional, por supuesto.


Me enfrento a este problema en un sitio web de TYPO3, donde todos los "Elementos de contenido" se envuelven con algo como:

<div id="c1234" class="contentElement">...</div>

y cambié el renderizado para que se vea así:

<div id="c1234" class="anchor"></div> <div class="contentElement">...</div>

Y este CSS:

.anchor{ position: relative; top: -50px; }

La barra superior fija tiene 40px de alto, ahora los anclajes funcionan nuevamente y comienzan 10px debajo de la barra superior.

El único inconveniente de esta técnica es que ya no puede usar :target .


Mi solución combina el objetivo y los selectores anteriores para nuestro CMS. Otras técnicas no tienen en cuenta el texto en el anclaje. Ajuste la altura y el margen negativo al desplazamiento que necesita ...

:target:before { content: ""; display: inline-block; height: 180px; margin: -180px 0 0; }


Para el mismo problema, utilicé una solución fácil: poner un relleno de 40px en cada anclaje.


Para navegadores modernos, simplemente agregue el CSS3: selector de destino a la página. Esto se aplicará a todos los anclajes de forma automática.

:target { display: block; position: relative; top: -100px; visibility: hidden; }


Podrías simplemente usar CSS sin ningún javascript.

Dale a tu ancla una clase:

<a class="anchor" id="top"></a>

A continuación, puede colocar el anclaje un desplazamiento más alto o más bajo que donde realmente aparece en la página, convirtiéndolo en un elemento de bloque y posicionándolo relativamente. -250px posicionará el ancla hasta 250px

a.anchor { display: block; position: relative; top: -250px; visibility: hidden; }


Puede lograr esto sin una identificación usando el selector a a[name]:not([href]) css. Esto simplemente busca enlaces con un nombre y sin href, por ejemplo, <a name="anc1"></a>

Una regla de ejemplo podría ser:

a[name]:not([href]){ display: block; position: relative; top: -100px; visibility: hidden; }


Solución de CSS pura inspirada por Alexander Savin:

a[name] { padding-top: 40px; margin-top: -40px; display: inline-block; /* required for webkit browsers */ }

Opcionalmente, puede agregar lo siguiente si el objetivo aún está fuera de la pantalla:

vertical-align: top;


También puede agregar un ancla con el siguiente atributo:

(text-indent:-99999px;) visibility: hidden; position:absolute; top:-80px;

y le da al contenedor principal una posición relativa.

Funciona perfecto para mi


Tomando prestado parte del código de una respuesta dada en este enlace (no se especifica ningún autor), puede incluir un bonito efecto de desplazamiento suave en el anclaje, haciendo que se detenga a -60px por encima del ancla, encajando muy bien debajo de la navegación de arranque programada bar (requiere jQuery):

$(".dropdown-menu a[href^=''#'']").on(''click'', function(e) { // prevent default anchor click behavior e.preventDefault(); // animate $(''html, body'').animate({ scrollTop: $(this.hash).offset().top - 60 }, 300, function(){ }); });


Un giro adicional a la excelente respuesta de @Jan es incorporar esto en el encabezado fijo #uberbar, que usa jQuery (o MooTools). ( http://davidwalsh.name/persistent-header-opacity )

He modificado el código para que la parte superior del contenido esté siempre debajo, no debajo del encabezado fijo y también haya agregado los anclajes de @Jan de nuevo, asegurándome de que los anclajes estén siempre ubicados debajo del encabezado fijo.

El CSS:

#uberbar { border-bottom:1px solid #0000cc; position:fixed; top:0; left:0; z-index:2000; width:100%; } a.anchor { display: block; position: relative; visibility: hidden; }

El jQuery (incluidos los ajustes tanto a #uberbar como a los enfoques de anclaje:

<script type="text/javascript"> $(document).ready(function() { (function() { //settings var fadeSpeed = 200, fadeTo = 0.85, topDistance = 30; var topbarME = function() { $(''#uberbar'').fadeTo(fadeSpeed,1); }, topbarML = function() { $(''#uberbar'').fadeTo(fadeSpeed,fadeTo); }; var inside = false; //do $(window).scroll(function() { position = $(window).scrollTop(); if(position > topDistance && !inside) { //add events topbarML(); $(''#uberbar'').bind(''mouseenter'',topbarME); $(''#uberbar'').bind(''mouseleave'',topbarML); inside = true; } else if (position < topDistance){ topbarME(); $(''#uberbar'').unbind(''mouseenter'',topbarME); $(''#uberbar'').unbind(''mouseleave'',topbarML); inside = false; } }); $(''#content'').css({''margin-top'': $(''#uberbar'').outerHeight(true)}); $(''a.anchor'').css({''top'': - $(''#uberbar'').outerHeight(true)}); })(); }); </script>

Y finalmente el HTML:

<div id="uberbar"> <!--CONTENT OF FIXED HEADER--> </div> .... <div id="content"> <!--MAIN CONTENT--> .... <a class="anchor" id="anchor1"></a> .... <a class="anchor" id="anchor2"></a> .... </div>

¡Tal vez esto sea útil para alguien a quien le gusta el encabezado digerido #uberbar!


.vspace elemento .vspace 40px de altura sujetando el anclaje antes de cada uno de mis elementos h1 .

<div class="vspace" id="gherkin"></div> <div class="page-header"> <h1>Gherkin</h1> </div>

En el CSS:

.vspace { height: 40px;}

Está funcionando muy bien y el espacio no es sorprendente.