Deshabilitar el zoom automático en la etiqueta de entrada "Texto" - Safari en iPhone


541

Hice una página HTML con una <input>etiqueta type="text". Cuando hago clic en él usando Safari en iPhone, la página se hace más grande (zoom automático). ¿Alguien sabe cómo deshabilitar esto?


8
Para todos los usuarios de Twitter Bootstrap que aterrizan aquí: vea también este problema de Github .
Jeroen

77
Creo que la respuesta de @daxmacrog responde exactamente lo que quieres, ¿estás dispuesto a aceptarlo para que pueda llegar a la cima y ahorrar mucho trabajo de las personas que leen todo esto? Respuesta de 2018: stackoverflow.com/a/46254706/172651
Evoluciona el

@Evolucionar la respuesta de la que habló rompe la funcionalidad de pellizco y zoom de Android. La respuesta de daxmacrog es defectuosa.
MH

55
Lo juro, Apple crea estas anti-características solo para molestarnos.
Andrew Koster

@ AndrewKoster, estoy de acuerdo contigo incluso ahora en 2020.
Ashok

Respuestas:


492

El navegador hará zoom si el tamaño de fuente es menor 16pxy el tamaño de fuente predeterminado para los elementos del formulario es 11px(al menos en Chrome y Safari).

Además, el selectelemento necesita tener la focuspseudoclase adjunta.

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;
}

No es necesario el uso de todo lo anterior, sólo puede estilo de los elementos que necesita, por ejemplo: solo text, numbery textarea:

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

Solución alternativa para que los elementos de entrada hereden de un estilo primario:

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

81
Solo para tener todo cubierto: 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 Necesitas usar select:focus. Estaba teniendo el mismo problema también.
DGibbs

141
No entiendo, ¿cómo es esto una solución? ¿Qué pasa si quiero un tamaño de fuente más pequeño / más grande?
bryan

47
la forma correcta es cambiar la metaetiqueta a: <meta name = "viewport" content = "width = device-width, initial-scale = 1, maximum-scale = 1, escalable por el usuario = 0" />
Milos Matic

37
@MilosMatic En la mayoría de los casos, probablemente no sea una buena solución, ya que evita completamente que el usuario escale la página. Potencialmente aún más molesto para sus visitantes.
BadHorsie

363

Puede evitar que Safari amplíe automáticamente los campos de texto durante la entrada del usuario sin deshabilitar la capacidad del usuario para pellizcar el zoom. Simplemente agregue maximum-scale=1pero omita el atributo de escala de usuario sugerido en otras respuestas.

Es una opción que vale la pena si tiene un formulario en una capa que "flota" si se hace zoom, lo que puede hacer que elementos importantes de la IU se muevan fuera de la pantalla.

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


66
Esta es la solución 2018+. Vota esto como si tu vida dependiera de ello.
Henrik Petterson

17
Esto romperá la capacidad de zoom de los dispositivos Android
fen1ksss

44
@daxmacrog, tienes razón, pero el OP no mencionó si quiere romper los androides al permitir el comportamiento necesario. Aquí es donde personalmente tomé la opción incorrecta. Por supuesto, es mejor especificar.
fen1ksss

13
@HenrikPetterson Esto hace más que deshabilitar el zoom automático según lo especificado por OP, también deshabilita el zoom de pellizco. Así que no creo que sea la solución 2018+.
André Werlang

44
@ AndréWerlang Eso no es exacto. Como se indica claramente en la respuesta, esta solución no deshabilita el zoom de pellizco en Safari (o Firefox), que es lo que preguntó el OP. Pero como se señaló en comentarios anteriores, deshabilita el zoom del usuario en dispositivos Android y en Chrome en iOS.
daxmacrog

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

Nuevo: IOS seguirá haciendo zoom, a menos que use 16 píxeles en la entrada sin el foco.

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

Agregué un fondo ya que IOS no agrega ningún fondo en la selección.


99
Esto funciona no solo para safari en iOS (iphone / ipad / ipod), sino también Safari / OSX y Chrome (Windows y Mac). Entonces, si está tratando de apuntar específicamente al iPhone, esto no funcionará.
Redtopia

31
¿Por qué todos dicen 16px pero a nadie le importa mencionar por qué exactamente es 16px? ¿Por qué un número tan arbitrario? ¿Por qué tenemos que establecer el tamaño del texto del campo de formulario en 16px y no ... digamos 1.8rem o 2.5em o algo así? ¿Es solo un error estúpido de un sistema operativo propietario?
Beebee

14
@Beebee El tamaño de fuente del 100% es de 16px, que es el predeterminado para la mayoría, si no para todos, los navegadores (también de escritorio). IOS lo usa como predeterminado probablemente porque es un tamaño cómodo para leer. Por qué está configurado de esta manera, no me he molestado en buscar, no me importa.
Christina

55
Use @media screen and (-webkit-min-device-pixel-ratio:0) and (max-device-width:1024px)para limitar el efecto al iPhone, pero no modifique los sitios web cuando se ve en Chrome.
BurninLeo

99
En lugar de usar una consulta de medios, debe usar @supports (-webkit-overflow-scrolling: touch), ya que esta característica css solo existe en iOS
James Moran

189

Si su sitio web está diseñado correctamente para un dispositivo móvil, puede decidir no permitir el escalado.

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

Esto resuelve el problema de que su página móvil o formulario va a 'flotar'.


123
Técnicamente correcto, pero no estoy de acuerdo con el razonamiento. Desactivar los acercamientos de los usuarios en un sitio diseñado adecuadamente es, en general, una mala idea.
Fer

20
"Diseñado adecuadamente" es muy subjetivo. Considere un encabezado fijo de 50 px en la parte superior de un sitio que sea totalmente receptivo y que funcione en todos los navegadores. Hacer zoom en iOS Safari rompe el posicionamiento del encabezado y prácticamente rompe todo el sitio.
Redtopia

6262
Deshabilitar la capacidad de zoom del usuario es una práctica terrible desde una perspectiva UX y realmente debe evitarse a toda costa. Poder acercar libremente es una característica básica de accesibilidad y un control que nunca debe quitarle al usuario.
Gabriel Luethje

72
En las aplicaciones móviles nativas nunca tienes la oportunidad de hacer zoom y funcionan bien, ¿por qué una aplicación web sería diferente? Si establece el tamaño de fuente y la altura de línea apropiados con contrastes claros, debería estar bien.
jotav

39
Aquellos que usan el argumento 'está bien en aplicaciones nativas' están pasando por alto el hecho de que las aplicaciones nativas bien hechas se adhieren a la configuración de accesibilidad a nivel del sistema operativo, como el tamaño del texto. Los usuarios mayores y con poca visión pueden usar, y lo hacen, tamaños de fuente extremadamente grandes en todo el sistema operativo porque lo necesitan . Las aplicaciones web a menudo no cumplen o no pueden cumplir con esta configuración, por lo tanto, es vital permitir la funcionalidad de accesibilidad incorporada del navegador web, como el zoom Lo que creas que es perfectamente legible, créeme, hay personas que no lo encontrarán lo suficientemente claro. No , no tomar esta opción no disponible para usuarios si el valor de la usabilidad.
Ryan Williams

72

En resumen, la respuesta es: establecer el tamaño de fuente de los elementos del formulario en al menos 16px


Sí, esta es definitivamente la mejor práctica para evitar hacer zoom en dispositivos móviles. Sin js, sin hacks, sin soluciones en absoluto. Pero incluso con 16px noté un pequeño zoom en mis páginas, así que probé 17px, 18px ... para ver qué pasa.
ed1nh0

8
Se recomienda declarar el 100% en el cuerpo, botón, entrada, área de texto y elementos seleccionados. Esto permite al usuario establecer un valor predeterminado que no sea el 16px enviado con los navegadores. Alguien que tiene problemas para leer en la pantalla puede establecer su valor predeterminado en 18px o 20px. No desea anular su elección forzando 16px sobre ellos. Sin embargo, cuando se trata de iOS, tomaron la decisión de ampliar cualquier valor que su HIG dice que es demasiado pequeño. Desafortunadamente, parece que no interpreta el valor del 100%, por lo que estamos atascados agregando el valor predeterminado para apaciguarlo.
J. Hogue

RE iOS Safari, a partir de este comentario parece que Safari interpreta correctamente el font-size: 100%valor y toma los 16px necesarios.
Nathan Lafferty

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

3
Tenga en cuenta que la configuración de escalable por el usuario en no deshabilitará todo el zoom, lo que probablemente sea una mala idea.
Stormsweeper

18
Esto solo funciona si el tamaño de fuente de su cuerpo es el predeterminado (sin especificar, o 1em, o 100%). Si configura un tamaño de fuente personalizado, puede configurarlo font-sizeen su fragmento 16pxpara evitar el zoom automático.
Alan H.

Sé que esta pregunta se dirigió al iPhone, pero esto es más compatible en todas las plataformas y en el futuro de más plataformas / dispositivos, probé el enfoque de 16px, pero en una tableta Android solo reduje el efecto de zoom automático. La configuración de '1em' como se especifica en la publicación resolvió el problema.
toddles_fp

3
Ni 1emtampoco 1remes una solución adecuada porque ambos pueden ser menores 16pxy Safari requiere al menos 16pxno hacer zoom.
Finesse

2
utilicé la solución viewport pero no funcionó, la solución de 16px funciona bien, pero 16px es demasiado grande para inputbox de mi sitio, ¿hay alguna tercera solución?
Suneth Kalhara

21

La forma correcta de solucionar este problema es cambiar la vista meta a:

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


32
Esta no es necesariamente la forma "adecuada" de prevenir este comportamiento. Mobile Safari se acerca si el texto se considera demasiado pequeño para leer. Desactivar el zoom todo junto es una tarea difícil y evita que los usuarios puedan interactuar con su página de la manera que pueden esperar.
AlecRust

3
Aparentemente, en iOS10, Apple cambió la propiedad de escala máxima para que ya no se respete, permitiendo que todos los sitios se acerquen independientemente de su configuración.
Wolfr

3
Esto funciona para iOS10 20 / septiembre / 2016 versión ... al menos funciona en mi aplicación ... ¡Gracias! Antes de usar <meta name = "viewport" content = "ancho = ancho del dispositivo, escala inicial = 1, escala mínima = 1 , escala máxima = 1"> Pero lo cambié a la línea en la respuesta y funcionó ...
eljamz

1
"Asegúrese de que el zoom del pellizco del navegador no esté bloqueado por el metaelemento de la ventana gráfica de la página, de modo que pueda usarse para ampliar la página al 200%. Deben evitarse los valores restrictivos para los atributos escalables por el usuario y de escala máxima de este metaelemento". w3.org/TR/mobile-accessibility-mapping/#zoom-magnification
danielnixon

He visto comentarios sobre cómo algunas de estas metaetiquetas no funcionan en iOS 10 y sé que lo anterior funciona en Chrome para iOS al menos. :) ¡Gracias!
cbloss793

16

No hay una manera limpia que pueda encontrar, pero aquí hay un truco ...

1) Noté que el evento mouseover ocurre antes del zoom, pero el zoom ocurre antes de mousedown o eventos de enfoque.

2) Puede cambiar dinámicamente la etiqueta de ventana META usando javascript (consulte ¿ Habilitar / deshabilitar zoom en iPhone safari con Javascript? )

Entonces, intente esto (se muestra en jquery para compacidad):

$("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" />');
}

Esto definitivamente es un truco ... puede haber situaciones en las que el mouseover / down no siempre atrape entradas / salidas, pero funcionó bien en mis pruebas y es un comienzo sólido.


55
No estoy seguro de cuándo podría haber cambiado el comportamiento de Safari, pero ahora el mousedown (iOS6.0.1) está ocurriendo antes del autozoom. Por lo tanto, en mi solución anterior, el zoom se vuelve a habilitar demasiado pronto. No he encontrado una solución adecuada, ya que todos los eventos que probé ahora ocurren antes del zoom. Puede volver a habilitar el zoom al presionar una tecla o desenfocar, pero hay algunos escenarios que esto podría pasar por alto (como si el usuario desea hacer zoom manualmente antes de comenzar a escribir algo).
dlo 01 de

15

Agregue escalable por el usuario = 0 a la meta de ventana gráfica de la siguiente manera

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

Trabajó para mi :)


11
"Asegúrese de que el zoom del pellizco del navegador no esté bloqueado por el metaelemento de la ventana gráfica de la página, de modo que pueda usarse para ampliar la página al 200%. Deben evitarse los valores restrictivos para los atributos escalables por el usuario y de escala máxima de este metaelemento". w3.org/TR/mobile-accessibility-mapping/#zoom-magnification
danielnixon

99
Esto rompe las reglas de accesibilidad definidas por W3.
Joshua Russell

funcionó para mí, también esta es la mejor solución para mí, ya que quiero la libertad de cambiar los tamaños de fuente de entrada por debajo de 16px y no quiero un truco JS
Blue Bot

14

Recientemente (hoy: D) tuve que integrar este comportamiento. Para no afectar los campos de diseño originales, incluido el combo, opté por aplicar la transformación en el foco del campo:

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

Para su información, esto funcionó bien en mi iPhone 5 con iOS 6, pero en un iPhone 4 con iOS 5 en modo vertical, el estilo de enfoque se aplicó después de que se produjo el zoom. Tal vez algo sutil está sucediendo, no investigué más.
Vish

Solo quiero decir que tengo muchas consultas diferentes usando el zoom para hacer que el desarrollo sea más rápido y, dependiendo de cuánto zoom determinará cuánto tamaño de fuente necesita, creo
Mike

: focus no funcionó para mí iOS 10.2 iPhone 6, pero input [type = "text"]: hover funcionó bien.
Amirhossein Rzd

13

Como muchas otras respuestas ya han señalado, esto se puede lograr agregando maximum-scalea la metaetiqueta viewport. Sin embargo, esto tiene la consecuencia negativa de deshabilitar el zoom del usuario en dispositivos Android . ( No deshabilita el zoom del usuario en dispositivos iOS desde la versión 10 ).

Podemos usar JavaScript para agregar dinámicamente maximum-scaleal meta viewportcuando el dispositivo es iOS. Esto logra lo mejor de ambos mundos: le permitimos al usuario hacer zoom y evitar que iOS haga zoom en los campos de texto en foco.

| 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               |

Código:

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();
}

¿Por qué creas una copia de addMaximumScaleToMetaViewport? ¿Es solo por razones semánticas?
Pherrymason

Sí, solo asigna la función a un nombre diferente para que quede claro cómo se está utilizando.
Oliver Joseph Ash

8

Hack de Javascript que funciona en iOS 7. Esto se basa en la respuesta de @dlo, pero los eventos mouseover y mouseout se reemplazan por eventos touchstart y touchend. Básicamente, este script agrega un tiempo de espera de medio segundo antes de que el zoom se habilite nuevamente para evitar el 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" />');
} 

Esto funcionó mejor para mí. Pero, cambié los eventos de inicio / toque automático a un evento de 'enfoque' con zoomDisable y zoomEnable.
Justin Cloud

Agregar el retraso parece funcionar bastante bien en las versiones más nuevas de iOS, pero es interesante que no funcione muy bien cuando se configura a 250 ms. Eso sugiere que, en algunas circunstancias, 500ms podría no funcionar tampoco, pero si funciona la mayor parte del tiempo, supongo que es mejor que no funcionar en absoluto. Buen pensamiento.
dlo

7

Esto funcionó para mí:

input, textarea {
    font-size: initial;
}

Muy simple, pero ¿hay alguna forma de controlar cuál es ese tamaño "inicial"?
2540625

No lo he probado, pero esta debería ser una forma de controlar el tamaño de la fuente. (por favor, avíseme si esto funciona y actualizaré mi respuesta) body {font-size: 20px; } input {tamaño-fuente: heredar; }

7

Usé la solución de Christina anterior, pero con una pequeña modificación para bootstrap y otra regla para aplicar a las computadoras de escritorio. El tamaño de fuente predeterminado de Bootstrap es 14px, lo que provoca el zoom. Lo siguiente lo cambia a 16px para "controles de formulario" en Bootstrap, evitando el zoom.

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

Y de vuelta a 14px para navegadores no móviles.

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

Intenté usar .form-control: focus, que lo dejó en 14px excepto en el foco que lo cambió a 16px y no solucionó el problema de zoom con iOS8. Al menos en mi iPhone con iOS8, el tamaño de fuente debe ser de 16px antes de enfocar para que el iPhone no amplíe la página.


6

Hice esto, también con 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'));
});

Por supuesto, algunos otros elementos en la interfaz pueden tener que adaptarse si este 16pxtamaño de fuente rompe el diseño.


44
Esto es elegante. Esto es estilismo. Estoy sin juegos de palabras. Enfoque inteligente.
crowjonah

@Wolfr, ¿probaste un dispositivo real?
Nicolas Hoizey

1
Esto funcionó para nosotros en iOS 12. Me gusta este enfoque mejor en lugar de perder el tiempo con transformaciones CSS y márgenes negativos.
anónimo-uno

6

Después de un tiempo de intentarlo, se me ocurrió esta solución.

// 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 = "";
});

En "mousedown" establece el tamaño de fuente de entrada a 16px. Esto evitará el zoom. En el evento de foco, cambia el tamaño de fuente de nuevo al valor inicial.

A diferencia de las soluciones publicadas anteriormente, esto le permitirá establecer el tamaño de fuente de la entrada a lo que desee.


Este realmente funciona para mí, especialmente porque en las versiones más recientes de iOS no puedes usar la metaetiqueta de la vista para deshabilitar el zoom.
mparizeau

Confirmado trabajando en iOS 12.1, gracias
Ziki

6

Después de leer casi todas las líneas aquí y probar las diversas soluciones, esto es, gracias a todos los que compartieron sus soluciones, lo que se me ocurrió, probé y funcionó para mí en el 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;}
}

Sin embargo, tiene algunas desventajas, notablemente un "salto" como resultado del rápido cambio de tamaño de fuente que ocurre entre los estados ed "hover" y "focus" ed, y el impacto de rediseño en el rendimiento


Gracias por tus comentarios, @MikeBoutin. ¿Puedes compartir tu env (dispositivo / versión de iOS)?
l3bel

6

Inspirado por la respuesta de @jirikuchta, resolví este problema agregando este bit de CSS:

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

No JS, y no noto ningún flash ni nada.

Vale la pena señalar que un viewportcon maximum-scale=1también funciona, pero no cuando la página se carga como un iframe, o si tiene algún otro script que modifique el viewport, etc.


4

Los pseudo elementos como :focusya no funcionan como solían hacerlo. Desde iOS 11, se puede agregar una declaración de reinicio simple antes de sus estilos principales (siempre que no los anule con un tamaño de fuente más pequeño).

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

Vale la pena mencionar que para las bibliotecas CSS como Tachyons.css, es fácil anular accidentalmente el tamaño de la fuente.

Por ejemplo, class: f5es equivalente a:, lo fontSize: 1remcual está bien si ha mantenido la escala de fuente del cuerpo por defecto.

Sin embargo: si elige la clase de tamaño de fuente: f6será equivalente a fontSize: .875remuna pantalla pequeña hacia arriba. En ese caso, deberá ser más específico acerca de sus declaraciones de reinicio:


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

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

/* not small */

}

3

Por cierto, si usa Bootstrap , puede usar esta variante:

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

3

Tuve que "arreglar" el problema del zoom automático en los controles de formulario para un sitio web de la Universidad Holandesa (que usaba 15 píxeles en controles de formulario). Se me ocurrió el siguiente conjunto de requisitos:

  • el usuario aún debe poder acercar
  • el tamaño de fuente debe permanecer igual
  • sin destellos de estilo temporal diferente
  • no se requiere jQuery
  • debe funcionar en el iOS más nuevo y no obstaculizar ninguna otra combinación de sistema operativo / dispositivo
  • si es posible no hay tiempos de espera mágicos, y si es necesario, borre los temporizadores correctamente

Esto es lo que se me ocurrió hasta ahora:

/*
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);
  }
}

Algunas notas:

  • Tenga en cuenta que hasta ahora solo lo he probado en iOS 11.3.1, pero lo probaré en algunas otras versiones pronto
  • El uso de focusIn events significa que requiere al menos iOS 5.1 (pero veo que los sitios que creamos funcionan en versiones de iOS anteriores a 9 como un buen bono de todos modos)
  • Uso de la delegación de eventos porque muchos sitios en los que trabajo tienen páginas que pueden crear dinámicamente controles de formulario
  • Configurar eventListeners en el elemento html (documentElement) para no tener que esperar a que el cuerpo esté disponible (no quiere molestarse en verificar si el documento tiene un estado listo / cargado o si necesita esperar el evento DOMContentLoaded)

3

En lugar de simplemente establecer el tamaño de fuente en 16px, puede:

  1. Diseñe el campo de entrada para que sea más grande que su tamaño previsto, permitiendo que el tamaño de fuente lógica se establezca en 16px.
  2. Use la scale()transformación CSS y los márgenes negativos para reducir el campo de entrada al tamaño correcto.

Por ejemplo, suponga que su campo de entrada tiene un estilo original con:

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

Si amplía el campo aumentando todas las dimensiones en 16/12 = 133.33%, luego reduce el uso scale()en 12/16 = 75%, el campo de entrada tendrá el tamaño visual correcto (y el tamaño de fuente), y no habrá zoom en atención.

Como scale()solo afecta el tamaño visual, también necesitará agregar márgenes negativos para reducir el tamaño lógico del campo.

Con este 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%;
}

el campo de entrada tendrá un tamaño de fuente lógico de 16px mientras que parece tener texto de 12px.

Tengo una publicación en el blog donde entre un poco más de detalles, y tengo este ejemplo como HTML visible:
Sin zoom de entrada en Safari en iPhone, la forma perfecta de píxeles


3

Incluso con estas respuestas, me llevó tres días descubrir qué estaba pasando y es posible que necesite la solución nuevamente en el futuro.

Mi situación era ligeramente diferente de la descrita.

En el mío, tenía un texto contento en un div en la página. Cuando el usuario hizo clic en un div DIFERENTE, un tipo de botón, seleccioné automáticamente algo de texto en el div contenteditable (un rango de selección que previamente se había guardado y borrado), ejecuté un execCommand de texto enriquecido en esa selección y lo borré nuevamente.

Esto me permitió cambiar invisiblemente los colores del texto en función de las interacciones del usuario con los divisores de color en otra parte de la página, mientras mantenía la selección normalmente oculta para permitirles ver los colores en el contexto adecuado.

Bueno, en el Safari de iPad, al hacer clic en el div de color, apareció el teclado en pantalla y nada de lo que hice lo impidió.

Finalmente descubrí cómo el iPad está haciendo esto.

Escucha una secuencia de inicio táctil y toque que desencadena una selección de texto editable.

Cuando ocurre esa combinación, muestra el teclado en pantalla.

En realidad, hace un zoom dolly donde expande la página subyacente mientras hace zoom en el texto editable. Me llevó un día entender lo que estaba viendo.

Entonces, la solución que utilicé fue interceptar touchstart y touchend en esos divs de color particulares. En ambos manejadores detengo la propagación y el burbujeo y devuelvo falso. Pero en el evento touchend, disparo el mismo comportamiento que el clic activado.

Entonces, antes, Safari estaba activando lo que creo que era "touchstart", "mousedown", "touchend", "mouseup", "click", y debido a mi código, una selección de texto, en ese orden.

La nueva secuencia debido a las intersecciones es simplemente la selección de texto. Todo lo demás se intercepta antes de que Safari pueda procesarlo y hacer sus tareas de teclado. Las interceptaciones touchstart y touchend evitan que los eventos del mouse también se activen, y en contexto esto está totalmente bien.

No conozco una forma más fácil de describir esto, pero creo que es importante tenerlo aquí porque encontré este hilo dentro de una hora de haber encontrado el problema por primera vez.

Estoy 98% seguro de que la misma solución funcionará con cuadros de entrada y cualquier otra cosa. Intercepta los eventos táctiles y procesalos por separado sin dejar que se propaguen o burbujeen, y considera hacer cualquier selección después de un pequeño tiempo de espera solo para asegurarte de que Safari no reconozca la secuencia como el disparador del teclado.


Esta es una gran explicación de lo que está haciendo el safari. ¡Gracias!
Jeremy

2

Veo que la gente aquí hace cosas extrañas con JavaScript o la función de ventana gráfica y apaga todo el zoom manual en los dispositivos. Eso no debería ser una solución en mi opinión. Agregar este fragmento de CSS desactivará el zoom automático en iOS sin cambiar su tamaño de fuente a un número fijo como 16px.

De manera predeterminada, uso el tamaño de fuente del 93.8% (15px) en los campos de entrada y al agregar mi fragmento de CSS esto permanece en el 93.8%. No es necesario cambiar a 16px o convertirlo en un número fijo.

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

55
Esto no funciona para mí, probado con los últimos iOS 6 e iOS 9.2.1. Aquí hay una página mínima reproducible: pastebin.com/bh5Zhe9h Todavía se enfoca. Es extraño que esto se haya publicado en 2015 y haya sido votado aún, pero no funciona en iOS 6.
Alexandre Dieulot

2

Establecer un tamaño de fuente (para los campos de entrada) igual al tamaño de fuente del cuerpo, parece ser lo que evita que el navegador se aleje o se acerque. Sugeriría usarlo font-size: 1remcomo una solución más elegante.


1

Como el acercamiento automático (sin alejamiento) todavía es anónimo en iPhone, aquí hay un JavaScript basado en la sugerencia de dlo que funciona con enfoque / desenfoque.

El zoom se deshabilita en cuanto una entrada de texto se borra y se vuelve a habilitar cuando se deja la entrada.

Nota: ¡Es posible que algunos usuarios no aprendan a editar textos en una entrada de texto pequeña! Por lo tanto, personalmente prefiero cambiar el tamaño del texto de entrada durante la edición (vea el código a continuación).

<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>

El siguiente código cambiará el tamaño del texto de una entrada a 16 píxeles (calculado, es decir, en el tamaño de zoom actual) durante el elemento que tiene el foco. Por lo tanto, el iPhone no se acercará automáticamente.

Nota: El factor de zoom se calcula en función de window.innerWidth y la pantalla del iPhone con 320 píxeles. Esto solo será válido para iPhone en modo vertical.

<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

Me tomó un tiempo encontrarlo, pero aquí está el mejor código que encontré ... 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

Basado en la respuesta de Stephen Walsh ... Este código funciona sin cambiar el tamaño de fuente de las entradas en foco (lo que parece cojo), además de que todavía funciona con FastClick , que sugiero agregar a todos los sitios móviles para ayudar a traer el "rápido". Ajuste su "ancho de ventana" para satisfacer sus necesidades.

// 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 el usuario ya hubiera ampliado un poco antes de hacer clic en el control de entrada, ¿esta solución provocaría que la ventana gráfica de repente se "despegara"?
Bruno Torquato

Sí, pero no parece más discordante que el efecto "zoom" anterior que ocurría cada vez que el usuario hacía clic en una entrada.
Pete

1

Un comentario para la respuesta principal sobre cómo configurar el tamaño de fuente en 16px preguntó cómo es una solución, y si desea una fuente más grande / más pequeña.

No sé sobre todos ustedes, pero usar px para los tamaños de fuente no es la mejor manera de hacerlo, deberían usar em.

Me encontré con este problema en mi sitio receptivo donde mi campo de texto es mayor de 16 píxeles. Tenía mi contenedor de formularios establecido en 2rem y mi campo de entrada establecido en 1.4em. En mis consultas móviles, cambio el tamaño de fuente html según la ventana gráfica. Como el html predeterminado es 10, mi campo de entrada se calcula a 28 px en el escritorio

Para eliminar el zoom automático, tuve que cambiar mi entrada a 1.6em. Esto aumentó el tamaño de mi fuente a 32px. Solo un poco más alto y apenas perceptible. En mi iPhone 4 y 5, cambio mi tamaño de fuente html a 15px para vertical y de nuevo a 10px para horizontal. Parece que el punto óptimo para ese tamaño de píxel era 48px, por lo que cambié de 1.4em (42px) a 1.6em (48px).

Lo que debe hacer es encontrar el punto óptimo en el tamaño de fuente y luego convertirlo al revés en sus tamaños rem / em.


1

Aquí hay un truco que utilicé en uno de mis proyectos:

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

Terminé con los estilos iniciales y la escala que quería, pero sin enfoque de enfoque.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.