Comme il s'agit d'un souci de présentation, une solution purement CSS serait idéale. Cependant, cette question a été posée en 2012, et bien que des solutions de positionnement relatif / marge négative aient été suggérées, ces approches semblent plutôt bricolées, créent des problèmes potentiels de flux, et ne peuvent pas répondre dynamiquement aux changements dans le DOM / viewport.
En gardant cela à l'esprit, je pense que l'utilisation de JavaScript est toujours (février 2017) la meilleure approche. Voici une solution vanilla-JS qui répondra à la fois aux clics des ancres et résoudra le hachage de la page au chargement. (Voir JSFiddle) . Modifiez le .getFixedOffset()
si des calculs dynamiques sont nécessaires. Si vous utilisez jQuery, voici une solution modifiée avec une meilleure délégation des événements et un défilement fluide .
(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);
1 votes
Le div wrapper présenté dans stackoverflow.com/questions/1431639/ est bien, je pense, pas trop agressif.
37 votes
Il existe un bel article sur ce sujet : css-tricks.com/hash-tag-links-padding
1 votes
En rapport : stackoverflow.com/questions/4086107/
1 votes
@0fnt, Ceci est en fait un duplicata de ce post. Pourquoi n'est-il pas fermé ?
0 votes
@Pacerier Je pense que cela nécessite une action du modérateur. Je l'ai signalé cependant
0 votes
Re : suppression de ce message, de SO : Cette question ne peut pas être supprimée car d'autres questions sont liées en tant que doublons de celle-ci.
3 votes
La question qui marque celle-ci comme dupliquée n'accepte pas les solutions javascript. Cette question a des solutions script. Elle devrait être réouverte.
0 votes
Cette solution est la meilleure : stackoverflow.com/a/28824157/1066234
0 votes
Je cherche une solution qui * fonctionne pour les ancres provenant de la même page ou d'une autre page, * et qui ajuste l'appui sur la touche de descente de page pour que le contenu ne soit pas coupé par l'en-tête, * et qui permet au pied de page sib-div de défiler vers le haut avec le contenu-div. Je n'ai pas encore trouvé de solution ! stackoverflow.com/questions/51070758/
1 votes
@J.Bruni Il existe un article beaucoup plus récent de CSS-tricks.com sur
scroll-padding-top
ici : css-tricks.com/