J'ai ce code pour mon site Web
function clickMe() {
var element = document.getElementById('about');
element.scrollIntoView({
block: "start",
behavior: "smooth",
});
}
Cela fonctionne assez bien mais j'ai un en-tête fixe, donc lorsque le code défile jusqu'à l'élément, l'en-tête est gênant.
Existe-t-il un moyen d'avoir un décalage et de le faire défiler en douceur?
5 réponses
Existe-t-il un moyen d'avoir un décalage et de le faire défiler en douceur?
Oui, mais pas avec scrollIntoView ()
Les scrollIntoViewOptions de Element.scrollIntoView () ne vous permettez pas d'utiliser un décalage. Il est uniquement utile lorsque vous souhaitez faire défiler jusqu'à la position exacte de l'élément.
Vous pouvez cependant utiliser Window.scrollTo () avec des options pour faire défiler jusqu'à une position décalée et pour le faire en douceur .
Si vous avez un en-tête d'une hauteur de 30px
par exemple, vous pouvez effectuer les opérations suivantes:
function scrollToTargetAdjusted(){
var element = document.getElementById('targetElement');
var headerOffset = 45;
var elementPosition = element.getBoundingClientRect().top;
var offsetPosition = elementPosition - headerOffset;
window.scrollTo({
top: offsetPosition,
behavior: "smooth"
});
}
Cela défilera en douceur jusqu'à votre élément afin qu'il ne soit pas bloqué par votre en-tête.
Remarque : vous soustrayez le décalage car vous voulez vous arrêter avant de faire défiler votre en-tête sur votre élément.
Voyez-le en action
Vous pouvez comparer les deux options dans l'extrait ci-dessous.
<script type="text/javascript">
function scrollToTarget() {
var element = document.getElementById('targetElement');
element.scrollIntoView({
block: "start",
behavior: "smooth",
});
}
function scrollToTargetAdjusted() {
var element = document.getElementById('targetElement');
var headerOffset = 45;
var elementPosition = element.getBoundingClientRect().top;
var offsetPosition = elementPosition - headerOffset;
window.scrollTo({
top: offsetPosition,
behavior: "smooth"
});
}
function backToTop() {
window.scrollTo(0, 0);
}
</script>
<div id="header" style="height:30px; width:100%; position:fixed; background-color:lightblue; text-align:center;"> <b>Fixed Header</b></div>
<div id="mainContent" style="padding:30px 0px;">
<button type="button" onclick="scrollToTarget();">element.scrollIntoView() smooth, header blocks view</button>
<button type="button" onclick="scrollToTargetAdjusted();">window.scrollTo() smooth, with offset</button>
<div style="height:1000px;"></div>
<div id="targetElement" style="background-color:red;">Target</div>
<br/>
<button type="button" onclick="backToTop();">Back to top</button>
<div style="height:1000px;"></div>
</div>
Je sais que c'est un hack et c'est certainement quelque chose que vous devez utiliser avec prudence, mais vous pouvez réellement ajouter un padding
et un margin
négatif à l'élément. Je ne peux pas garantir que cela fonctionnerait pour vous car je n'ai pas votre balisage et votre code, mais j'ai eu un problème similaire et j'ai utilisé cette solution de contournement pour le résoudre.
Supposons que votre en-tête soit 30px
et que vous souhaitez un décalage de 15px
, puis:
#about {
padding-top: 45px; // this will allow you to scroll 15px below your 30px header
margin-top: -45px; // and this will make sure that you don't change your layout because of it
}
La réponse de Søren D. Ptæus m'a mis sur la bonne voie mais j'ai eu des problèmes avec getBoundingClientRect()
quand je n'étais pas au sommet du window
.
Ma solution ajoute un peu plus à la sienne pour que getBoundingClientRect()
fonctionne un peu plus régulièrement et avec plus de polyvalence. J'ai utilisé l'approche décrite ici et l'ai mise en œuvre pour faire fonctionner cela comme prévu.
const element = document.getElementById('targetElement');
const offset = 45;
const bodyRect = document.body.getBoundingClientRect().top;
const elementRect = element.getBoundingClientRect().top;
const elementPosition = elementRect - bodyRect;
const offsetPosition = elementPosition - offset;
window.scrollTo({
top: offsetPosition,
behavior: 'smooth'
});
N'oubliez pas d'inclure le polyfill lors de l'implémentation!
J'ai essayé les autres solutions, mais j'avais un comportement étrange. Cependant, cela a fonctionné pour moi.
function scrollTo(id) {
var element = document.getElementById(id);
var headerOffset = 60;
var elementPosition = element.offsetTop;
var offsetPosition = elementPosition - headerOffset;
document.documentElement.scrollTop = offsetPosition;
document.body.scrollTop = offsetPosition; // For Safari
}
Et le style:
html {
scroll-behavior: smooth;
}
Solution simple mais élégante si l'élément a une petite hauteur (plus courte que la fenêtre):
element.scrollIntoView({ behavior: 'instant', block: 'center' });
Le block: center
fera défiler l'élément de sorte que le centre de l'élément soit au centre vertical de la fenêtre, de sorte que l'en-tête supérieur ne le couvrira pas.
Questions connexes
De nouvelles questions
javascript
Pour des questions concernant la programmation dans ECMAScript (JavaScript / JS) et ses divers dialectes / implémentations (hors ActionScript). Veuillez inclure toutes les balises pertinentes dans votre question; par exemple, [node.js], [jquery], [json], etc.