Désactiver le zoom automatique dans la balise «Texte» de saisie - Safari sur iPhone


541

J'ai créé une page HTML avec une <input>balise type="text". Lorsque je clique dessus en utilisant Safari sur iPhone, la page s'agrandit (zoom automatique). Quelqu'un sait-il comment désactiver cela?


8
Pour tous les utilisateurs de Twitter Bootstrap qui atterrissent ici: voir aussi ce problème Github .
Jeroen

7
Je pense que la réponse @daxmacrog répond exactement à ce que vous voulez, êtes-vous prêt à l'accepter pour qu'il puisse atteindre le sommet et économiser beaucoup de retouches aux personnes qui lisent tout cela? Réponse 2018: stackoverflow.com/a/46254706/172651
Evolve

@Évoluez la réponse dont vous avez parlé brise la fonctionnalité de pincement et de zoom Android. la réponse de daxmacrog est imparfaite.
MH

5
Je le jure, Apple crée ces anti-fonctionnalités juste pour jouer avec nos têtes.
Andrew Koster

@AndrewKoster, je suis encore d'accord avec vous en 2020.
Ashok

Réponses:


492

Le navigateur zoomera si la taille de police est inférieure à 16pxet la taille de police par défaut pour les éléments de formulaire est 11px(au moins dans Chrome et Safari).

De plus, l' selectélément doit avoir la focuspseudo-classe attachée.

input[type="color"],
input[type="date"],
input[type="datetime"],
input[type="datetime-local"],
input[type="email"],
input[type="month"],
input[type="number"],
input[type="password"],
input[type="search"],
input[type="tel"],
input[type="text"],
input[type="time"],
input[type="url"],
input[type="week"],
select:focus,
textarea {
  font-size: 16px;
}

Il est pas nécessaire d'utiliser tout ce qui précède, vous pouvez simplement le style des éléments dont vous avez besoin, par exemple: il suffit text, numberet textarea:

input[type='text'],
input[type='number'],
textarea {
  font-size: 16px;
}

Solution alternative pour que les éléments d'entrée héritent d'un style parent:

body {
  font-size: 16px;
}
input[type="text"] {
  font-size: inherit;
}

81
Juste pour tout couvrir: select, textarea, input[type="text"], input[type="password"], input[type="datetime"], input[type="datetime-local"], input[type="date"], input[type="month"], input[type="time"], input[type="week"], input[type="number"], input[type="email"], input[type="url"], input[type="search"], input[type="tel"], input[type="color"] { font-size: 16px; }
Nic Barbier

8
@Nic Vous devez utiliser select:focus. Avait aussi le même problème.
DGibbs

141
Je ne comprends pas, comment est-ce un correctif? Et si je veux une taille de police plus petite / plus grande?
bryan

47
la bonne façon est de changer la balise META en: <meta name = "viewport" content = "width = device-width, initial-scale = 1, maximum-scale = 1, user-scalable = 0" />
Milos Matic

37
@MilosMatic Dans la plupart des cas, ce n'est probablement pas une bonne solution, car cela empêche complètement l'utilisateur de redimensionner la page. Potentiellement encore plus ennuyeux pour vos visiteurs.
BadHorsie

363

Vous pouvez empêcher Safari de zoomer automatiquement sur les champs de texte lors de la saisie par l'utilisateur sans désactiver la possibilité pour l'utilisateur de pincer le zoom. Ajoutez simplement maximum-scale=1mais omettez l'attribut à l'échelle de l'utilisateur suggéré dans d'autres réponses.

C'est une option intéressante si vous avez un formulaire dans une couche qui "flotte" autour si vous zoomez, ce qui peut entraîner le déplacement d'éléments importants de l'interface utilisateur hors de l'écran.

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">


66
Ceci est la solution 2018+. Votez comme si votre vie en dépendait.
Henrik Petterson

17
Cela cassera la capacité de zoom des appareils Android
fen1ksss

4
@daxmacrog, vous avez raison, mais l'OP n'a pas mentionné s'il voulait briser les androïdes en autorisant le comportement nécessaire. C'est là que personnellement j'ai pris une option incorrecte. Bien sûr, il vaut mieux préciser.
fen1ksss

13
@HenrikPetterson Cela fait plus que simplement désactiver le zoom automatique comme spécifié par OP, il désactive également le zoom par pincement. Je ne pense donc pas que ce soit la solution 2018+.
André Werlang

4
@ AndréWerlang Ce n'est pas exact. Comme indiqué clairement dans la réponse, cette solution ne désactive pas le zoom par pincement dans Safari (ou Firefox), ce que l'OP a demandé. Mais comme indiqué dans les commentaires précédents, il désactive le zoom utilisateur sur les appareils Android et dans Chrome sur iOS.
daxmacrog

223
@media screen and (-webkit-min-device-pixel-ratio:0) { 
  select:focus,
  textarea:focus,
  input:focus {
    font-size: 16px;
    background: #eee;
  }
}

Nouveau: IOS zoomera toujours, sauf si vous utilisez 16px sur l'entrée sans la mise au point.

@media screen and (-webkit-min-device-pixel-ratio:0) { 
  select,
  textarea,
  input {
    font-size: 16px;
  }
}

J'ai ajouté un arrière-plan car IOS n'ajoute aucun arrière-plan à la sélection.


9
Cela fonctionne non seulement pour safari sur iOS (iphone / ipad / ipod), mais aussi Safari / OSX et Chrome (windows et Mac). Donc, si vous essayez de cibler spécifiquement l'iphone, cela ne fonctionnera pas.
Redtopia

31
Pourquoi tout le monde dit 16px mais personne ne se soucie de mentionner pourquoi c'est exactement 16px? Pourquoi un tel nombre arbitraire? Pourquoi devons-nous définir la taille du texte de notre champ de formulaire à 16 pixels et non ... par exemple 1,8rem ou 2,5em ou autre? Est-ce juste un bug stupide d'un système d'exploitation propriétaire?
Beebee

14
La taille de la police @Beebee 100% est de 16 pixels, celle par défaut pour la plupart sinon tous les navigateurs (bureau également). IOS l'utilise par défaut probablement parce que c'est une taille confortable pour la lecture. Pourquoi c'est réglé de cette façon, je n'ai pas pris la peine de lever les yeux, je m'en fous.
Christina

5
Utilisez @media screen and (-webkit-min-device-pixel-ratio:0) and (max-device-width:1024px)pour limiter l'effet à l'iPhone, mais ne modifiez pas les sites Web lorsqu'ils sont affichés dans Chrome.
BurninLeo

9
Au lieu d'utiliser une requête multimédia, vous devez utiliser @supports (-webkit-overflow-scrolling: touch), car cette fonctionnalité CSS n'existe que sur iOS
James Moran

189

Si votre site Web est correctement conçu pour un appareil mobile, vous pouvez décider de ne pas autoriser la mise à l'échelle.

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />

Cela résout le problème autour duquel votre page ou formulaire mobile va «flotter».


123
Techniquement correct, mais je ne suis pas d'accord avec le raisonnement. La désactivation des zooms des utilisateurs sur un site correctement conçu est généralement toujours une mauvaise idée.
Fer

20
"Bien conçu" est très subjectif. Considérez un en-tête fixe de 50 pixels en haut d'un site qui est entièrement réactif et devrait fonctionner dans tous les navigateurs. Le zoom dans iOS Safari brise le positionnement de l'en-tête et brise à peu près tout le site.
Redtopia

62
La désactivation de la fonction de zoom utilisateur est une pratique terrible du point de vue UX et devrait vraiment être évitée à tout prix. Pouvoir zoomer librement est une fonctionnalité d'accessibilité de base et un contrôle que vous ne devez jamais retirer à l'utilisateur.
Gabriel Luethje

72
Dans les applications mobiles natives, vous n'avez jamais la possibilité de zoomer et elles fonctionnent très bien, pourquoi une application Web serait-elle différente? Si vous définissez la taille de police et la hauteur de ligne appropriées avec des contrastes clairs, vous devriez être d'accord.
jotav

39
Ceux qui utilisent l'argument `` tout va bien dans les applications natives '' ignorent le fait que les applications natives bien conçues respectent les paramètres d'accessibilité au niveau du système d'exploitation tels que la taille du texte. Les utilisateurs plus âgés et malvoyants peuvent utiliser et utilisent des tailles de police extrêmement larges à l'échelle du système d'exploitation, car ils en ont besoin . Souvent, les applications Web n'adhèrent pas ou ne peuvent pas respecter ce paramètre, il est donc essentiel d'autoriser la fonctionnalité d'accessibilité intégrée du navigateur Web, comme le zoom. Quoi que vous pensiez être parfaitement lisible, croyez-moi, il y a des gens qui ne le trouveront pas assez clair. Ne retirez pas cette option aux utilisateurs si vous appréciez la convivialité.
Ryan Williams

72

En résumé, la réponse est: définissez la taille de la police des éléments du formulaire sur au moins 16 pixels


Oui, c'est certainement la meilleure pratique pour éviter de zoomer sur les appareils mobiles. Pas de js, pas de hacks, pas de solutions de contournement du tout. Mais même avec 16px j'ai remarqué un très petit zoom dans mes pages donc j'ai essayé 17px, 18px ... pour voir ce qui se passe.
ed1nh0

8
Il est recommandé de déclarer 100% sur le corps, le bouton, l'entrée, la zone de texte et les éléments de sélection. Cela permet à l'utilisateur de définir une valeur par défaut qui n'est pas la 16 pixels livrée avec les navigateurs. Une personne qui a du mal à lire à l'écran peut définir sa valeur par défaut à 18 pixels ou 20 pixels. Vous ne voulez pas outrepasser leur choix en leur imposant 16px. En ce qui concerne iOS, cependant, ils ont décidé d'augmenter l'échelle de toute valeur que leur HIG juge trop petite. Malheureusement, il semble qu'il n'interprète pas la valeur de 100%, nous sommes donc bloqués en ajoutant la valeur par défaut pour l'apaiser.
J.Hogue

RE iOS Safari, à partir de ce commentaire, il semble que Safari interprète correctement la font-size: 100%valeur et saisit les 16 pixels nécessaires.
Nathan Lafferty

36
input[type='text'],textarea {font-size:1em;}

3
Notez que le réglage de l'échelle de l'utilisateur sur non désactivera tout zoom, ce qui est probablement une mauvaise idée.
Stormsweeper

18
Cela ne fonctionne que si la taille de police de votre corps est la valeur par défaut (non spécifié, ou 1em, ou 100%). Si vous définissez une taille de police personnalisée, vous pouvez définir le font-sizedans votre extrait de code 16pxpour éviter le zoom automatique.
Alan H.

Je sais que cette question s'adressait à l'iPhone, mais c'est plus compatible entre les plates-formes et dans l'avenir de plus de plates-formes / appareils, j'ai essayé l'approche 16px mais sur une tablette Android, cela n'a fait que réduire l'effet de zoom automatique. La définition de '1em' comme spécifié dans le message a résolu le problème.
toddles_fp

3
Ni l'un 1emni l' autre 1remn'est une solution appropriée car les deux peuvent être inférieurs à 16pxet Safari nécessite au moins 16pxde ne pas zoomer.
Finesse

2
j'ai utilisé la solution de fenêtre d'affichage mais cela n'a pas fonctionné, la solution 16px fonctionne très bien, mais 16px est trop grande pour la boîte d'entrée de mon site, y a-t-il une troisième solution
Suneth Kalhara

21

Le moyen approprié de résoudre ce problème consiste à remplacer la fenêtre d'affichage des métadonnées par:

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/>


32
Ce n'est pas nécessairement la manière "appropriée" d'empêcher ce comportement. Mobile Safari effectue un zoom avant si le texte est jugé trop petit pour être lu. Désactiver le zoom tous ensemble est difficile et empêche les utilisateurs d'être en mesure d'interagir avec votre page d'une manière à laquelle ils peuvent s'attendre.
AlecRust

3
Apparemment, dans iOS10, Apple a modifié la propriété d'échelle maximale pour qu'elle ne soit plus respectée, permettant à tous les sites de zoomer quel que soit son paramètre.
Wolfr

3
Cela fonctionne pour la version iOS10 20 / septembre / 2016 ... fonctionne au moins sur mon application ... Merci !!! Avant d'utiliser <meta name = "viewport" content = "width = device-width, initial-scale = 1, minimum-scale = 1 , maximum-scale = 1"> Mais je l'ai basculé sur la ligne de la réponse et cela a fonctionné ...
eljamz

1
"Assurez-vous que le zoom de pincement du navigateur n'est pas bloqué par le méta-élément de la fenêtre d'affichage de la page afin qu'il puisse être utilisé pour zoomer sur la page à 200%. Les valeurs restrictives pour les attributs évolutifs et à l'échelle maximale de ce méta-élément doivent être évitées." w3.org/TR/mobile-accessibility-mapping/#zoom-magnification
danielnixon

J'ai vu des commentaires sur le fait que certaines de ces balises META ne fonctionnent pas sur iOS 10 et je sais que ce qui précède fonctionne sur Chrome pour iOS au moins. :) Merci!
cbloss793

16

Il n'y a aucun moyen propre que je pourrais trouver, mais voici un hack ...

1) J'ai remarqué que l'événement survol survient avant le zoom, mais le zoom se produit avant les événements de mousedown ou focus.

2) Vous pouvez modifier dynamiquement la balise de la fenêtre META en utilisant javascript (voir Activer / désactiver le zoom sur Safari iPhone avec Javascript? )

Donc, essayez ceci (indiqué dans jquery pour la compacité):

$("input[type=text], textarea").mouseover(zoomDisable).mousedown(zoomEnable);
function zoomDisable(){
  $('head meta[name=viewport]').remove();
  $('head').prepend('<meta name="viewport" content="user-scalable=0" />');
}
function zoomEnable(){
  $('head meta[name=viewport]').remove();
  $('head').prepend('<meta name="viewport" content="user-scalable=1" />');
}

C'est certainement un hack ... il peut y avoir des situations où le survol / le bas n'attrape pas toujours les entrées / sorties, mais cela a bien fonctionné dans mes tests et c'est un bon début.


5
Je ne sais pas quand le comportement de Safari a peut-être changé, mais maintenant (iOS6.0.1) le mousedown se produit avant le zoom automatique. Ainsi, dans ma solution précédente, le zoom est réactivé trop tôt. Je n'ai pas trouvé de correctif adéquat, car tous les événements que j'ai essayés se produisent maintenant avant le zoom. Vous pouvez réactiver le zoom sur une touche enfoncée ou un flou, mais il existe certains scénarios qui peuvent manquer (comme si l'utilisateur souhaite zoomer manuellement avant de commencer à taper quoi que ce soit).
dlo

15

Ajouter une échelle utilisateur = 0 pour afficher la méta comme suit

<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">

A travaillé pour moi :)


11
"Assurez-vous que le zoom de pincement du navigateur n'est pas bloqué par le méta-élément de la fenêtre d'affichage de la page afin qu'il puisse être utilisé pour zoomer sur la page à 200%. Les valeurs restrictives pour les attributs évolutifs et à l'échelle maximale de ce méta-élément doivent être évitées." w3.org/TR/mobile-accessibility-mapping/#zoom-magnification
danielnixon

9
Cela casse les règles d'accessibilité définies par W3.
Joshua Russell

travaillé pour moi, c'est aussi la meilleure solution pour moi car je veux la liberté de changer les tailles de police d'entrée en dessous de 16px et je ne veux pas un hack JS
Blue Bot

14

J'ai récemment (aujourd'hui: D) dû intégrer ce comportement. Afin de ne pas impacter les champs de conception d'origine, y compris le combo, j'ai choisi d'appliquer la transformation au centre du champ:

input[type="text"]:focus, input[type="password"]:focus,
textarea:focus, select:focus {
  font-size: 16px;
}

Pour info, cela a bien fonctionné sur mon iphone 5 avec iOS 6, mais sur un iphone 4 avec iOS 5 en mode portrait, le style de mise au point a été appliqué après le zoom. Peut-être que quelque chose de subtil se passait, je n'ai pas enquêté davantage.
Vish

Je veux juste dire que j'ai beaucoup de requêtes différentes en utilisant le zoom pour accélérer le développement et en fonction de combien vous zoomez déterminera la taille de police dont vous avez besoin je crois
mike

: le focus n'a pas fonctionné pour moi iOS 10.2 iPhone 6, mais la saisie [type = "text"]: le survol a bien fonctionné.
Amirhossein Rzd

13

Comme de nombreuses autres réponses l'ont déjà souligné, cela peut être obtenu en ajoutant maximum-scaleà la viewportbalise META. Cependant, cela a pour conséquence négative de désactiver le zoom utilisateur sur les appareils Android . ( Il ne désactive pas le zoom utilisateur sur les appareils iOS depuis la v10 .)

Nous pouvons utiliser JavaScript pour ajouter dynamiquement maximum-scaleà la méta viewportlorsque l'appareil est iOS. Cela permet d'obtenir le meilleur des deux mondes: nous permettons à l'utilisateur de zoomer et d' empêcher iOS de zoomer sur les champs de texte sur le focus.

| maximum-scale             | iOS: can zoom | iOS: no text field zoom | Android: can zoom |
| ------------------------- | ------------- | ----------------------- | ----------------- |
| yes                       | yes           | yes                     | no                |
| no                        | yes           | no                      | yes               |
| yes on iOS, no on Android | yes           | yes                     | yes               |

Code:

const addMaximumScaleToMetaViewport = () => {
  const el = document.querySelector('meta[name=viewport]');

  if (el !== null) {
    let content = el.getAttribute('content');
    let re = /maximum\-scale=[0-9\.]+/g;

    if (re.test(content)) {
        content = content.replace(re, 'maximum-scale=1.0');
    } else {
        content = [content, 'maximum-scale=1.0'].join(', ')
    }

    el.setAttribute('content', content);
  }
};

const disableIosTextFieldZoom = addMaximumScaleToMetaViewport;

// /programming/9038625/detect-if-device-is-ios/9039885#9039885
const checkIsIOS = () =>
  /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;

if (checkIsIOS()) {
  disableIosTextFieldZoom();
}

pourquoi vous créez une copie de addMaximumScaleToMetaViewport? Est-ce uniquement pour des raisons sémantiques?
Pherrymason

Oui, il suffit de mapper la fonction à un nom différent pour savoir clairement comment elle est utilisée.
Oliver Joseph Ash

8

Le hack Javascript qui fonctionne sur iOS 7. Il est basé sur la réponse de @dlo mais les événements mouseover et mouseout sont remplacés par les événements touchstart et touchend. Fondamentalement, ce script ajoute un délai d'attente d'une demi-seconde avant que le zoom ne soit à nouveau activé pour empêcher le zoom.

$("input[type=text], textarea").on({ 'touchstart' : function() {
    zoomDisable();
}});
$("input[type=text], textarea").on({ 'touchend' : function() {
    setTimeout(zoomEnable, 500);
}});

function zoomDisable(){
  $('head meta[name=viewport]').remove();
  $('head').prepend('<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0" />');
}
function zoomEnable(){
  $('head meta[name=viewport]').remove();
  $('head').prepend('<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=1" />');
} 

Cela a fonctionné le mieux pour moi. Mais, j'ai changé les événements touchstart / touchend en un événement 'focus' avec à la fois zoomDisable et zoomEnable.
Justin Cloud

L'ajout du délai semble fonctionner assez bien sur les nouvelles versions d'iOS, mais il est intéressant de noter qu'il ne fonctionne pas très bien lorsqu'il est réglé sur 250 ms. Cela suggère que dans certaines circonstances, 500 ms peuvent ne pas fonctionner non plus, mais si cela fonctionne la plupart du temps, je suppose que c'est mieux que de ne pas fonctionner du tout. Bien pensé.
dlo

7

Cela a fonctionné pour moi:

input, textarea {
    font-size: initial;
}

Joliment simple, mais existe-t-il un moyen de contrôler la taille "initiale"?
2540625

Je ne l'ai pas testé, mais cela devrait être un moyen de contrôler la taille de la police. (veuillez me faire savoir si cela fonctionne et je mettrai à jour ma réponse) body {font-size: 20px; } input {font-size: inherit; }

7

J'ai utilisé la solution de Christina ci-dessus, mais avec une petite modification pour le bootstrap et une autre règle à appliquer aux ordinateurs de bureau. La taille de police par défaut de Bootstrap est 14px, ce qui provoque le zoom. Ce qui suit le change en 16px pour les "contrôles de formulaire" dans Bootstrap, empêchant le zoom.

@media screen and (-webkit-min-device-pixel-ratio:0) {
  .form-control {
    font-size: 16px;
  }
}

Et revenons à 14px pour les navigateurs non mobiles.

@media (min-width: 768px) {
  .form-control {
    font-size: 14px;
  }
}

J'ai essayé d'utiliser .form-control: focus, qui l'a laissé à 14px, sauf sur la mise au point qui l'a changé en 16px et cela n'a pas résolu le problème du zoom avec iOS8. Au moins sur mon iPhone utilisant iOS8, la taille de la police doit être de 16 pixels avant de se concentrer pour que l'iPhone ne zoome pas sur la page.


6

Je l'ai fait, également avec jQuery:

$('input[type=search]').on('focus', function(){
  // replace CSS font-size with 16px to disable auto zoom on iOS
  $(this).data('fontSize', $(this).css('font-size')).css('font-size', '16px');
}).on('blur', function(){
  // put back the CSS font-size
  $(this).css('font-size', $(this).data('fontSize'));
});

Bien sûr, certains autres éléments de l'interface peuvent devoir être adaptés si cette 16pxtaille de police casse le design.


4
C'est chic. C'est stylin '. Je n'ai plus de jeux de mots. Approche intelligente.
crowjonah

@Wolfr avez-vous essayé sur un appareil réel?
Nicolas Hoizey

1
Cela a fonctionné pour nous sur iOS 12. J'aime cette approche la meilleure au lieu de contourner avec des transformations CSS et des marges négatives.
anonyme-un

6

Après un certain temps, j'ai trouvé cette solution

// set font-size to 16px to prevent zoom 
input.addEventListener("mousedown", function (e) {
  e.target.style.fontSize = "16px";
});

// change font-size back to its initial value so the design will not break
input.addEventListener("focus", function (e) {
  e.target.style.fontSize = "";
});

Sur "mousedown", il définit la taille de police de l'entrée à 16 pixels. Cela empêchera le zoom. Lors de l'événement focus, la taille de police revient à sa valeur initiale.

Contrairement aux solutions publiées précédemment, cela vous permettra de définir la taille de police de l'entrée comme vous le souhaitez.


Celui-ci fonctionne réellement pour moi, d'autant plus que dans les nouvelles versions d'iOS, vous ne pouvez pas utiliser la balise META de la fenêtre pour désactiver le zoom.
mparizeau

Travail confirmé sur iOS 12.1, merci
Ziki

6

Après avoir lu presque toutes les lignes ici et testé les différentes solutions, voici, grâce à tous ceux qui ont partagé leurs solutions, ce que j'ai trouvé, testé et travaillé pour moi sur iPhone 7 iOS 10.x:

@media screen and (-webkit-min-device-pixel-ratio:0) {
    input[type="email"]:hover,
    input[type="number"]:hover,
    input[type="search"]:hover,
    input[type="text"]:hover,
    input[type="tel"]:hover,
    input[type="url"]:hover,
    input[type="password"]:hover,
    textarea:hover,
    select:hover{font-size: initial;}
}
@media (min-width: 768px) {
    input[type="email"]:hover,
    input[type="number"]:hover,
    input[type="search"]:hover,
    input[type="text"]:hover,
    input[type="tel"]:hover,
    input[type="url"]:hover,
    input[type="password"]:hover,
    textarea:hover,
    select:hover{font-size: inherit;}
}

Il présente cependant certains inconvénients, notablement un "saut" en raison du changement rapide de taille de police qui se produit entre les états de "survol" et de "mise au point" - et l'impact du redessin sur les performances.


Merci pour vos commentaires, @MikeBoutin. Pouvez-vous s'il vous plaît partager votre env (version appareil / iOS)?
l3bel

6

Inspiré par la réponse de @jirikuchta, j'ai résolu ce problème en ajoutant ce peu de CSS:

#myTextArea:active {
  font-size: 16px; /* `16px` is safer I assume, although `1rem` works too */
}

Pas de JS, et je ne remarque aucun flash ou quoi que ce soit.

Il convient de noter qu'un viewportavec maximum-scale=1fonctionne également, mais pas lorsque la page est chargée en tant que iframe, ou si vous avez un autre script modifiant le viewport, etc.


4

Les pseudo-éléments comme :focusne fonctionnent plus comme avant. Depuis iOS 11, une simple déclaration de réinitialisation peut être ajoutée avant vos styles principaux (à condition de ne pas les remplacer avec une taille de police plus petite).

/* Prevent zoom */
select, input, textarea {
  font-size: 16px;
}

Il convient de mentionner que pour les bibliothèques CSS telles que Tachyons.css, il est facile de remplacer accidentellement la taille de votre police.

Par exemple, class: f5est équivalent à:fontSize: 1rem ce qui est bien si vous avez conservé l'échelle de police du corps par défaut.

Cependant: si vous choisissez la classe de taille de police: f6ce sera équivalent à fontSize: .875remsur un petit écran vers le haut. Dans ce cas, vous devrez être plus précis sur vos déclarations de réinitialisation:


  /* Prevent zoom */
  select, input, textarea {
    font-size: 16px!important;
  }

@media screen and (min-width: 30em) {

/* not small */

}

3

Par ailleurs, si vous utilisez Bootstrap , vous pouvez simplement utiliser cette variante:

.form-control {
  font-size: 16px;
}

3

J'ai dû "corriger" le problème du zoom automatique dans les contrôles de formulaire pour un site Web de l'université néerlandaise (qui utilisait 15 pixels dans les contrôles de formulaire). Je suis venu avec l'ensemble d'exigences suivantes:

  • l'utilisateur doit toujours pouvoir zoomer
  • la taille de la police doit rester la même
  • aucun flash de style différent temporaire
  • aucune exigence jQuery
  • doit fonctionner sur le dernier iOS et ne pas entraver toute autre combinaison OS / appareil
  • si possible pas de timeouts magiques, et si nécessaire effacer correctement les minuteries

Voici ce que j'ai trouvé jusqu'à présent:

/*
NOTE: This code overrides the viewport settings, an improvement would be
      to take the original value and only add or change the user-scalable value
*/

// optionally only activate for iOS (done because I havn't tested the effect under other OS/devices combinations such as Android)
var iOS = navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform)
if (iOS)
  preventZoomOnFocus();


function preventZoomOnFocus()
{
  document.documentElement.addEventListener("touchstart", onTouchStart);
  document.documentElement.addEventListener("focusin", onFocusIn);
}


let dont_disable_for = ["checkbox", "radio", "file", "button", "image", "submit", "reset", "hidden"];
//let disable_for = ["text", "search", "password", "email", "tel", "url", "number", "date", "datetime-local", "month", "year", "color"];


function onTouchStart(evt)
{
  let tn = evt.target.tagName;

  // No need to do anything if the initial target isn't a known element
  // which will cause a zoom upon receiving focus
  if (    tn != "SELECT"
      &&  tn != "TEXTAREA"
      && (tn != "INPUT" || dont_disable_for.indexOf(evt.target.getAttribute("type")) > -1)
     )
    return;

  // disable zoom
  setViewport("width=device-width, initial-scale=1.0, user-scalable=0");
}

// NOTE: for now assuming this focusIn is caused by user interaction
function onFocusIn(evt)
{
  // reenable zoom
  setViewport("width=device-width, initial-scale=1.0, user-scalable=1");
}

// add or update the <meta name="viewport"> element
function setViewport(newvalue)
{
  let vpnode = document.documentElement.querySelector('head meta[name="viewport"]');
  if (vpnode)
    vpnode.setAttribute("content",newvalue);
  else
  {
    vpnode = document.createElement("meta");
    vpnode.setAttribute("name", "viewport");
    vpnode.setAttribute("content", newvalue);
  }
}

Quelques notes:

  • Notez que jusqu'à présent, je ne l'ai testé que sur iOS 11.3.1, mais je le testerai bientôt sur quelques autres versions
  • L'utilisation d'événements focus signifie qu'il nécessite au moins iOS 5.1 (mais je vois quand même des sites que nous construisons fonctionnant dans des versions iOS plus anciennes que 9 comme un bonus sympa)
  • Utilisation de la délégation d'événements car de nombreux sites sur lesquels je travaille ont des pages qui pourraient créer dynamiquement des contrôles de formulaire
  • Définition des eventListeners sur l'élément html (documentElement) afin de ne pas avoir à attendre que le corps soit disponible (ne voulez pas vous embêter à vérifier si le document a l'état prêt / chargé ou devez attendre l'événement DOMContentLoaded)

3

Au lieu de simplement définir la taille de la police sur 16 pixels, vous pouvez:

  1. Stylez le champ de saisie de manière à ce qu'il soit plus grand que sa taille prévue, ce qui permet de définir la taille de police logique sur 16 pixels.
  2. Utilisez la scale()transformation CSS et les marges négatives pour réduire le champ de saisie à la taille correcte.

Par exemple, supposons que votre champ de saisie soit initialement stylisé avec:

input[type="text"] {
    border-radius: 5px;
    font-size: 12px;
    line-height: 20px;
    padding: 5px;
    width: 100%;
}

Si vous agrandissez le champ en augmentant toutes les dimensions de 16/12 = 133,33%, puis réduisez en utilisant scale()de 12/16 = 75%, le champ de saisie aura la bonne taille visuelle (et la taille de police), et il n'y aura pas de zoom sur concentrer.

Comme cela scale()n'affecte que la taille visuelle, vous devrez également ajouter des marges négatives pour réduire la taille logique du champ.

Avec ce CSS:

input[type="text"] {
    /* enlarge by 16/12 = 133.33% */
    border-radius: 6.666666667px;
    font-size: 16px;
    line-height: 26.666666667px;
    padding: 6.666666667px;
    width: 133.333333333%;

    /* scale down by 12/16 = 75% */
    transform: scale(0.75);
    transform-origin: left top;

    /* remove extra white space */
    margin-bottom: -10px;
    margin-right: -33.333333333%;
}

le champ de saisie aura une taille de police logique de 16 pixels tout en semblant avoir du texte 12 pixels.

J'ai un article de blog où j'entre dans un peu plus de détails, et j'ai cet exemple en HTML visible:
Pas de zoom d'entrée dans Safari sur iPhone, le moyen parfait pour les pixels


3

Même avec ces réponses, il m'a fallu trois jours pour comprendre ce qui se passait et j'aurai peut-être besoin de la solution à l'avenir.

Ma situation était légèrement différente de celle décrite.

Dans le mien, j'avais un texte contentable dans une div sur la page. Lorsque l'utilisateur a cliqué sur une div différente, un bouton en quelque sorte, j'ai automatiquement sélectionné du texte dans la div modifiable (une plage de sélection qui avait été précédemment enregistrée et effacée), j'ai exécuté une commande execCommand de texte enrichi sur cette sélection et l'ai effacée à nouveau.

Cela m'a permis de changer invisiblement les couleurs du texte en fonction des interactions des utilisateurs avec les divisions de couleurs ailleurs sur la page, tout en gardant la sélection normalement cachée pour leur permettre de voir les couleurs dans le contexte approprié.

Eh bien, sur Safari sur iPad, cliquer sur la couleur div a entraîné l'apparition du clavier à l'écran, et rien de ce que j'ai fait ne l'a empêché.

J'ai finalement compris comment l'iPad faisait ça.

Il écoute une séquence de démarrage et de contact qui déclenche une sélection de texte modifiable.

Lorsque cette combinaison se produit, elle affiche le clavier à l'écran.

En fait, il fait un zoom dolly où il développe la page sous-jacente tout en zoomant sur le texte modifiable. Cela m'a pris un jour juste pour comprendre ce que je voyais.

Donc, la solution que j'ai utilisée était d'intercepter à la fois le démarrage et le toucher sur ces divisions de couleurs particulières. Dans les deux gestionnaires, j'arrête la propagation et le bouillonnement et renvoie false. Mais dans l'événement tactile, je déclenche le même comportement que celui déclenché par le clic.

Donc, avant, Safari déclenchait ce que je pensais être "touchstart", "mousedown", "touchend", "mouseup", "click", et à cause de mon code, une sélection de texte, dans cet ordre.

La nouvelle séquence en raison des interceptions est simplement la sélection de texte. Tout le reste est intercepté avant que Safari puisse le traiter et faire son truc de clavier. Les interceptions touchstart et touchend empêchent également les événements de la souris de se déclencher, et dans le contexte, cela est tout à fait correct.

Je ne connais pas un moyen plus simple de décrire cela, mais je pense qu'il est important de l'avoir ici parce que j'ai trouvé ce fil dans l'heure suivant la première rencontre avec le problème.

Je suis sûr à 98% que le même correctif fonctionnera avec les zones de saisie et tout le reste. Interceptez les événements tactiles et traitez-les séparément sans les laisser se propager ou bouillonner, et envisagez de faire des sélections après un petit délai juste pour vous assurer que Safari ne reconnaît pas la séquence comme déclencheur du clavier.


C'est une excellente explication de ce que fait le safari. Merci!
Jeremy

2

Je vois des gens ici faire des choses étranges avec JavaScript ou la fonction de fenêtre et désactiver tous les zooms manuels sur les appareils. À mon avis, cela ne devrait pas être une solution. L'ajout de cet extrait CSS désactivera le zoom automatique dans iOS sans changer votre taille de police en un nombre fixe comme 16px.

Par défaut, j'utilise une taille de police de 93,8% (15px) dans les champs de saisie et en ajoutant mon extrait de code CSS, cela reste à 93,8%. Pas besoin de changer en 16px ou d'en faire un nombre fixe.

input[type="text"]:focus,
textarea:focus {
    -webkit-text-size-adjust: 100%;
}

5
Cela ne fonctionne pas pour moi, testé avec les derniers iOS 6 et iOS 9.2.1. Voici une page reproductible minimale: pastebin.com/bh5Zhe9h Il continue de zoomer sur la mise au point. Étrange que cela ait été publié en 2015 et que le vote positif ne fonctionne pas encore dans iOS 6.
Alexandre Dieulot

2

La définition d'une taille de police (pour les champs de saisie) égale à la taille de la police du corps semble être ce qui empêche le navigateur de faire un zoom avant ou arrière. Je suggère d'utiliser font-size: 1remune solution plus élégante.


1

Comme le zoom avant automatique (sans zoom arrière) est toujours ennuyeux sur iPhone, voici un JavaScript basé sur la suggestion de dlo de travailler avec le focus / flou.

Le zoom est désactivé dès qu'une entrée de texte est interrompue et réactivé lorsque l'entrée est laissée.

Remarque: Certains utilisateurs peuvent ne pas apprécier l'édition de textes dans une petite entrée de texte! Par conséquent, je préfère personnellement changer la taille du texte de l'entrée lors de l'édition (voir le code ci-dessous).

<script type="text/javascript">
<!--
function attachEvent(element, evtId, handler) {
    if (element.addEventListener) {
        element.addEventListener(evtId, handler, false);
    } else if (element.attachEvent) {
        var ieEvtId = "on"+evtId;
        element.attachEvent(ieEvtId, handler);
    } else {
        var legEvtId = "on"+evtId;
        element[legEvtId] = handler;
    }
}
function onBeforeZoom(evt) {
    var viewportmeta = document.querySelector('meta[name="viewport"]');
    if (viewportmeta) {
        viewportmeta.content = "user-scalable=0";
    }
}
function onAfterZoom(evt) {
    var viewportmeta = document.querySelector('meta[name="viewport"]');
    if (viewportmeta) {
        viewportmeta.content = "width=device-width, user-scalable=1";
    }
}
function disableZoom() {
    // Search all relevant input elements and attach zoom-events
    var inputs = document.getElementsByTagName("input");
    for (var i=0; i<inputs.length; i++) {
        attachEvent(inputs[i], "focus", onBeforeZoom);
        attachEvent(inputs[i], "blur", onAfterZoom);
    }
}
if (navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i)) {
    attachEvent(window, "load", disableZoom);
}
// -->
</script>

Le code suivant changera la taille du texte d'une entrée à 16 pixels (calculée, c'est-à-dire dans la taille de zoom actuelle) pendant que l'élément a le focus. L'iPhone ne zoomera donc pas automatiquement.

Remarque: Le facteur de zoom est calculé en fonction de window.innerWidth et de l'affichage de l'iPhone avec 320 pixels. Cela ne sera valable que pour l'iPhone en mode portrait.

<script type="text/javascript">
<!--
function attachEvent(element, evtId, handler) {
    if (element.addEventListener) {
        element.addEventListener(evtId, handler, false);
    } else if (element.attachEvent) {
        var ieEvtId = "on"+evtId;
        element.attachEvent(ieEvtId, handler);
    } else {
        var legEvtId = "on"+evtId;
        element[legEvtId] = handler;
    }
}
function getSender(evt, local) {
    if (!evt) {
        evt = window.event;
    }
    var sender;
    if (evt.srcElement) {
        sender = evt.srcElement;
    } else {
        sender = local;
    }
    return sender;
}
function onBeforeZoom(evt) {
    var zoom = 320 / window.innerWidth;
    var element = getSender(evt);
    element.style.fontSize = Math.ceil(16 / zoom) + "px";
}
function onAfterZoom(evt) {
    var element = getSender(evt);
    element.style.fontSize = "";
}
function disableZoom() {
    // Search all relevant input elements and attach zoom-events
    var inputs = document.getElementsByTagName("input");
    for (var i=0; i<inputs.length; i++) {
        attachEvent(inputs[i], "focus", onBeforeZoom);
        attachEvent(inputs[i], "blur", onAfterZoom);
    }
}
if (navigator.userAgent.match(/iPhone/i)) {
    attachEvent(window, "load", disableZoom);
}
// -->
</script>

1

Il m'a fallu du temps pour le trouver, mais voici le meilleur code que j'ai trouvé ...... http://nerd.vasilis.nl/prevent-ios-from-zooming-onfocus/

var $viewportMeta = $('meta[name="viewport"]');
$('input, select, textarea').bind('focus blur', function(event) {
$viewportMeta.attr('content', 'width=device-width,initial-scale=1,maximum-scale=' +        (event.type == 'blur' ? 10 : 1));
});

1

Basé sur la réponse de Stephen Walsh ... Ce code fonctionne sans changer la taille de la police des entrées sur le focus (qui semble boiteux), et il fonctionne toujours avec FastClick , que je suggère d'ajouter à tous les sites mobiles pour aider à apporter le "snappy". Ajustez votre "largeur de fenêtre" en fonction de vos besoins.

// disable autozoom when input is focused
    var $viewportMeta = $('head > meta[name="viewport"]');
    $('input, select, textarea').bind('touchend', function(event) {
        $viewportMeta.attr('content', 'width=640, user-scalable=0');
        setTimeout(function(){ $viewportMeta.attr('content', 'width=640, user-scalable=1'); }, 1)
    });

Si l'utilisateur avait déjà zoomé un peu avant de cliquer sur le contrôle d'entrée, cette solution ferait-elle soudainement "dézoomer" la fenêtre?
Bruno Torquato

Oui, mais cela n'a pas l'air plus choquant que le précédent effet de "zoom" qui se produisait chaque fois que l'utilisateur cliquait sur une entrée.
Pete

1

Un commentaire pour la meilleure réponse sur la définition de la taille de la police à 16 pixels a demandé comment cela était une solution, et si vous vouliez une police plus grande / plus petite.

Je ne sais pas tout de vous, mais utiliser px pour les tailles de police n'est pas la meilleure solution, vous devriez les utiliser.

J'ai rencontré ce problème sur mon site réactif où mon champ de texte est supérieur à 16 pixels. J'ai eu mon conteneur de formulaires défini sur 2rem et mon champ de saisie sur 1.4em. Dans mes requêtes mobiles, je change la taille de police html en fonction de la fenêtre d'affichage. Étant donné que le code HTML par défaut est 10, mon champ de saisie est calculé à 28 pixels sur le bureau

Pour supprimer le zoom automatique, j'ai dû changer mon entrée à 1.6em. Cela a augmenté ma taille de police à 32 pixels. Juste un peu plus haut et à peine perceptible. Sur mon iPhone 4 et 5, je change ma taille de police html à 15 pixels pour le portrait et à 10 pixels pour le paysage. Il est apparu que le point idéal pour cette taille de pixel était de 48 pixels, c'est pourquoi je suis passé de 1,4em (42px) à 1,6em (48px).

La chose que vous devez faire est de trouver le point idéal sur la taille de la police, puis de la convertir en arrière dans vos tailles rem / em.


1

Voici un hack que j'ai utilisé sur l'un de mes projets:

select {
    font-size: 2.6rem; // 1rem = 10px
    ...
    transform-origin: ... ...;
    transform: scale(0.5) ...;
}

J'ai fini avec les styles et l'échelle initiaux que je voulais, mais pas de zoom sur la mise au point.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.