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




mobile dont (24)

JavaScript hack que funciona en iOS 7. Esto se basa en la respuesta de @dlo, pero los eventos de mouseover y mouseout son reemplazados por touchstart y touchend. Básicamente, esta secuencia de comandos 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" />');
} 

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


Después de leer casi todas las líneas aquí y probar las distintas soluciones, esto es, gracias a todos los que compartieron sus soluciones, lo que se me ocurrió, probé y trabajé para mí en 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 algunos inconvenientes, notablemente un "salto" como resultado del cambio rápido en el tamaño de la fuente que se produce entre los estados de "desplazamiento" y "enfoque", y el impacto de redibujado en el rendimiento


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

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

Por ejemplo, supongamos que su campo de entrada está originalmente diseñado 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 reduzca 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 deberá 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 en la que profundizo un poco más, y tengo este ejemplo como HTML visible:
No hay zoom de entrada en Safari en iPhone, la manera perfecta de píxeles


Aquí hay un hack 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 zoom.


Hace poco (hoy: D) tuve que integrar este comportamiento. Para no afectar los campos de diseño original, 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;
}

Esto funcionó para mí:

input, textarea {
    font-size: initial;
}

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

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

1) Noté que el evento de mouseover ocurre antes del zoom, pero el zoom ocurre antes de los eventos de ratón o enfoque.

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

Por lo tanto, intente esto (se muestra en jquery para la 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 es definitivamente un hackeo ... puede haber situaciones en las que el mouseover / abajo no siempre atrapa entradas / salidas, pero funcionó bien en mis pruebas y es un buen comienzo.


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


@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 16px en la entrada sin el enfoque.

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


Después de un rato 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 enfoque, 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 en lo que desee.


He tenido que "arreglar" el zoom automático en el problema de controles de formulario para un sitio web de la Universidad Holandesa (que usaba 15px en los controles de formulario) Se me ocurrió el siguiente conjunto de requisitos:

  • el usuario todavía debe poder acercarse
  • el tamaño de fuente debe permanecer igual
  • No hay flashes de diferentes estilos temporales.
  • sin requisito de jQuery
  • debe funcionar en el nuevo iOS y no obstaculizar ninguna otra combinación de SO / dispositivo
  • si es posible, no hay tiempos de espera mágicos, y si es necesario borrar 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 eventos focusIn significa que requiere al menos iOS 5.1 (pero veo que los sitios que construimos funcionan en versiones de iOS anteriores a 9 como un bono genial de todos modos)
  • Uso de la delegación de eventos porque muchos de los sitios en los que trabajo tienen páginas que podrían crear controles de formulario dinámicamente
  • Configuración de los EventListeners en el elemento html (documentElement) para no tener que esperar a que el cuerpo esté disponible (no quiero molestar en comprobar si el documento está listo / cargado o tener que esperar el evento DOMContentLoaded)

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

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

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

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

Y volver 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 focus, que lo cambió a 16px y no solucionó el problema del zoom con iOS8. Al menos en mi iPhone con iOS8, el tamaño de fuente debe ser 16px antes de enfocarse para que el iPhone no haga zoom en la página.


Como el acercamiento automático (sin alejamiento) sigue siendo una anulación en el iPhone, aquí hay un JavaScript basado en la sugerencia de dlo que funciona con enfoque / desenfoque.

El zoom se desactiva tan pronto como la entrada de texto se enfoca y se vuelve a activar cuando se deja la entrada.

Nota: ¡ Algunos usuarios pueden no aceptar la edición de textos en una entrada de texto pequeña! Por lo tanto, personalmente prefiero cambiar el tamaño del texto de la entrada durante la edición (ver 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 enfoque. Por lo tanto, el iPhone no hará zoom automáticamente.

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

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

Si su sitio web está diseñado adecuadamente para un dispositivo móvil, podría 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 que su página o formulario móvil va a 'flotar' alrededor.


Agregue user-scalable = 0 a viewport meta como sigue

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

Trabajó para mi :)


Puede evitar que Safari se acerque automáticamente a los campos de texto durante la entrada del usuario sin desactivar la capacidad del usuario para pellizcar el zoom. Solo agregue maximum-scale=1 pero deje de lado 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" alrededor si se amplía, lo que puede hacer que elementos importantes de la interfaz de usuario se muevan fuera de la pantalla.

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


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


En Angular, puede usar directivas para evitar que el zoom se enfoque en los dispositivos IOS. No hay etiqueta meta para preservar la accesibilidad.

import { Directive, ElementRef, HostListener } from '@angular/core';

const MINIMAL_FONT_SIZE_BEFORE_ZOOMING_IN_PX = 16;

@Directive({ selector: '[noZoomiOS]' })

export class NoZoomiOSDirective {
  constructor(private el: ElementRef) {}

@HostListener('focus')
  onFocus() {
    this.setFontSize('');
  }

@HostListener('mousedown')
  onMouseDown() {
    this.setFontSize(`${MINIMAL_FONT_SIZE_BEFORE_ZOOMING_IN_PX}px`);
  }

private setFontSize(size: string) {
  const { fontSize: currentInputFontSize } = window.getComputedStyle(this.el.nativeElement, null);

  if (MINIMAL_FONT_SIZE_BEFORE_ZOOMING_IN_PX <= +currentInputFontSize.match(/\d+/)) {
      return;
   }

  const iOS = navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform);
  iOS 
     && (this.el.nativeElement.style.fontSize = size);
 }
}

Puedes usarlo así <input noZoomiOS >después de declararlo en tu*.module.ts


¡¡¡ES TRABAJO!!! ¡TERMINO MI VIAJE DE BÚSQUEDA!

<meta name="viewport" content="width=640px, initial-scale=.5, maximum-scale=.5" />

Probado en iPhone OS6 , Android 2.3.3 Emulator

Tengo un sitio web móvil que tiene un ancho fijo de 640px, y me enfrenté al autozoom en foco.

¡Estaba intentando un montón de slutions pero ninguna funcionaba tanto en iPhone como en Android!

Ahora, para mí, está bien desactivar el zoom porque el sitio web fue el primer diseño móvil.

aquí es donde lo encuentro: ¿Cómo hacer el tamaño y la escala de las vistas para la compatibilidad con varios navegadores?


Establecer un tamaño de fuente (para los campos de entrada) igual al tamaño de fuente del cuerpo, parece ser lo que impide que el navegador se acerque o hacia dentro. Yo sugeriría usar font-size: 1rem como una solución más elegante.


Basado en la respuesta de Stephen Walsh ... Este código funciona sin cambiar el tamaño de fuente de las entradas en el foco (que parece poco convincente), y además funciona con FastClick , que sugiero agregar a todos los sitios móviles para ayudar a llevar el "rápido". Ajuste el "ancho de la ventana gráfica" para que se adapte a 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)
    });

Se me ocurrió una solución bastante ingenua, pero parece funcionar. Mi objetivo era evitar que los dobles toques accidentales se interpretaran como acercar, mientras mantuve pellizcado para hacer zoom para el acceso.

La idea es medir el tiempo entre el primer touchstart y el segundo touchend en un doble toque y luego interpretar el último touchend y hacer clic si el retraso es demasiado pequeño. Mientras se evita el zoom accidental, este método parece mantener el desplazamiento de la lista no afectado, lo cual es bueno. Sin embargo, no estoy seguro si no me he perdido nada.

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

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

Inspirado por una esencia de mutewinter y la respuesta de Joseph .





html iphone zoom mobile-safari html-input