Ik heb een pagina waar een schuifbalk met tabelrijen met divs erin dynamisch wordt gegenereerd vanuit de database. Elke tabelrij fungeert als een link, een beetje zoals je zou zien in een YouTube-afspeellijst naast de videospeler.
Wanneer een gebruiker de pagina bezoekt, wordt verondersteld dat de optie die ze gebruiken naar de bovenkant van de scrollende div gaat. Deze functionaliteit werkt. Het probleem is dat het net iets te ver gaat. Alsof de optie waarop ze staan ongeveer 10px te hoog is. Dus de pagina wordt bezocht, de url wordt gebruikt om te identificeren welke optie is geselecteerd en schuift die optie vervolgens naar de bovenkant van de scrollende div. Opmerking: dit is niet de schuifbalk voor het venster, het is een div met een schuifbalk.
Ik gebruik deze code om de geselecteerde optie naar de bovenkant van de div te verplaatsen:
var pathArray = window.location.pathname.split( '/' );
var el = document.getElementById(pathArray[5]);
el.scrollIntoView(true);
Het verplaatst het naar de bovenkant van de div, maar ongeveer 10 pixels te ver naar boven.
Weet iemand hoe je dat oplost?
Antwoord 1, autoriteit 100%
Vloeiend scrollen naar de juiste positie
Verkrijg correctey
-coördinaat en gebruik window.scrollTo({top: y, behavior: 'smooth'})
const id = 'profilePhoto';
const yOffset = -10;
const element = document.getElementById(id);
const y = element.getBoundingClientRect().top + window.pageYOffset + yOffset;
window.scrollTo({top: y, behavior: 'smooth'});
Antwoord 2, autoriteit 49%
Plaats anker volgens absolute methode
Een andere manier om dit te doen, is door uw ankers precies daar te plaatsen waar u wilt op de pagina, in plaats van te vertrouwen op verschuiving van scrollen. Ik vind dat het een betere controle biedt voor elk element (bijvoorbeeld als je een andere offset wilt voor bepaalde elementen), en mogelijk ook beter bestand is tegen wijzigingen/verschillen in de browser-API.
<div id="title-element" style="position: relative;">
<div id="anchor-name" style="position: absolute; top: -100px; left: 0"></div>
</div>
De offset is nu gespecificeerd als -100px ten opzichte van het element. Maak een functie om dit anker te maken voor hergebruik van code, of als u een modern JS-framework zoals React gebruikt, doe dit door een component te maken die uw anker weergeeft, en geef de ankernaam en uitlijning door voor elk element, wat al dan niet kan niet hetzelfde zijn.
Gebruik dan gewoon :
const element = document.getElementById('anchor-name')
element.scrollIntoView({ behavior: 'smooth', block: 'start' });
Voor soepel scrollen met een offset van 100px.
Antwoord 3, autoriteit 45%
Je kunt het in twee stappen doen:
el.scrollIntoView(true);
window.scrollBy(0, -10); // Adjust scrolling with a negative value here
Antwoord 4, autoriteit 28%
Als het ongeveer 10px is, dan denk ik dat je de scroll-offset van de bevattende div
eenvoudig zo handmatig kunt aanpassen:
el.scrollIntoView(true);
document.getElementById("containingDiv").scrollTop -= 10;
Antwoord 5, autoriteit 23%
Ik heb dit probleem opgelost door te gebruiken,
element.scrollIntoView({ behavior: 'smooth', block: 'center' });
Hierdoor verschijnt het element in het center
na het scrollen, zodat ik yOffset
niet hoef te berekenen.
Hopelijk helpt het…
Antwoord 6, autoriteit 15%
Dit werkt voor mij in Chrome (met soepel scrollen en geen timing-hacks)
Het verplaatst alleen het element, start het scrollen en verplaatst het vervolgens terug.
Er is geen “knallen” zichtbaar als het element al op het scherm staat.
pos = targetEle.style.position;
top = targetEle.style.top;
targetEle.style.position = 'relative';
targetEle.style.top = '-20px';
targetEle.scrollIntoView({behavior: 'smooth', block: 'start'});
targetEle.style.top = top;
targetEle.style.position = pos;
Antwoord 7, autoriteit 3%
Een andere oplossing is om “offsetTop” als volgt te gebruiken:
var elementPosition = document.getElementById('id').offsetTop;
window.scrollTo({
top: elementPosition - 10, //add your necessary value
behavior: "smooth" //Smooth transition to roll
});
Antwoord 8, autoriteit 2%
U kunt ook de element.scrollIntoView()
opties
el.scrollIntoView(
{
behavior: 'smooth',
block: 'start'
},
);
die de meeste browsers ondersteunen
Antwoord 9, autoriteit 2%
Ik heb dit en het werkt uitstekend voor mij:
// add a smooth scroll to element
scroll(el) {
el.scrollIntoView({
behavior: 'smooth',
block: 'start'});
setTimeout(() => {
window.scrollBy(0, -40);
}, 500);}
Hopelijk helpt het.
Antwoord 10, autoriteit 2%
Dus misschien is dit een beetje onhandig, maar tot nu toe gaat het goed. Ik werk in hoekige 9.
bestand .ts
scroll(el: HTMLElement) {
el.scrollIntoView({ block: 'start', behavior: 'smooth' });
}
bestand .html
<button (click)="scroll(target)"></button>
<div #target style="margin-top:-50px;padding-top: 50px;" ></div>
Ik pas de offset aan met marge en opvulling bovenaan.
Saludos!
Antwoord 11
Oplossing als u Ionic Capacitor, Angular Material gebruikt en iOS 11 moet ondersteunen.
document.activeElement.parentElement.parentElement.scrollIntoView({block: 'center', behavior: 'smooth'});
De sleutel is om naar de ouder van de ouder te scrollen, de wrapper rond de invoer. Deze wrapper bevat het label voor de invoer die nu niet langer is afgesneden.
Als je alleen iOS 14 hoeft te ondersteunen, werkt de “block” center-param echt, dus dit is voldoende:
document.activeElement.scrollIntoView({block: 'center', behavior: 'smooth'});
Antwoord 12
Een tijdelijke oplossing gevonden. Stel dat je naar een div wilt scrollen, Element hier bijvoorbeeld, en je wilt een ruimte van 20px erboven hebben.
Stel de ref in op een gemaakte div erboven:
<div ref={yourRef} style={{position: 'relative', bottom: 20}}/>
<Element />
Als u dit doet, wordt de gewenste tussenruimte gecreëerd.
Als je een koptekst hebt, maak dan ook een lege div achter de koptekst en wijs hieraan een hoogte toe die gelijk is aan de hoogte van de koptekst en verwijs ernaar.
Antwoord 13
Mijn belangrijkste idee is het creëren van een tempDivboven de weergave waarnaar we willen scrollen. Het werkt goed zonder achter te blijven in mijn project.
scrollToView = (element, offset) => {
var rect = element.getBoundingClientRect();
var targetY = rect.y + window.scrollY - offset;
var tempDiv;
tempDiv = document.getElementById("tempDiv");
if (tempDiv) {
tempDiv.style.top = targetY + "px";
} else {
tempDiv = document.createElement('div');
tempDiv.id = "tempDiv";
tempDiv.style.background = "#F00";
tempDiv.style.width = "10px";
tempDiv.style.height = "10px";
tempDiv.style.position = "absolute";
tempDiv.style.top = targetY + "px";
document.body.appendChild(tempDiv);
}
tempDiv.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
Voorbeeld met
onContactUsClick = () => {
this.scrollToView(document.getElementById("contact-us"), 48);
}
Ik hoop dat het helpt
Antwoord 14
Gebaseerd op het antwoord van Arseniy-II: ik had de use-case waarbij de scrollende entiteit niet het venster zelf was, maar een innerlijke sjabloon (in dit geval een div). In dit scenario moeten we een ID voor de schuifcontainer instellen en deze via getElementById
ophalen om de schuiffunctie te gebruiken:
<div class="scroll-container" id="app-content">
...
</div>
const yOffsetForScroll = -100
const y = document.getElementById(this.idToScroll).getBoundingClientRect().top;
const main = document.getElementById('app-content');
main.scrollTo({
top: y + main.scrollTop + yOffsetForScroll,
behavior: 'smooth'
});
Laat het hier achter voor het geval iemand in een vergelijkbare situatie zit!
Antwoord 15
Hier is mijn 2 cent.
Ik heb ook het probleem gehad dat de scrollIntoView een beetje voorbij het element scrolde, dus ik heb een script (native javascript) gemaakt dat een element voor de bestemming plaatst, het een beetje naar boven gepositioneerd met css en daarnaartoe gescrolld een. Na het scrollen verwijder ik de gemaakte elementen weer.
HTML:
//anchor tag that appears multiple times on the page
<a href="#" class="anchors__link js-anchor" data-target="schedule">
<div class="anchors__text">
Scroll to the schedule
</div>
</a>
//The node we want to scroll to, somewhere on the page
<div id="schedule">
//html
</div>
Javascript-bestand:
(() => {
'use strict';
const anchors = document.querySelectorAll('.js-anchor');
//if there are no anchors found, don't run the script
if (!anchors || anchors.length <= 0) return;
anchors.forEach(anchor => {
//get the target from the data attribute
const target = anchor.dataset.target;
//search for the destination element to scroll to
const destination = document.querySelector(`#${target}`);
//if the destination element does not exist, don't run the rest of the code
if (!destination) return;
anchor.addEventListener('click', (e) => {
e.preventDefault();
//create a new element and add the `anchors__generated` class to it
const generatedAnchor = document.createElement('div');
generatedAnchor.classList.add('anchors__generated');
//get the first child of the destination element, insert the generated element before it. (so the scrollIntoView function scrolls to the top of the element instead of the bottom)
const firstChild = destination.firstChild;
destination.insertBefore(generatedAnchor, firstChild);
//finally fire the scrollIntoView function and make it animate "smoothly"
generatedAnchor.scrollIntoView({
behavior: "smooth",
block: "start",
inline: "start"
});
//remove the generated element after 1ms. We need the timeout so the scrollIntoView function has something to scroll to.
setTimeout(() => {
destination.removeChild(generatedAnchor);
}, 1);
})
})
})();
CSS:
.anchors__generated {
position: relative;
top: -100px;
}
Ik hoop dat dit iemand helpt!
Antwoord 16
Ik voeg deze css-tips toe voor degenen die dit probleem niet hebben opgelost met bovenstaande oplossingen:
#myDiv::before {
display: block;
content: " ";
margin-top: -90px; // adjust this with your header height
height: 90px; // adjust this with your header height
visibility: hidden;
}
Antwoord 17
UPD: ik heb een npm-pakketgemaakt dat beter werkt dan het volgende oplossing en gemakkelijker te gebruiken.
Mijn smoothScroll-functie
Ik heb de geweldige oplossing van Steve Banton genomen en een functie geschreven die het gebruik gemakkelijker maakt. Het zou gemakkelijker zijn om gewoon window.scroll()
of zelfs window.scrollBy()
te gebruiken, zoals ik eerder heb geprobeerd, maar deze twee hebben wat problemen:
- Alles wordt rommel na gebruik met een soepel gedrag aan.
- Je kunt ze hoe dan ook niet voorkomen en moet wachten tot de en van de boekrol.
Dus ik hoop dat mijn functie nuttig voor je zal zijn. Er is ook een lichtgewicht polyfillwaardoor het werkt in Safari en zelfs IE.
Hier is de code
Kopieer het gewoon en verpruts het zoals je wilt.
import smoothscroll from 'smoothscroll-polyfill';
smoothscroll.polyfill();
const prepareSmoothScroll = linkEl => {
const EXTRA_OFFSET = 0;
const destinationEl = document.getElementById(linkEl.dataset.smoothScrollTo);
const blockOption = linkEl.dataset.smoothScrollBlock || 'start';
if ((blockOption === 'start' || blockOption === 'end') && EXTRA_OFFSET) {
const anchorEl = document.createElement('div');
destinationEl.setAttribute('style', 'position: relative;');
anchorEl.setAttribute('style', `position: absolute; top: -${EXTRA_OFFSET}px; left: 0;`);
destinationEl.appendChild(anchorEl);
linkEl.addEventListener('click', () => {
anchorEl.scrollIntoView({
block: blockOption,
behavior: 'smooth',
});
});
}
if (blockOption === 'center' || !EXTRA_OFFSET) {
linkEl.addEventListener('click', () => {
destinationEl.scrollIntoView({
block: blockOption,
behavior: 'smooth',
});
});
}
};
export const activateSmoothScroll = () => {
const linkEls = [...document.querySelectorAll('[data-smooth-scroll-to]')];
linkEls.forEach(linkEl => prepareSmoothScroll(linkEl));
};
Als u een link-element wilt maken, hoeft u alleen het volgende data-attribuut toe te voegen:
data-smooth-scroll-to="element-id"
U kunt ook een ander kenmerk instellen als toevoeging
data-smooth-scroll-block="center"
Het vertegenwoordigt de optie block
van de functie scrollIntoView()
. Standaard is dit start
. Lees meer op MDN.
Eindelijk
Pas de smoothScroll-functie aan uw behoeften aan.
Als je bijvoorbeeld een vaste header hebt (of ik noem het met het woord masthead
), dan kun je zoiets als dit doen:
const mastheadEl = document.querySelector(someMastheadSelector);
// and add it's height to the EXTRA_OFFSET variable
const EXTRA_OFFSET = mastheadEl.offsetHeight - 3;
Als je zo’n hoesje niet hebt, verwijder het dan gewoon, waarom niet :-D.
Antwoord 18
Ik heb geprobeerd enkele van de bovenstaande antwoorden te gebruiken, maar scrollen werkte niet. Na wat speurwerk merkte ik dat de scrollposities in feite heel vreemd waren (zelfs negatieve waarden) en dat dit werd veroorzaakt door hoe Angular de pagina’s in de router-outlet
weergaf.
Mijn oplossing was om de schuifpositie van het element te berekenen vanaf de bovenkant van de pagina. Ik heb een element met id start-of-page
aan het begin van de sjabloon geplaatst en ik heb de hoeveelheid scroll verkregen door de positie van het doelfragment af te trekken.
ngAfterViewInit(): void {
this.route.fragment.subscribe(fragment => {
try {
// @ts-ignore
// document.querySelector('#hero').scrollIntoView({behavior:smooth, block: "start", inline: "start"});
// @ts-ignore
// document.querySelector('#' + fragment).scrollIntoView({behavior:smooth, block: "start", inline: "start"});
this._scrollTo('#' + fragment,0);
} catch (e) { };
});
}
private _scrollTo(selector: any, yOffset = 0){
const base = document.querySelector('#start-of-page');
const el = document.querySelector(selector);
// @ts-ignore
const y = el.getBoundingClientRect().top - base.getBoundingClientRect().top;
window.scrollTo({top: y, behavior: 'smooth'});
}
Antwoord 19
Een oplossing is om een onzichtbaar tijdelijk element te maken met een offset ten opzichte van het doel, ernaartoe te scrollen en het vervolgens te verwijderen. Het is misschien niet ideaal, maar andere oplossingen werkten niet voor mij in de context waarin ik werkte. Bijvoorbeeld:
const createOffsetElement = (element) => {
const offsetElement = document.createElement('div');
offsetElement.style = `
position: relative;
top: -10em;
height: 1px;
width: 1px;
visibility: hidden;
`;
const inputWrapper = element.closest('.ancestor-element-class');
inputWrapper.appendChild(offsetElement);
return offsetElement;
};
const scrollTo = (element) => {
const offsetElement = createOffsetElement(element);
offsetElement.scrollIntoView({
behavior: 'smooth',
});
offsetElement.remove();
};
Antwoord 20
De eenvoudigste manier om dit te doen,
html, body {
scroll-behavior: smooth;
}
html [id], body [id] {
scroll-margin: 50px !important;
}
met de door u verstrekte code
var pathArray = window.location.pathname.split( '/' );
var el = document.getElementById(pathArray[5]);
el.style.scrollMargin = 50px !important;
el.scrollIntoView(true);
Antwoord 21
Eenvoudige oplossing voor het naar beneden scrollen van een specifiek element
const element = document.getElementById("element-with-scroll");
element.scrollTop = element.scrollHeight - 10;
Antwoord 22
Gebruik voor een element in een tabelrij JQuery om de rij boven de gewenste rij te krijgenen scrol in plaats daarvan naar die rij.
Stel dat ik meerdere rijen in een tabel heb, waarvan sommige moeten worden beoordeeld door en admin. Elke rij die moet worden beoordeeld, heeft zowel een pijl omhoog als een pijl omlaag om u naar het vorige of volgende item te brengen dat moet worden beoordeeld.
Hier is een compleet voorbeeld dat moet worden uitgevoerd als u een nieuw HTML-document in Kladblok maakt en opslaat. Er is extra code om de boven- en onderkant van onze artikelen te detecteren voor beoordeling, zodat we geen fouten maken.
<html>
<head>
<title>Scrolling Into View</title>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<style>
div.scroll { height: 6em; width: 20em; overflow: auto; }
thead th { position: sticky; top: -1px; background: #fff; }
.up, .down { cursor: pointer; }
.up:hover, .down:hover { color: blue; text-decoration:underline; }
</style>
</head>
<body>
<div class='scroll'>
<table border='1'>
<thead>
<tr>
<th>Review</th>
<th>Data</th>
</tr>
</thead>
<tbody>
<tr id='row_1'>
<th></th>
<td>Row 1 (OK)</td>
</tr>
<tr id='row_2'>
<th></th>
<td>Row 2 (OK)</td>
</tr>
<tr id='row_3'>
<th id='jump_1'><span class='up'>UP</span> <span class='down'>DN</span></th>
<td>Row 3 (REVIEW)</td>
</tr>
<tr id='row_4'>
<th></th>
<td>Row 4 (OK)</td>
</tr>
<tr id='row_5'>
<th id='jump_2'><span class='up'>UP</span> <span class='down'>DN</span></th>
<td>Row 5 (REVIEW)</td>
</tr>
<tr id='row_6'>
<th></th>
<td>Row 6 (OK)</td>
</tr>
<tr id='row_7'>
<th></th>
<td>Row 7 (OK)</td>
</tr>
<tr id='row_8'>
<th id='jump_3'><span class='up'>UP</span> <span class='down'>DN</span></th>
<td>Row 8 (REVIEW)</td>
</tr>
<tr id='row_9'>
<th></th>
<td>Row 9 (OK)</td>
</tr>
<tr id='row_10'>
<th></th>
<td>Row 10 (OK)</td>
</tr>
</tbody>
</table>
</div>
<script>
$(document).ready( function() {
$('.up').on('click', function() {
var id = parseInt($(this).parent().attr('id').split('_')[1]);
if (id>1) {
var row_id = $('#jump_' + (id - 1)).parent().attr('id').split('_')[1];
document.getElementById('row_' + (row_id-1)).scrollIntoView({behavior: 'smooth', block: 'start'});
} else {
alert('At first');
}
});
$('.down').on('click', function() {
var id = parseInt($(this).parent().attr('id').split('_')[1]);
if ($('#jump_' + (id + 1)).length) {
var row_id = $('#jump_' + (id + 1)).parent().attr('id').split('_')[1];
document.getElementById('row_' + (row_id-1)).scrollIntoView({behavior: 'smooth', block: 'start'});
} else {
alert('At last');
}
});
});
</script>
</body>
</html>