Hvordan finder vi bredden og højden på browserens vindue? Hvordan får vi den fulde bredde og højde af dokumentet … inklusiv den del, der er rullet ud så vi ikke kan se den? Hvordan ruller vi siden ved hjælp af JavaScript?
Til denne type information kan vi bruge det roden dokumentelement document.documentElement, der svarer til <html> taggen. Men der er en del særheder at overveje, fordi de virker lidt forskelligt i forskellige browsere. Og det kan være svært at gennemskue.
Bredde/højde på vinduet
For at få vinduets bredde og højde kan vi bruge clientWidth/clientHeight af document.documentElement:
For eksempel viser denne knap højden på dit vindue:
window.innerWidth/innerHeightBrowsere understøtter også egenskaber som window.innerWidth/innerHeight. De ser ud til at være det vi vil have, så hvorfor ikke bruge dem i stedet?
Hvis der er et scrollbar, og det optager plads, giver clientWidth/clientHeight bredden og højden uden (minus) det. Med andre ord returnerer de bredden og højden af den synlige del af dokumentet, klar til brug af indholdet.
window.innerWidth/innerHeight inkluderer scrollbar’en.
Hvis der er et scrollbar, og det optager plads, så viser disse to linjer forskellige værdier:
alert( window.innerWidth ); // fuld bredde af vinduet
alert( document.documentElement.clientWidth ); // vinduets bredde minus scrollbar'en
I de fleste tilfælde har vi brug for den tilgængelige bredde af vinduet for at kunne tegne eller placere noget inden for scrollbars (hvis der er nogen), så vi bør bruge documentElement.clientHeight/clientWidth.
DOCTYPE er vigtigtBemærk: top-level geometri egenskaber kan virke en smule anderledes, når der ikke er et <!DOCTYPE HTML> i HTML’en. Lidt mærkeligt men sandt.
I moderne HTML bør vi altid skrive DOCTYPE.
Bredde/højde på dokumentet
Teoretisk set er document.documentElement roden – det vil sige det element der indeholder alt indholdet – så vi kunne forvente at kunne måle dokumentets fulde størrelse som document.documentElement.scrollWidth/scrollHeight.
Men for siden som helhed virker disse egenskaber ikke altid som forventet. For eksempel kan document.documentElement.scrollHeight være mindre end document.documentElement.clientHeight i Chrome/Safari/Opera, hvis der ikke er noget scrollbar. Mærkeligt, ikke?
For at få den fulde højde på dokumentet med sikkerhed, skal vi tage maksimum af følgende egenskaber:
let scrollHeight = Math.max(
document.body.scrollHeight, document.documentElement.scrollHeight,
document.body.offsetHeight, document.documentElement.offsetHeight,
document.body.clientHeight, document.documentElement.clientHeight
);
alert('Dokumentets fulde højde, inklusiv den del der er scrollet ud: ' + scrollHeight);
Hvorfor det? Jeg tror det er bedre at lade være med at spørge. Disse uoverensstemmelser stammer fra gamle dage, ikke fra en “smart” logik.
Find den nuværende scroll position
DOM-elementer har deres nuværende scroll information i deres scrollLeft/scrollTop egenskaber.
document.documentElement.scrollLeft/scrollTop virker i de fleste browsere, undtagen ældre WebKit-baserede browsere, som Safari (bug 5991), hvor vi skal bruge document.body i stedet for document.documentElement.
Heldigvis behøver vi slet ikke at huske disse særheder, for scroll positionen er tilgængelig i de specielle egenskaber window.pageXOffset/pageYOffset:
alert('Aktuelle scroll position fra toppen: ' + window.pageYOffset);
alert('Aktuelle scroll position fra venstre: ' + window.pageXOffset);
Disse egenskaber kan kun læses.
window-egenskaberne scrollX og scrollYAf historiske årsager eksisterer begge egenskaber, men de er det samme:
window.pageXOffseter et alias forwindow.scrollX.window.pageYOffseter et alias forwindow.scrollY.
Scrolling: scrollTo, scrollBy, scrollIntoView
For at rulle siden med JavaScript skal dens DOM være fuldt udbygget.
For eksempel vil det ikke virke, hvis vi forsøger at rulle siden med et script i <head>.
Regelmæssige elementer kan rulles ved at ændre scrollTop/scrollLeft.
Vi kan gøre det samme for siden ved hjælp af document.documentElement.scrollTop/scrollLeft (undtagen Safari, hvor document.body.scrollTop/Left skal bruges i stedet).
Alternativt er der en simplere, universel løsning: de specielle metoder window.scrollBy(x,y) og window.scrollTo(pageX,pageY).
-
Metoden
scrollBy(x,y)ruller siden relativt til dens nuværende position. For eksempel vilscrollBy(0,10)rulle siden10pxned.Knappen herunder demonstrerer dette:
-
Metoden
scrollTo(pageX,pageY)ruller siden til absolutte koordinater, således at øverste venstre hjørne af den synlige del har koordinaterne(pageX, pageY)relativt til dokumentets øverste venstre hjørne. Det er som at sættescrollLeft/scrollTop.For at rulle til helt i begyndelsen kan vi bruge
scrollTo(0,0).
Disse metoder virker på tværs af alle browsere på samme måde.
scrollIntoView
For fuldstændighedens skyld, lad os dække én metode mere: elem.scrollIntoView(top).
Kaldet til elem.scrollIntoView(top) ruller siden for at gøre elem synlig. Den har et argument:
- Hvis
top=true(standard), så rulles siden for at gøreelemsynlig øverst i vinduet. Elementets øvre kant vil blive justeret med vinduets top. - Hvis
top=false, så rulles siden for at gøreelemsynlig nederst. Elementets nedre kant vil blive justeret med vinduets bund.
Knappen herunder ruller siden for at positionere sig selv øverst i vinduet:
Og denne knap ruller siden for at positionere sig selv nederst:
Forbud mod scrolling
Nogle gange skal vi gøre dokumentet “unscrollable”. For eksempel, når vi skal dække siden med en stor besked, der kræver øjeblikkelig opmærksomhed, og vi ønsker, at den besøgende skal interagere med den besked, ikke med dokumentet.
For at forhindre scrolling i dokumentet er det nok at sætte document.body.style.overflow = "hidden". Siden vil “fryse” ved sin nuværende scroll position.
Prøv det:
Den første knap forhindrer scrollingen, mens den anden frigiver den.
Den samme teknik kan bruges til at forhindre scrollingen for andre elementer end document.body.
Ulempen ved metoden er, at scrollbaren forsvinder. Hvis den optog noget plads, så er den plads nu fri og indholdet “springer” for at fylde den.
Det ser lidt mærkeligt ud, men kan løses ved at sammenligne clientWidth før og efter pausen. Hvis den steg (scrollbaren forsvandt), så tilføjes padding til document.body i stedet for scrollbaren for at holde indholdets bredde den samme.
Opsummering
Geometri:
-
Bredde/højde på den synlige del af dokumentet (indholdsområdets bredde/højde):
document.documentElement.clientWidth/clientHeight -
Bredde/højde af hele dokumentet, med den del der er scrollet ud:
let scrollHeight = Math.max( document.body.scrollHeight, document.documentElement.scrollHeight, document.body.offsetHeight, document.documentElement.offsetHeight, document.body.clientHeight, document.documentElement.clientHeight );
Scrolling:
-
Læs den aktuelle scroll:
window.pageYOffset/pageXOffset. -
Ændr den aktuelle scroll:
window.scrollTo(pageX,pageY)– absolutte koordinater,window.scrollBy(x,y)– scroll relativt til den aktuelle position,elem.scrollIntoView(top)– scroll for at gøreelemsynlig (juster med toppen/bunden af vinduet).
Kommentarer
<code>-taggen, for flere linjer - omslut dem i<pre>-tag, for mere end 10 linjer - brug en sandbox (plnkr, jsbin, codepen…)