disabilitare lo zoom viewport iOS 10+ safari?


164

Ho aggiornato il mio iPhone 6 plus alla versione beta di iOS 10 e ho appena scoperto che in Safari mobile, puoi ingrandire qualsiasi pagina web toccando due volte o pizzicando IGNORA il user-scalable=nocodice nel meta tag. Non so se si tratta di un bug o di una funzionalità. Se è considerata una funzionalità, come si disabilita lo zoom viewport iOS 10 safari?


aggiornato su iOS 11/12, iOS 11 e iOS 12 Safari NON rispettano ancora il user-scalable=nometa tag.

sito github mobile su Safari


2
Una funzione di accessibilità: Da notare in Safari su iOS 10 twitter.com/thomasfuchs/status/742531231007559680/photo/1
ErikE

87
No, non lo è. È una cattiva pratica per i normali contenuti Web. Per le app Web, il comportamento di zoom predefinito può rovinare completamente l'usabilità. Ad esempio, nessuno vuole ingrandire un pulsante del canale in alto perché lo hanno toccato due volte, né zoomare su una parte di un videogioco perché hanno toccato due volte il pulsante di salto. C'è una ragione per cui questa funzionalità è stata aggiunta in primo luogo e non ha senso interrompere l'usabilità per tutti solo perché alcuni "web designer" non sanno cosa stanno facendo. Vai a urlare ai progettisti del sito e smetti di rompere il browser.
dgatwood,

36
Dire che è "cattiva pratica" è un'opinione e non cambia il fatto che Apple insista nel prendere gli standard web che la comunità impiega mesi / anni / decenni a implementare multipiattaforma e prendersi una cazzata gigantesca. Perché Apple dovrebbe dettare che i web designer non sanno cosa stanno facendo? Discussione terribile.
Samrap

2
Personalmente, penso che questo derivi dal codice online del boilerplate in cui gli sviluppatori semplicemente copiano e incollano alla cieca senza sapere quale sia lo scopo del codice.
William Isted

7
La risposta è semplice, Apple: rendere la disabilitazione del meta tag un'impostazione di accessibilità predefinita. Coloro che ne hanno bisogno, lo avranno, senza punire quelli che non lo fanno.
Ruben Martinez Jr.,

Risposte:


94

È possibile impedire il ridimensionamento delle pagine Web in Safari su iOS 10, ma coinvolgerà più lavoro da parte tua. Immagino che l'argomento sia che un certo grado di difficoltà dovrebbe impedire agli sviluppatori di beni di culto di far cadere "user-scalable = no" in ogni tag viewport e rendere le cose inutilmente difficili per gli utenti ipovedenti.

Tuttavia, vorrei vedere Apple modificare la loro implementazione in modo che ci sia un modo semplice (meta-tag) per disabilitare il doppio tocco per ingrandire. La maggior parte delle difficoltà riguarda tale interazione.

Puoi interrompere il pizzico per ingrandire con qualcosa del genere:

document.addEventListener('touchmove', function (event) {
  if (event.scale !== 1) { event.preventDefault(); }
}, false);

Si noti che se eventuali target più profondi chiamano stopPropagation sull'evento, l'evento non raggiungerà il documento e il comportamento di ridimensionamento non sarà impedito da questo listener.

La disabilitazione del doppio tocco per ingrandire è simile. Disattivi qualsiasi tocco sul documento che si verifica entro 300 millisecondi dal tocco precedente:

var lastTouchEnd = 0;
document.addEventListener('touchend', function (event) {
  var now = (new Date()).getTime();
  if (now - lastTouchEnd <= 300) {
    event.preventDefault();
  }
  lastTouchEnd = now;
}, false);

Se non imposti correttamente gli elementi del modulo, la messa a fuoco su un input eseguirà lo zoom automatico e, dato che hai disabilitato principalmente lo zoom manuale, ora sarà quasi impossibile decomprimere. Assicurati che la dimensione del carattere di input sia> = 16px.

Se stai cercando di risolverlo in un WKWebView in un'app nativa, la soluzione sopra indicata è praticabile, ma questa è una soluzione migliore: https://stackoverflow.com/a/31943976/661418 . E come menzionato in altre risposte, in iOS 10 beta 6, Apple ha ora fornito una bandiera per onorare il meta tag.

Aggiornamento maggio 2017: ho sostituito il vecchio metodo "verifica lunghezza tocchi al tocco" per disabilitare lo zoom con pizzico con un approccio più semplice "verifica evento. Scala al tocco". Dovrebbe essere più affidabile per tutti.


3
Nota che l'hacking touchstart è incoerente ... e se riesci a evitarlo, sei bloccato in uno stato molto scomodo
Sam Saffron,

5
Per esempio. app di mappatura a schermo intero, c'è una funzione di zoom hardcoded nell'applicazione di mappatura (Google Maps JS, Leaflet ecc.). Google consiglia di aggiungere un meta tag <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />e se il browser non rispetta il meta tag, è un pessimo design del browser. L'altro, come un design molto brutto, è l'azione avanti / indietro che scorre, cosa che non può essere impedita in iOS 9/10. Si interrompe gravemente trascinando le azioni all'interno dell'applicazione web.
Timo Kähkönen,

4
Se l'utente inizia a trascinare con un dito, metti un secondo dito sullo schermo sarà in grado di pizzicare-zoom. Puoi disabilitare sia lo zoom che lo scorrimento con un preventDefaulton touchmove. Non è possibile (completamente) disabilitare lo zoom senza disabilitare lo scorrimento.
Paolo,

10
Wow, questa parte (incollerò qui) mi è stata di grande aiuto. Non l'ho mai visto menzionato da nessun'altra parte su Internet. Mi ci sono volute ore per risolvere questo problema. Sono davvero deluso dalle scelte di progettazione UX di Apple in merito, in cui i moduli eseguono lo zoom automatico, ma non si riducono.If you don't set up your form elements right, focusing on an input will auto-zoom, and since you have mostly disabled manual zoom, it will now be almost impossible to unzoom. Make sure the input font size is >= 16px.
Ryan

6
Sembra che questo non funzioni più in iOS 12. Qualche idea su come farlo funzionare per iOS 12?
TJR

78

Questa è una nuova funzionalità di iOS 10.

Dalle note di rilascio di iOS 10 beta 1:

  • Per migliorare l'accessibilità sui siti Web in Safari, gli utenti possono ora pizzicare per ingrandire anche quando un sito Web viene impostato user-scalable=nonella finestra.

Mi aspetto che vedremo presto un componente aggiuntivo JS per disabilitarlo in qualche modo.


4
@Onza: non credo sia male. Credo che vada bene. La disabilitazione del pizzico / zoom (comportamento predefinito dell'utente) è considerata negativa e molti siti Web mobili lo fanno. L'unico caso utente accettabile sarebbe una vera app Web che assomigli e sembri un'app.
wouterds

6
Cattivo .. cambio viewport usando js e blocco lo zoom solo quando alcuni elementi sono selezionati sul sito web ora è rotto a causa di questa "decisione". Se qualcuno decide di bloccarlo, c'è un motivo.
Zhenya,

9
@Karlth è molto comodo per uno sviluppatore di giochi
Sandeep,

14
Ho IOS 10.0.2, scalabile dall'utente = no non disabilita più lo zoom sul nostro sito Web ... Il nostro problema principale con lo zoom è con il nostro menu laterale fisso .. Rompe solo il layout .. Qualche idea o soluzione su questo? Capisco che lo zoom è buono per l'accessibilità, abbiamo reso disponibile lo zoom su parti specifiche del nostro sito usando js events (hammer) e css .. Non vedo perché una regola debba essere imposta a tutti, sembra che la polizia del PC stia iniziando a conquistare anche il nostro mondo di sviluppo ?!
webkit,

50
"L'unico caso utente accettabile sarebbe una vera app Web che assomigli e sembri un'app". - e questo è, come hai detto tu, un caso d'uso reale e accettabile, che non è così raro ..
Florrie,

21

Sono stato in grado di risolvere questo problema utilizzando la touch-actionproprietà CSS sui singoli elementi. Prova a impostare gli touch-action: manipulation;elementi su cui si fa comunemente clic, come collegamenti o pulsanti.


1
la "manipolazione" non impedisce lo zoom con pizzico, solo lo zoom con doppio tocco.
Moos,

4
Questa dovrebbe essere la risposta accettata. puoi usare tu stesso touch-action: none;per controllare tutti i gesti.
Guy Sopher,

4
questo è fantastico - disabilitare lo zoom con doppio tocco mentre si lascia lo zoom con pizzico, che DOVREBBE essere considerato un gesto - il doppio tocco non dovrebbe. 1 cane è un cane. 1 cane + 1 cane non effettua una navetta spaziale. Produce 2 cani e fanno cose che ti aspetteresti che facciano 2 cani. Non mi sarei mai aspettato che 2 cani fossero una navetta spaziale. Mai.
Larry,

5
@GuySopher iOS non fornisce touch-action: nonesolo manipulatoin, il che lascia il problema del pizzico-zoom così com'è.
umanità e

14

Sembra che questo comportamento sia apparentemente cambiato nell'ultima beta, che al momento della stesura è beta 6.

Dalle note di rilascio per iOS 10 Beta 6:

WKWebViewora il valore predefinito è rispettato user-scalable=noda una finestra. I clienti di WKWebViewpossono migliorare l'accessibilità e consentire agli utenti di pizzicare per ingrandire su tutte le pagine impostando la WKWebViewConfiguration proprietà ignoresViewportScaleLimitssu YES.

Tuttavia, nei miei test (molto limitati), non posso ancora confermare che sia così.

Modifica: verificato, iOS 10 Beta 6 rispetta user-scalable=nodi default per me.


11
10.0.1 qui. Non lo rispetta. Che cosa succede con Apple che si sbarazza delle funzionalità di cui tutti hanno bisogno ...
lifwanian,

1
Questo si riferisce a WKWebView non Safari. Fonte: Uno dei nostri mappa applicazioni si è rotto e non abbiamo alcuna idea di come risolvere il problema.
Fabio Poloni

Aha! Mi scuso, sono venuto qui durante la ricerca di una soluzione per lo stesso bug / funzione WKWebViewe ho ipotizzato che la domanda originale fosse fatta WKWebViewquando scrivevo la mia risposta. Quindi suppongo che durante una delle prime versioni beta, Apple abbia cambiato il comportamento sia di WKWebViewSafari mobile che mobile, quindi in beta 6 hanno ripristinato il comportamento WKWebViewma lo hanno mantenuto per Safari mobile.
Cellane

1
10.0.2 non rispetta user-scalable=no. Non sono sicuro del motivo per cui avrebbero mai annullato questo, solo per riportarlo indietro, solo per rimuoverlo di nuovo.
Aidan Hakimian,

13

La soluzione che le opere in Safari Mobile in questo momento della scrittura, è quello di avere il terzo argomento in addEventListenerBE { passive: false }, quindi gli sguardi di soluzione completa come questo:

document.addEventListener('touchmove', function (event) {
  if (event.scale !== 1) { event.preventDefault(); }
}, { passive: false });

Potresti voler controllare se le opzioni sono supportate per rimanere retrocompatibili.


3
Qualcuno ha provato questo su iOS 12? Ho aggiunto il codice sopra e non sta facendo nulla per la mia webapp. Ancora in grado di ingrandire questo stupido Safari. I miei meta tag viewport aspetto come questo: btw <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">.
Patrick DaVader,

2
@PatrickDaVader Sì, non riesco a trovare alcuna soluzione funzionante per iOS 12 Safari. Mal di mare da tutti gli incessanti zoom.
Jamie Birch,

1
Questo funziona in iOS 13. I miei tag <meta> includono: <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, viewport-fit=cover, user-scalable=no, shrink-to-fit=no" />e<meta name="HandheldFriendly" content="true">
Sterling Bourne,

1
@SterlingBourne Copia la tua configurazione. Funziona, ma solo il 90% delle volte. Non sono sicuro del perché non sempre.
Hillcow,

1
La risposta di @SterlingBourne ha funzionato per me! Grazie. Dovrebbe pubblicarlo come una risposta piuttosto che come un commento in modo che possa essere votato <meta name = "viewport" content = "larghezza = larghezza dispositivo, scala iniziale = 1, scala massima = 1, viewport-fit = copertina, user-scalable = no, shrink-to-fit = no "/> e <meta name =" HandheldFriendly "content =" true ">
Gene Black

8

Ho trascorso circa un'ora a cercare un'opzione javascript più solida e non ne ho trovata una. Accade così che nei giorni scorsi ho armeggiato con hammer.js (Hammer.js è una libreria che ti permette di manipolare facilmente tutti i tipi di eventi tattili) e per lo più non riesco a quello che stavo cercando di fare.

Con questo avvertimento e la comprensione che non sono affatto un esperto di javascript, questa è una soluzione che mi è venuta in mente che sfrutta fondamentalmente hammer.js per catturare gli eventi pinch-zoom e doppio tocco e quindi registrarli e scartarli.

Assicurati di includere hammer.js nella tua pagina e quindi prova ad attaccare questo javascript nella testa da qualche parte:

< script type = "text/javascript" src="http://hammerjs.github.io/dist/hammer.min.js"> < /script >
< script type = "text/javascript" >

  // SPORK - block pinch-zoom to force use of tooltip zoom
  $(document).ready(function() {

    // the element you want to attach to, probably a wrapper for the page
    var myElement = document.getElementById('yourwrapperelement');
    // create a new hammer object, setting "touchAction" ensures the user can still scroll/pan
    var hammertime = new Hammer(myElement, {
      prevent_default: false,
      touchAction: "pan"
    });

    // pinch is not enabled by default in hammer
    hammertime.get('pinch').set({
      enable: true
    });

    // name the events you want to capture, then call some function if you want and most importantly, add the preventDefault to block the normal pinch action
    hammertime.on('pinch pinchend pinchstart doubletap', function(e) {
      console.log('captured event:', e.type);
      e.preventDefault();
    })
  });
</script>


Ho anche provato a risolvere questo problema lavorando con hammer.js e posso confermare che potrei impedire lo zoom del viewport aggiungendo .preventDefaulta tutti i gestori di gesti hammer. Sto usando Swipe / Pinch / Pan / Tap insieme, l'ho aggiunto a tutti i gestori, non so se ce n'è uno specifico che sta facendo il lavoro.
Conan,

6

Ho provato la risposta precedente sul pinch-to-zoom

document.documentElement.addEventListener('touchstart', function (event) {
    if (event.touches.length > 1) {
        event.preventDefault();
    }
}, false);

tuttavia a volte lo schermo continua a zoomare quando event.touches.length> 1 ho scoperto che il modo migliore è utilizzare l'evento touchmove, per evitare che un dito si muova sullo schermo. Il codice sarà qualcosa del genere:

document.documentElement.addEventListener('touchmove', function (event) {
    event.preventDefault();      
}, false);

Spero che possa essere d'aiuto.


7
Funziona solo se la tua app è perfetta ... se hai contenuti scorrevoli, non funziona ... comunque un bel trucco per alcuni scenari.
eljamz,

8
Questo disabilita anche lo scorrimento sul sito Web. BAD
Gags,

@eljamz grazie per farmi sapere e sì..la mia app si adatta perfettamente allo schermo.
Chihying Wu,

@Gags Non ho ancora testato la funzione di scorrimento, grazie per farmelo sapere.
Chihying Wu,

6

Verificare il fattore di scala nell'evento touchove quindi prevenire l'evento touch.

document.addEventListener('touchmove', function(event) {
    event = event.originalEvent || event;
    if(event.scale > 1) {
        event.preventDefault();
    }
}, false);

2
iOS 13 cambia falso in {passivo: falso}
wayofthefuture il

6

Possiamo ottenere tutto ciò che vogliamo iniettando una regola di stile e intercettando gli eventi di zoom:

$(function () {
  if (!(/iPad|iPhone|iPod/.test(navigator.userAgent))) return
  $(document.head).append(
    '<style>*{cursor:pointer;-webkit-tap-highlight-color:rgba(0,0,0,0)}</style>'
  )
  $(window).on('gesturestart touchmove', function (evt) {
    if (evt.originalEvent.scale !== 1) {
      evt.originalEvent.preventDefault()
      document.body.style.transform = 'scale(1)'
    }
  })
})

✔ Disabilita lo zoom con pizzico.

✔ Disabilita lo zoom con doppio tocco.

✔ Lo scorrimento non è interessato.

✔ Disabilita l'evidenziazione del tocco (che viene attivato, su iOS, dalla regola di stile).

AVVISO: modificare il rilevamento di iOS a proprio piacimento. Maggiori informazioni qui .


Ci scusiamo con lukejackson e Piotr Kowalski , le cui risposte compaiono in forma modificata nel codice sopra.


Funziona sul mio emulatore iPad che esegue iOS 11.2. Sul mio vero iPad con iOS 11.3 non funziona. Ho aggiunto un console.log per assicurarmi che gli eventi vengano generati e quindi vengano visualizzati nella console. Ha a che fare con iOS 11.3? O con dispositivi reali?
Mathieu R.,

1
@MathieuR. È un problema di iOS 11.3. Può essere corretto utilizzando una delle addEventListenerrisposte basate e passando { passive: false }come optionsparametro anziché false. Tuttavia, per la compatibilità con le versioni precedenti è necessario passare a falsemeno che il passivecampo opzione non sia supportato. Vedi developer.mozilla.org/en-US/docs/Web/API/EventTarget/…
Josh Gallagher,

@JoshGallagher Potresti fornire un esempio funzionante? Su iOS11 nessuna delle risposte funziona per me.
Mick,

Il 'gesturestart' -> preventDefault funziona per me al momento della scrittura su iOS 12,2
Michael Camden,

5

Ho trovato una soluzione abbastanza ingenua, ma sembra funzionare. Il mio obiettivo era impedire che i doppi tocchi accidentali venissero interpretati come zoom in, mantenendo il pizzico per lo zoom funzionante per l'accessibilità.

L'idea è di misurare il tempo tra il primo touchstarte il secondo touchendcon un doppio tocco e quindi di interpretare l'ultimo touchendcome clic se il ritardo è troppo piccolo. Pur impedendo lo zoom accidentale, questo metodo sembra mantenere invariato lo scorrimento dell'elenco, il che è carino. Non sono sicuro di non aver perso nulla però.

let preLastTouchStartAt = 0;
let lastTouchStartAt = 0;
const delay = 500;

document.addEventListener('touchstart', () => {
  preLastTouchStartAt = lastTouchStartAt;
  lastTouchStartAt = +new Date();
});
document.addEventListener('touchend', (event) => {
  const touchEndAt = +new Date();
  if (touchEndAt - preLastTouchStartAt < delay) {
    event.preventDefault();
    event.target.click();
  }
});

Ispirato da una sintesi di mutewinter e dalla risposta di Joseph .


5

Nel mio caso particolare, sto usando Babylon.js per creare una scena 3D e tutta la mia pagina è composta da una tela a schermo intero. Il motore 3D ha la sua funzionalità di zoom, ma su iOS il pizzico-zoom interferisce con quello. Ho aggiornato la risposta @Joseph per superare il mio problema. Per disabilitarlo, ho capito che devo passare {passive: false} come opzione al listener di eventi. Il seguente codice funziona per me:

window.addEventListener(
    "touchmove",
    function(event) {
        if (event.scale !== 1) {
            event.preventDefault();
        }
    },
    { passive: false }
);

Il mio caso d'uso è anche una scena 3d a pagina intera con controlli pinch personalizzati. Sarei stato affondato se non ci fosse una soluzione alternativa ad Apple ignorando esplicitamente la scala utente: nessun meta.
Nick Bilyk,

1

Per quanto strano possa sembrare, almeno per Safari in iOS 10.2, il doppio tocco per ingrandire è magicamente disabilitato se il tuo elemento o uno dei suoi antenati ha uno dei seguenti:

  1. Un ascoltatore onClick - può essere un semplice noop.
  2. Un cursor: pointerset in CSS

che ne dici di pizzicare?
Sam Su

Sfortunatamente, pizzicare per ingrandire non è coperto da questa soluzione. Per questo, abbiamo usato la soluzione proposta in: stackoverflow.com/a/39594334/374196
mariomc

Non funziona per me. Sto usando 10.2.1 Beta 4 su un iPod Touch usando questa pagina di test e toccando due volte uno dei quadratini grigi ingrandisci: jsbin.com/kamuta/quiet
robocat

1
Ho questo in un intervallo in un'app di reazione e non funziona.
FMD,

1

Lo zoom involontario tende a verificarsi quando:

  • Un utente tocca due volte un componente dell'interfaccia
  • Un utente interagisce con il viewport utilizzando due o più cifre (pizzico)

Per evitare il comportamento del doppio tocco ho trovato due soluzioni molto semplici:

<button onclick='event.preventDefault()'>Prevent Default</button>
<button style='touch-action: manipulation'>Touch Action Manipulation</button>

Entrambi impediscono a Safari (iOS 10.3.2) di ingrandire il pulsante. Come puoi vedere, uno è solo JavaScript, l'altro è solo CSS. Utilizzare in modo appropriato.

Ecco una demo: https://codepen.io/lukejacksonn/pen/QMELXQ

Non ho ancora tentato di prevenire il comportamento del pizzico, principalmente perché tendo a non creare interfacce multi touch per il web e in secondo luogo mi sono reso conto che forse tutte le interfacce, inclusa l'interfaccia utente dell'app nativa, dovrebbero essere "pizzica per ingrandire" -able in luoghi. Mi piacerebbe ancora di progettazione per evitare che l'utente dover fare questo per rendere l'interfaccia utente accessibile a loro, a tutti i costi.


1

Ho trovato questa semplice soluzione che sembra impedire il doppio clic per ingrandire:

    // Convert touchend events to click events to work around an IOS 10 feature which prevents
    // developers from using disabling double click touch zoom (which we don't want).
    document.addEventListener('touchend', function (event) {
        event.preventDefault();
        $(event.target).trigger('click');
    }, false);

1

Come richiesto, ho trasferito il mio commento a una risposta in modo che le persone possano votarlo:

Funziona il 90% delle volte per iOS 13:

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, viewport-fit=cover, user-scalable=no, shrink-to-fit=no" />

e

<meta name="HandheldFriendly" content="true">


0

Ho verificato tutte le risposte sopra in pratica con la mia pagina su iOS (iPhone 6, iOS 10.0.2), ma senza successo. Questa è la mia soluzione di lavoro:

$(window).bind('gesturestart touchmove', function(event) {
    event = event.originalEvent || event;
    if (event.scale !== 1) {
         event.preventDefault();
         document.body.style.transform = 'scale(1)'
    }
});

Sfortunatamente questo funziona solo quando la tua pagina si adatta perfettamente, non quando hai contenuti scorrevoli
Scarpa

Hmm. Funziona bene con contenuti scorrevoli, nella mia esperienza (iOS 10.3).
jeff_mcmahan,

0

questo ha funzionato per me:

document.documentElement.addEventListener('touchmove', function (event) {
    event.preventDefault();
}, false);

Ho provato questo, ha impedito lo zoom con pizzico, tuttavia disabilita lo scorrimento touch del viewport in modo da non poter più scorrere la pagina su e giù.
TGR
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.