Does Instagram's toolbar cover the bottom 44px when scrolling?

Stop rulning i Safari: En komplet guide

06/02/2025

Rating: 4.45 (15589 votes)
Indholdsfortegnelse

Forståelse af Rulning og Zoom i Safari

På mobile enheder, især iPhones og iPads, er touch-interaktioner kernen i brugeroplevelsen. Safari, Apples standardbrowser, fortolker en række bevægelser som rulning, zoom og panorering. Mens disse funktioner generelt forbedrer navigationen, kan der opstå situationer, hvor det er nødvendigt at begrænse eller helt deaktivere dem. Dette er især relevant for webudviklere, der ønsker at skabe specifikke brugergrænseflader, såsom fuldskærmsmodaler, hamburgermenuer eller interaktive elementer, hvor baggrundsinformationen ikke skal kunne tilgås ved et uheld under interaktionen med et specifikt indholdsområde.

How do I make a lock scrolling class jarring?
This often impacts useability on mobile devices, and depending on your layout, the scrolling of background content can be visually jarring. The common quick solution (with a few pitfalls) is to dynamically create some sort of a lock scrolling class such as the following: overflow: hidden;

Denne artikel vil dykke ned i, hvordan man kan styre og potentielt deaktivere rulning og zoom i Safari. Vi vil udforske både de indbyggede mekanismer i webteknologier og de metoder, der kan anvendes for at opnå den ønskede kontrol. Det er vigtigt at bemærke, at en fuldstændig deaktivering af alle touch-interaktioner kan have en negativ indvirkning på brugeroplevelsen, hvis det ikke implementeres korrekt. Målet er ofte at forhindre uønsket baggrunds-rulning, mens specifikke elementer forbliver scrollbare.

CSS-baserede Løsninger: touch-action

CSS tilbyder en kraftfuld egenskab kaldet touch-action, som giver udviklere mulighed for at styre, hvordan et element reagerer på touch-input. Denne egenskab er designet til at håndtere almindelige touch-gestus som rulning, zoom og panning.

Grundlæggende Brug af touch-action

Den mest direkte måde at begrænse rulning på er ved at sætte touch-action til none på et specifikt element. Dette vil som udgangspunkt forhindre både vandret og lodret rulning samt zoom på det pågældende element.

.no-scroll { touch-action: none; }

Hvis du anvender denne klasse på et body-element, vil det potentielt forhindre al rulning på siden. Dette kan være nyttigt i visse scenarier, men det er vigtigt at være opmærksom på begrænsningerne.

Begrænsninger ved touch-action: none

Selvom touch-action: none er en effektiv løsning, har den sine begrænsninger, især i komplekse layouts:

  • Underordnede Elementer med Egen Rulning: Hvis et underordnet element har sin egen definerede rulning (f.eks. overflow: scroll eller overflow: auto), kan touch-action: none på forældreelementet blive tilsidesat eller opføre sig uforudsigeligt.
  • Safari Kompatibilitet: Som nævnt i kildematerialet, har Safari historisk set haft visse udfordringer med fuld overholdelse af touch-action: none, især når det kombineres med andre CSS-egenskaber i underordnede elementer. Specifikt kan overflow-x: hidden i et barn annullere effekten.

Specifikke værdier for touch-action

Udover none understøtter touch-action også specifikke værdier, der giver finere kontrol:

  • auto: Standardværdien, tillader alle standard gestus.
  • none: Deaktiverer alle standard gestus.
  • pan-x: Tillader kun vandret panning.
  • pan-y: Tillader kun lodret panning.
  • pinch-zoom: Tillader kun pinch-to-zoom gestus.

Du kan også kombinere disse, f.eks. pan-x pinch-zoom for at tillade vandret rulning og zoom, men deaktivere lodret rulning.

JavaScript-baserede Løsninger: Event Listeners

Når CSS-løsninger ikke er tilstrækkelige, eller når der kræves mere dynamisk kontrol, kommer JavaScript til undsætning. Ved at lytte til og manipulere touch-events kan vi opnå præcis den adfærd, vi ønsker.

Forhindring af Grundlæggende Rulning

Den mest basale JavaScript-metode til at forhindre rulning er at aflytte touchmove-eventet og kalde event.preventDefault(). Dette forhindrer standardhandlingen, som i dette tilfælde er rulning.

document.addEventListener('touchmove', function (e) { e.preventDefault(); });

Advarsel: Som kildematerialet pointerer, kan det at anvende preventDefault() direkte på touchstart-eventet på document eller window deaktivere rulning på alle efterfølgende områder. Det er ofte bedre at være mere specifik.

Forhindring af Dokument-Rulning, men Tilladelse af Element-Rulning

Et almindeligt scenarie er at have en modal eller et sidepanel, der skal være scrollbart internt, men som ikke skal forårsage, at baggrunden ruller. Her er en mere sofistikeret tilgang:

Denne metode udnytter, at Safari bruger den første touch-bevægelse til at bestemme, om det er dokumentet eller et specifikt element, der skal rulles.

var firstMove = true; window.addEventListener('touchstart', function (e) { firstMove = true; }); window.addEventListener('touchmove', function (e) { if (firstMove) { e.preventDefault(); firstMove = false; } });

Denne kode forhindrer rulning, når den første berøring efterfulgt af en bevægelse sker. Dette er en simplificeret, men ofte effektiv metode.

En Mere Robust Løsning med Element-Inspektion

For en endnu mere robust løsning, der tager højde for forskellige scrollbare elementer i hierarkiet, kan man inspicere det berørte element og dets forældre for at bestemme, om dokumentet skal rulles.

How to disable horizontal scroll in CSS?
To disable horizontal scroll for an element (like a div), use the following CSS style: overflow-x:hidden;. The above script will prevent horizontal scrolling for the element with the given ID. For instance, use $ ("#yourElementID") instead of $ (document).
let touchTarget = null; let scrollMap = {}; let disableScroll = false; function conditionParentUntilTrue(element, condition) { let outcome; if (element === document.body) { return false; } outcome = condition(element); if (outcome) { return true; } else { return conditionParentUntilTrue(element.parentNode, condition); } } window.addEventListener('touchstart', function (e) { touchTarget = e.targetTouches[0].target; scrollMap.left = conditionParentUntilTrue(touchTarget, (el) => el.scrollLeft > 0); scrollMap.top = conditionParentUntilTrue(touchTarget, (el) => el.scrollTop > 0); scrollMap.right = conditionParentUntilTrue(touchTarget, (el) => el.scrollWidth > el.clientWidth && el.scrollWidth - el.clientWidth > el.scrollLeft); scrollMap.bottom = conditionParentUntilTrue(touchTarget, (el) => el.scrollHeight > el.clientHeight && el.scrollHeight - el.clientHeight > el.scrollTop); let touch = e.targetTouches[0]; let touchScreenX = touch.screenX; let touchScreenY = touch.screenY; disableScroll = false; // Check if the touch is on an element that should not scroll the body if (scrollMap.left || scrollMap.top || scrollMap.right || scrollMap.bottom) { // It's possible this element or its parent can scroll, let's assume no document scroll for now. } else { // This touch is likely intended for document scroll. } }); window.addEventListener('touchmove', function (e) { if (disableScroll) { e.preventDefault(); return; } let touch = e.targetTouches[0]; let moveScreenX = touch.screenX; let moveScreenY = touch.screenY; if ( (moveScreenX > touchScreenX && scrollMap.left) || (moveScreenY < touchScreenY && scrollMap.bottom) || (moveScreenX < touchScreenX && scrollMap.right) || (moveScreenY > touchScreenY && scrollMap.top) ) { // Scrolling an element or its parent, not the document. } else { // This movement is intended for the document body scroll. e.preventDefault(); disableScroll = true; } });

Denne mere komplekse løsning analyserer om elementet eller dets forældre kan scrolles i en given retning. Hvis det kan, tillades bevægelsen. Hvis ikke, og bevægelsen er i en retning, der normalt ville scrolles i dokumentet, så forhindres det.

Den Anbefalede JavaScript-tilgang: Containere med Scrollbar Børn

En meget praktisk løsning, som beskrevet i kildematerialet, involverer at håndtere interaktioner mellem en forældrecontainer og scrollbare børn.

Låsning af Forældre med Scrollbart Barn

Denne funktion tilføjer en klasse til forælderen, der skjuler overflow, og tilføjer event listeners for at stoppe hhv. wheel og touchmove events på forælderen, mens stopPropagation bruges på barnet for at tillade intern rulning.

const preventDefaultScroll = (e) => e.preventDefault(); const allowScrollWithoutPropogation = (e) => e.stopPropagation(); const lockParentWithScrollingChild = (parentSelector, childSelector) => { const parentElement = document.querySelector(parentSelector); const childElement = document.querySelector(childSelector); parentElement?.classList.add('locked-scroll'); parentElement?.addEventListener('wheel', preventDefaultScroll, { passive: false }); parentElement?.addEventListener('touchmove', preventDefaultScroll, { passive: false }); childElement?.addEventListener('wheel', allowScrollWithoutPropogation, false); childElement?.addEventListener('touchmove', allowScrollWithoutPropogation, false); }; // Eksempel på brug: // lockParentWithScrollingChild('#menu-container-header', '#menu-container');

Vigtigt om passive: false: Ved at sætte passive: false tillader vi, at preventDefault() kan kaldes inden for scroll-relaterede events. Uden dette ville man støde på fejlmeddelelsen "Unable to preventDefault inside passive event listener invocation.". Dette kan dog have en lille indvirkning på ydeevnen, så det bør bruges med omtanke.

Ophævelse af Låsning

Det er lige så vigtigt at kunne rydde op efter sig, når låsningen ikke længere er nødvendig. Dette inkluderer at fjerne klassen og de tilføjede event listeners.

const unlockParentWithScrollingChild = (parentSelector, childSelector) => { const parentElement = document.querySelector(parentSelector); const childElement = document.querySelector(childSelector); parentElement?.classList.remove('locked-scroll'); parentElement?.removeEventListener('wheel', preventDefaultScroll); parentElement?.removeEventListener('touchmove', preventDefaultScroll); childElement?.removeEventListener('wheel', allowScrollWithoutPropogation); childElement?.removeEventListener('touchmove', allowScrollWithoutPropogation); }; // Eksempel på brug: // unlockParentWithScrollingChild('#menu-container-header', '#menu-container');

Tabel: CSS vs. JavaScript Metoder

MetodeFordeleUlemperBedst til
CSS touch-action: noneSimpel, ingen JavaScript nødvendigBegrænsninger med underordnede elementer, potentiel Safari-inkonsistensSimpel deaktivering af rulning på et element
JavaScript preventDefault()touchmoveMere kontrol, kan anvendes dynamiskKan være for aggressiv, hvis ikke brugt korrekt (deaktiverer alt)Simpel deaktivering af rulning på hele siden
JavaScript med stopPropagation() på børnTillader intern rulning i specifikke elementer, robustKræver JavaScript, mere kompleks implementering, passive: false overvejelserModaler, sidepaneler, hvor kun specifikke områder skal være scrollbare

Konklusion

At styre rulning og zoom i Safari på mobile enheder kræver en forståelse af både CSS og JavaScript. Mens touch-action giver en elegant CSS-baseret løsning til enkle tilfælde, giver JavaScript mere granulær kontrol, især når man skal håndtere interaktionen mellem scrollbare forældre og børn. Den anbefalede JavaScript-tilgang med stopPropagation er ofte den mest effektive til at skabe en problemfri brugeroplevelse, hvor specifikke dele af UI'en kan rulles, mens resten af siden forbliver låst.

Husk altid at teste din implementering grundigt på forskellige enheder og iOS-versioner for at sikre den ønskede funktionalitet og undgå ubehagelige overraskelser for brugerne. En velovervejet tilgang til at håndtere touch-interaktioner er afgørende for et vellykket mobilt webdesign.

Ofte Stillede Spørgsmål (FAQ)

Hvordan forhindrer jeg zoom i Safari på iPhone?

Du kan forhindre zoom ved at bruge touch-action: manipulation eller touch-action: none i din CSS. manipulation tillader rulning, men deaktiverer zoom. For en mere specifik kontrol kan JavaScript bruges til at aflytte gesturestart og gesturechange events og kalde event.preventDefault().

Hvorfor virker min touch-action: none ikke i Safari?

Dette kan skyldes, at et underordnet element har sin egen overflow-egenskab sat, eller at der er andre CSS-regler, der konflikter. Prøv at forenkle dit CSS eller brug JavaScript-løsningen for mere pålidelighed.

Kan jeg kun forhindre lodret rulning?

Ja, du kan bruge touch-action: pan-x til kun at tillade vandret rulning og dermed forhindre lodret rulning. Omvendt kan touch-action: pan-y bruges til kun at tillade lodret rulning.

Hvis du vil læse andre artikler, der ligner Stop rulning i Safari: En komplet guide, kan du besøge kategorien Mobil.

Go up