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?
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?
Respuestas:
El navegador hará zoom si el tamaño de fuente es menor 16px
y el tamaño de fuente predeterminado para los elementos del formulario es 11px
(al menos en Chrome y Safari).
Además, el select
elemento necesita tener la focus
pseudoclase 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
, number
y 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;
}
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; }
select:focus
. Estaba teniendo el mismo problema también.
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=1
pero 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">
@media screen and (-webkit-min-device-pixel-ratio:0) {
select:focus,
textarea:focus,
input:focus {
font-size: 16px;
background: #eee;
}
}
@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.
@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.
@supports (-webkit-overflow-scrolling: touch)
, ya que esta característica css solo existe en iOS
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'.
En resumen, la respuesta es: establecer el tamaño de fuente de los elementos del formulario en al menos 16px
font-size: 100%
valor y toma los 16px necesarios.
input[type='text'],textarea {font-size:1em;}
1em
, o 100%
). Si configura un tamaño de fuente personalizado, puede configurarlo font-size
en su fragmento 16px
para evitar el zoom automático.
1em
tampoco 1rem
es una solución adecuada porque ambos pueden ser menores 16px
y Safari requiere al menos 16px
no hacer zoom.
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"/>
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.
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 :)
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;
}
Como muchas otras respuestas ya han señalado, esto se puede lograr agregando maximum-scale
a 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-scale
al meta viewport
cuando 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();
}
addMaximumScaleToMetaViewport
? ¿Es solo por razones semánticas?
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ó para mí:
input, textarea {
font-size: initial;
}
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.
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 16px
tamaño de fuente rompe el diseño.
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.
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
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 viewport
con maximum-scale=1
tambié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.
Los pseudo elementos como :focus
ya 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: f5
es equivalente a:, lo fontSize: 1rem
cual está bien si ha mantenido la escala de fuente del cuerpo por defecto.
Sin embargo: si elige la clase de tamaño de fuente: f6
será equivalente a fontSize: .875rem
una 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 */
}
Por cierto, si usa Bootstrap , puede usar esta variante:
.form-control {
font-size: 16px;
}
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:
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:
En lugar de simplemente establecer el tamaño de fuente en 16px, puede:
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
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.
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%;
}
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: 1rem
como una solución más elegante.
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>
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));
});
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)
});
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.