Вимкнути автоматичне збільшення тегу "Текст" - Safari на iPhone


539

Я створив HTML-сторінку, на якій є <input>тег type="text". Коли я натискаю на нього за допомогою Safari на iPhone, сторінка стає більшою (автоматичне збільшення). Хтось знає, як це відключити?


8
Для всіх користувачів Twitter Bootstrap, які прибувають тут: дивіться також цю проблему Github .
Єроен

7
Я думаю, що відповідь @daxmacrog відповідає точно тому, що ти хочеш, чи ти готовий прийняти це, щоб він міг піднятися до вершини і врятувати багато переробку від людей, які читають все це? Відповідь 2018 року: stackoverflow.com/a/46254706/172651
Еволюція

@Evolve відповідь, про яку ви говорили, про функції перерв і функцій масштабування Android. Відповідь daxmacrog є хибною.
MH

4
Я клянусь, Apple створює ці антифункції просто для того, щоб возитися з нашими головами.
Андрій Костер

@AndrewKoster, я з вами згоден навіть зараз у 2020 році.
Ашок

Відповіді:


491

Браузер збільшуватиме масштаб, якщо розмір шрифту менший, 16pxа розмір шрифту за замовчуванням для елементів форми 11px(принаймні, у Chrome та Safari).

Крім того, до цього selectелемента слід focusприєднати псевдоклас.

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

Не обов'язково використовувати всі вище, ви можете просто стиль елементи вам потрібно, наприклад: просто text, numberі textarea:

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

Альтернативне рішення, щоб вхідні елементи успадкували від батьківського стилю:

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

81
Тільки щоб все охопити: 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 Вам потрібно використовувати select:focus. Мав те саме питання.
DGibbs

141
Я не розумію, як це виправити? Що робити, якщо я хочу менший / більший розмір шрифту?
Брайан

47
належним чином - змінити метатег на: <meta name = "viewport" content = "width = ширина пристрою, початковий масштаб = 1, максимальний масштаб = 1, масштабування користувача = 0" />
Milos Matic

37
@MilosMatic У більшості випадків, мабуть, не дуже вдале рішення, оскільки воно повністю заважає користувачеві масштабувати сторінку. Потенційно ще більше дратує ваших відвідувачів.
BadHorsie

361

Ви можете запобігти автоматичному збільшенню текстових полів Safari під час введення користувача, не вимкнувши можливість користувача стискати зум. Просто додайте, maximum-scale=1але не залишайте атрибут масштабу користувача, запропонований в інших відповідях.

Важливий варіант, якщо у вас є форма в шарі, який "плаває" навколо, якщо збільшується, що може спричинити зміщення важливих елементів інтерфейсу з екрану.

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


65
Це рішення 2018+. Підвищити це так, як від цього залежить твоє життя.
Генрік Петтерсон

17
Це призведе до порушення можливостей масштабування пристроїв для Android
fen1ksss

4
@daxmacrog, ви праві, але ОП не згадав, чи хоче він зламати андроїди, дозволяючи потрібну поведінку. Тут я особисто прийняв неправильний варіант. Звичайно, краще уточнити.
fen1ksss

13
@HenrikPetterson Це більше, ніж просто вимкнення автоматичного масштабування, як зазначено в ОП, а також вимикає прищепне збільшення. Тож я не думаю, що це рішення 2018+.
Андре Верланг

4
@ AndréWerlang Це не точно. Як чітко зазначено у відповіді, це рішення не вимикає прискорене збільшення Safari (або Firefox), про що запитувала ОП. Але, як вказувалося в попередніх коментарях, це забороняє масштабування користувачів на пристроях Android та Chrome в iOS.
daxmacrog

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

Нове: IOS продовжує масштабувати, якщо ви не використовуєте 16 пікселів на вході без фокуса.

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

Я додав фон, оскільки IOS не додає фонового режиму для вибору.


9
Це працює не тільки для сафарі на iOS (iphone / ipad / ipod), але і Safari / OSX та Chrome (Windows та Mac). Тож якщо ви намагаєтеся конкретно націлити на iphone, це не вийде.
Редтопія

31
Чому всі кажуть 16px, але ніхто не зважає згадувати, чому саме це 16px? Чому таке довільне число? Чому ми маємо встановити розмір тексту поля у форматі 16 пікселів, а не .. скажімо, 1,8rem чи 2,5em чи таке? Це просто дурна помилка з власною ОС?
Beebee

14
@Beebee 100% розмір шрифту - 16 пікселів, що за замовчуванням для більшості, якщо не для всіх браузерів (також для робочого столу). IOS використовує це як за замовчуванням, мабуть, тому, що це зручний розмір для читання. Чому це встановлено таким чином, я не намагався шукати, не байдуже.
Крістіна

5
Використовуйте @media screen and (-webkit-min-device-pixel-ratio:0) and (max-device-width:1024px)для обмеження ефекту на iPhone, але не змінюйте веб-сайти під час перегляду в Chrome.
BurninLeo

9
Замість використання медіа-запиту слід використовувати @supports (-webkit-overflow-scrolling: touch), оскільки ця функція css існує лише в iOS
Джеймс Моран,

189

Якщо ваш веб-сайт розроблений належним чином для мобільного пристрою, ви можете вирішити забороняти масштабування.

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

Це вирішує проблему, що ваша мобільна сторінка або форма збирається "плавати" навколо.


123
Технічно правильно, але я не згоден з міркуваннями. Вимкнення масштабування користувачів на правильно розробленому сайті, як правило, все ще погана ідея.
Фер

20
"Правильно розроблений" є дуже суб'єктивним. Розгляньте фіксований 50px заголовок у верхній частині веб-сайту, який повністю реагує і повинен працювати у всіх браузерах. Масштабування iOS Safari порушує позиціонування заголовка і значно розбиває весь сайт.
Редтопія

62
Відключення можливостей масштабування користувачів - жахлива практика з точки зору UX, і його потрібно уникати будь-якою ціною. Можливість вільного збільшення - це основна функція доступності та контроль, який ви ніколи не повинні відбирати у користувача.
Габріель Лутьє

72
У вітчизняних мобільних додатках ви ніколи не отримуєте шансу на збільшення, і вони спрацьовують прекрасно, чому б webapp відрізнявся? Якщо ви встановите відповідний розмір шрифту та висоту рядка з чіткими контрастами, у вас повинно бути добре.
jotav

39
Ті, хто використовує аргумент "це добре в рідних додатках", не помічають факту, що добре створені натурні програми дотримуються налаштувань доступності на рівні ОС, таких як розмір тексту. Користувачі похилого віку та погано бачать користувачі можуть і користуватися надзвичайно великими розмірами шрифтів на всій ОС, тому що їм це потрібно . Веб-додатки часто не можуть або не можуть дотримуватися цього параметра, тому дозволити вбудовану функціональність доступності веб-браузера, наприклад масштабування, життєво важливим. Що б ви думали, це ідеально читабельно, повірте, є люди, які не вважають це досить зрозумілим. Ви НЕ приймати цей параметр від користувачів , якщо ви цінуєте зручність і простоту використання.
Райан Вільямс

72

Підсумовуючи відповідь, слід встановити розмір шрифту елементів форми принаймні 16 пікселів


Так, це, безумовно, найкраща практика, щоб уникнути масштабування на мобільних пристроях. Ні js, ні хакі, ні обхідні шляхи взагалі. Але навіть з 16 пікселями я помітив дуже мало масштабування сторінок, тому я спробував 17 пікселів, 18 пікселів ... щоб побачити, що відбувається.
ed1nh0

8
Найкраще задекларувати 100% оголошення на тілі, кнопці, введенні, текстовій області та виділенні елементів. Це дозволяє користувачеві встановити типовий параметр, який не є 16px, що постачається разом із браузерами. Хтось, хто має проблеми з читанням на екрані, може встановити за замовчуванням 18 пікселів або 20 пікселів. Ви не хочете, щоб перекривати їх вибір, натискаючи на них 16 пікселів. Що ж стосується iOS, то вони прийняли рішення збільшити масштаб будь-якого значення, яке, за їхніми HIG, вважає, занадто мало. На жаль, схоже, що він не інтерпретує 100% -ве значення, тому ми затримуємося, додаючи за замовчуванням, щоб його заспокоїти.
Дж. Хоґе

RE iOS Safari, оскільки в цьому коментарі виявляється, що Safari правильно інтерпретує font-size: 100%значення і захоплює необхідну 16 пікселів.
Натан Лафферті

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

3
Зауважте, що встановлення масштабування користувача на "ні" відключить усе масштабування, що, мабуть, є поганою ідеєю.
штурмовик

18
Це працює лише в тому випадку, якщо розмір шрифту вашого тіла за замовчуванням (не вказано, або 1emабо 100%). Якщо встановити нестандартний розмір шрифту, ви можете встановити його font-sizeу своєму фрагменті, 16pxщоб уникнути автоматичного масштабування.
Алан Х.

Я знаю, що це питання було спрямовано на iPhone, але це більш сумісно на будь-яких платформах, і в майбутньому більше платформ / пристроїв я спробував підхід 16px, але на планшеті Android лише зменшив ефект автоматичного збільшення. Встановлення "1em", як зазначено в публікації, вирішило проблему.
toddles_fp

3
Ні , 1emні 1remне є правильним рішенням , тому як може бути менше 16pxі Safari вимагає , по крайней мере , 16pxщоб не збільшити.
Finesse

2
Я використав рішення viewport, але воно не спрацювало, 16px рішення працює чудово, але 16px занадто велике для вхідної скриньки мого сайту, чи є якесь третє рішення
Suneth Kalhara

21

Правильним способом вирішити цю проблему є зміна метаполе перегляду на:

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


32
Це не обов'язково "правильний" спосіб запобігання такої поведінки. Mobile Safari збільшує масштаб, якщо текст вважається занадто малим для читання. Вимкнення масштабування все разом важко перешкоджає і не дозволяє користувачам взаємодіяти з вашою сторінкою так, як вони можуть очікувати.
AlecRust

3
Очевидно, в iOS10 Apple змінила властивість максимального масштабу, щоб її більше не дотримувались, дозволяючи всім веб-сайтам збільшувати масштаб незалежно від їх налаштувань.
Вольфр

3
Це працює для версії iOS10 20 / вересня 2016 року ... принаймні працює на моєму додатку ... Дякую !!! Перш ніж я використовував <meta name = "viewport" content = "width = ширина пристрою, початковий масштаб = 1, мінімальний масштаб = 1 , максимальний масштаб = 1"> Але я переключив його на рядок на відповідь і це спрацювало ...
eljamz

1
"Переконайтесь, що металевий елемент перегляду сторінки не блокує масштабування за допомогою піктограми браузера, щоб його можна було використовувати для збільшення сторінки до 200%. Слід уникати обмежувальних значень для атрибутів, що масштабуються користувачем та максимального масштабу цього метаелементу." w3.org/TR/mobile-accessibility-mapping/#zoom-magnification
danielnixon

Я бачив коментарі, як деякі з цих метатегів не працюють на iOS 10, і я знаю, що вищезазначене працює в Chrome для iOS як мінімум. :) Дякую!
cbloss793

16

Я не можу знайти чистий спосіб, але ось хак ...

1) Я помітив, що подія переміщення миші відбувається перед збільшенням, але збільшення відбувається перед подіями в режимі миші або фокусування.

2) Ви можете динамічно змінювати тег вікна перегляду META за допомогою javascript (див. Увімкнути / вимкнути масштабування на iPhone safari за допомогою Javascript? )

Отже, спробуйте це (показано в jquery для компактності):

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

Це, безумовно, хак ... можуть бути ситуації, коли миші / вниз не завжди ловлять записи / виходи, але це добре працювало в моїх тестах і є надійним початком.


5
Не впевнений, коли поведінка Safari могло змінитися, але зараз (iOS6.0.1) mousedown відбувається до початку автоматичного зуму. Таким чином, у моєму попередньому рішенні масштабування буде відновлено занадто рано. Я не знайшов адекватного виправлення, оскільки всі події, які я намагався зараз, відбуваються перед збільшенням. Ви можете повторно ввімкнути масштабування при натисканні клавіші або розмитті, але є деякі сценарії, які можуть пропустити (наприклад, якщо користувач хоче вручну збільшити масштаб, перш ніж починати щось вводити).
dlo

14

Нещодавно (сьогодні: D) довелося інтегрувати цю поведінку. Щоб не впливати на оригінальні поля дизайну, включаючи комбіновані, я вирішив застосувати перетворення у фокусі поля:

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

FYI, це добре працювало на моєму iphone 5 із iOS 6, але на iphone 4 із iOS 5 у портретному режимі фокусування було застосовано після збільшення масштабу. Можливо, щось тонке відбувається, я далі не досліджував.
Виш

Я просто хочу сказати, що у мене є безліч різних запитів, що використовують масштабування, щоб прискорити розвиток, і залежно від того, наскільки ви збільшите масштаб, визначаєте, який розмір шрифту вам потрібно, я вважаю
Майк

: фокус не працював для мене iOS 10.2 iPhone 6, але введення [type = "text"]: наведення курсора працює добре.
Amirhossein Rzd

14

Додайте користувацький масштаб = 0, щоб переглядати мета перегляду, як показано нижче

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

Для мене працювали :)


11
"Переконайтесь, що металевий елемент перегляду сторінки не блокує масштабування за допомогою піктограми браузера, щоб його можна було використовувати для збільшення сторінки до 200%. Слід уникати обмежувальних значень для атрибутів, що масштабуються користувачем та максимального масштабу цього метаелементу." w3.org/TR/mobile-accessibility-mapping/#zoom-magnification
danielnixon

9
Це порушує правила доступності, визначені W3.
Джошуа Рассел

працював для мене, також це найкраще рішення для мене, оскільки я хочу свободу змінювати розміри шрифту вводу нижче 16 пікселів і не хочу зламати JS
Blue Bot

13

Як уже було вказано на багато інших відповідей, цього можна досягти, додавши maximum-scaleметатег viewport. Однак це має негативний наслідок відключення масштабування користувачів на пристроях Android . ( Це не вимикає масштабування користувачів на пристроях iOS, починаючи з v10 .)

Ми можемо використовувати JavaScript для динамічного додавання maximum-scaleдо мета, viewportколи пристрій iOS. Це дозволяє досягти найкращого з обох світів: ми дозволяємо користувачеві збільшувати масштаб і запобігати збільшенню iOS в текстові поля у фокусі.

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

Код:

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? Це виключно з смислових причин?
Ферисон

Так, просто відображення функції на іншу назву, щоб було зрозуміло, як вона використовується.
Олівер Джозеф Еш

8

Hack Javascript, який працює на iOS 7. Це засновано на відповіді @dlo, але події миші та миші замінюються подіями touchstart та touchchend. В основному, цей сценарій додає півтора секунди час, перш ніж зум буде знову ввімкнено для запобігання збільшення.

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

Це працювало найкраще для мене. Але я змінив події touchstart / touchchend на одну подію "фокусування" як на zoomDisable, так і на zoomEnable.
Justin Cloud

Додавання затримки, здається, працює досить добре для нових версій iOS, але цікаво, що він працює не дуже добре, якщо встановлено 250 мс. Це натякає на те, що за певних обставин 500 мільйонів можуть також не працювати, але якщо це працює більшу частину часу, я думаю, що це краще, ніж взагалі не працювати. Гарне мислення.
dlo

7

Це працювало для мене:

input, textarea {
    font-size: initial;
}

Приємно просто, але чи можна контролювати, що таке "початковий" розмір?
2540625

Я цього не перевіряв, але це має бути спосіб контролювати розмір шрифту. (будь ласка, повідомте мене, якщо це працює, і я оновлю свою відповідь) body {font-size: 20px; } введення {font-size: nasledit; }

7

Я використовував рішення Крістіни вище, але з невеликою модифікацією для завантажувальної програми та іншим правилом, яке стосується настільних комп'ютерів. За замовчуванням розмір шрифту Bootstrap становить 14 пікселів, що викликає збільшення. Далі змінено його на 16 пікселів для "форм управління" у Bootstrap, запобігаючи збільшення.

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

І назад до 14 пікселів для немобільних браузерів.

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

Я спробував використовувати .form-control: focus, який залишив його на 14px, за винятком фокусу, який змінив його на 16px, і він не виправив проблему збільшення з iOS8. Принаймні на моєму iPhone, що використовує iOS8, розмір шрифту повинен бути 16 пікселів, перш ніж фокус для iPhone не збільшувати сторінку.


6

Я це робив, також з 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'));
});

Звичайно, деякі інші елементи в інтерфейсі, можливо, доведеться адаптувати, якщо цей 16pxрозмір шрифту порушує дизайн.


4
Це класно. Це стилін '. Я поза каламбурами. Розумний підхід.
кройона

@Wolfr ви спробували на фактичному пристрої?
Nicolas Hoizey

1
Це працювало для нас на iOS 12. Мені подобається такий підхід найкраще замість того, щоб перебиратись із перетвореннями css та негативними полями.
анонімний-один

6

Через деякий час, намагаючись, я придумав це рішення

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

У режимі "mousedown" він встановлює розмір шрифту вводу 16 пікселів. Це запобіжить збільшення масштабу. У фокусі події він змінює розмір шрифту до початкового значення.

На відміну від рішень, розміщених раніше, це дозволить вам встановити розмір шрифту вхідного тексту на все, що завгодно.


Цей фактично працює для мене, тим більше, що в нових версіях iOS ви не можете використовувати метатег перегляду vidport для відключення масштабування.
mparizeau

Підтверджено, що працює над iOS 12.1, дякую
Ziki

6

Прочитавши майже кожен рядок тут і випробувавши різні рішення, це, дякую всім, хто поділився своїми рішеннями, те, що я придумав, протестував і працював для мене на 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;}
}

Однак це має деякі мінуси, помітно «стрибок» внаслідок швидкої зміни розміру шрифту, що виникає між станами «наведення курсора» та «фокусом», - і перемальовує вплив на продуктивність


Дякую за відгук, @MikeBoutin. Чи можете ви поділитися своїм env (версія пристрою / iOS)?
l3bel

6

Натхненний відповіддю @jirikuchta, я вирішив цю проблему, додавши цей біт CSS:

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

Ні JS, і я не помічаю ні спалаху, ні чогось іншого.

Варто відзначити , що viewportз maximum-scale=1теж працює, але не тоді , коли сторінка завантажується в якості фрейма, або якщо у вас є якийсь - то інший сценарій , що змінюють viewportі т.д.


4

Псевдоелементи на кшталт :focusне працюють, як раніше. З iOS 11 перед вашими основними стилями можна додати просту декларацію про скидання (за умови, що ви не змінюєте їх меншим розміром шрифту).

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

Варто згадати, що для бібліотек CSS, таких як Tachyons.css, тоді легко випадково змінити розмір шрифту.

Наприклад клас: f5еквівалентно:fontSize: 1rem що добре, якщо ви зберегли масштаб шрифту тіла за замовчуванням.

Однак: якщо ви вибрали клас розміру шрифту: f6це буде еквівалентно fontSize: .875remна невеликому дисплеї вгору. У цьому випадку вам потрібно буде детальніше визначити свої декларації про скидання:


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

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

/* not small */

}

3

До речі, якщо ви використовуєте Bootstrap , ви можете просто використовувати такий варіант:

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

3

Мені довелося «виправити» проблему автоматичного збільшення масштабів у формі контролю для веб-сайту Голландського університету (який використовував 15 пікселів для керування формою). Я придумав такий набір вимог:

  • Користувач повинен мати можливість збільшити масштаб
  • розмір шрифту повинен залишатися однаковим
  • відсутність спалахів тимчасової різної стилізації
  • немає вимоги jQuery
  • повинен працювати на новітній iOS і не перешкоджати будь-якій іншій комбінації ОС / пристроїв
  • по можливості немає магічних тайм-аутів, а при необхідності правильно очистіть таймери

Ось що я придумав поки що:

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

Деякі примітки:

  • Зауважте, що поки що я тестував його лише на iOS 11.3.1, але незабаром протестую його на кількох інших версіях
  • Використання подій focusIn означає, що для цього потрібно як мінімум iOS 5.1 (але я бачу, що сайти, які ми створюємо, працюють у версіях iOS, старші 9 років, як класний бонус)
  • Використання делегування подій, оскільки на багатьох сайтах, над якими я працюю, є сторінки, які можуть динамічно створювати елементи управління формами
  • Встановлення EventListeners на html-елемент (documentElement), щоб не потрібно чекати, коли тіло стане доступним (не хочуть турбуватися, перевіряючи, чи має документ готовий / завантажений стан чи потрібно чекати події DOMContentLoaded)

3

Замість того, щоб просто встановити розмір шрифту на 16 пікселів, ви можете:

  1. Складіть поле введення так, щоб воно було більшим за його передбачуваний розмір, що дозволяє встановити розмір логічного шрифту на 16 пікселів.
  2. Використовуйте scale()перетворення CSS та негативні поля, щоб зменшити поле введення до потрібного розміру.

Наприклад, припустимо, що ваше поле введення спочатку оформлено за допомогою:

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

Якщо ви збільшите поле, збільшивши всі розміри на 16/12 = 133,33%, а потім зменшіть, використовуючи scale()на 12/16 = 75%, поле введення матиме правильний розмір візуалу (і розмір шрифту), і масштабування не буде фокус.

Оскільки scale()впливає лише на візуальний розмір, вам також потрібно буде додати негативні поля для зменшення логічного розміру поля.

За допомогою цього 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%;
}

поле для введення буде мати логічний розмір шрифту 16 пікселів, але, здається, має текст 12 пікселів.

У мене є повідомлення в блозі, де я детальніше розглядаю деталі, і цей приклад є видимим HTML:
Немає масштабування введення Safari на iPhone, ідеальний спосіб пікселів


3

Навіть з цими відповідями мені знадобилося три дні, щоб зрозуміти, що відбувається, і мені, можливо, буде потрібно рішення знову в майбутньому.

Моя ситуація трохи відрізнялася від описаної.

У моєму, я мав якийсь змістовний текст у діві на сторінці. Коли користувач натиснув кнопку РІЗНИЙ div, кнопку сортування, я автоматично відібрав деякий текст у довідковому розділі (діапазон вибору, який раніше був збережений та очищений), запустив у цьому виді вибраний текстовий файл execCommand та очистив його знову.

Це дозволило мені непомітно змінювати кольори тексту на основі взаємодії користувачів з кольоровими диваками в інших місцях сторінки, зберігаючи вибір звичайно прихованим, щоб вони могли бачити кольори у відповідному контексті.

Що ж, на Safari iPad, натискання кольорового поділу призвело до появи екранної клавіатури, і нічого, що я зробив, це не завадило б.

Нарешті я зрозумів, як це робить iPad.

Він слухає послідовність дотику та сенсорної послідовності, яка запускає вибір редагованого тексту.

Коли ця комбінація трапляється, вона показує екранну клавіатуру.

Насправді це робить кульовий масштаб там, де він розширює основну сторінку під час збільшення тексту, що редагується. Минув мені день, щоб зрозуміти, що я бачу.

Тому рішення, яке я використав, було перехоплювати як сенсорний запуск, так і торкатися цих кольорових дивок. В обох обробниках я припиняю розповсюдження та барботаж та повертаю помилкові. Але в події touchend я викликаю ту саму поведінку, що і натискання натискання.

Отже, раніше Сафарі викликав те, що, на мою думку, було "сенсорним", "мюседоун", "дотиком", "мишею", "клацанням", і через мій код - вибір тексту в тому порядку.

Нова послідовність через перехоплення - це просто вибір тексту. Все інше перехоплюється до того, як Safari зможе обробити його та виконати його роботи з клавіатури. Перехоплення сенсорним запуском і дотиком запобігає запусканню подій миші, і в контексті це абсолютно добре.

Я не знаю простішого способу описати це, але я думаю, що важливо мати його тут, тому що я знайшов цю тему протягом години після першої зустрічі з проблемою.

Я на 98% впевнений, що те саме виправлення працюватиме з полями введення та будь-чим іншим. Перехоплюйте сенсорні події та обробляйте їх окремо, не даючи їм розповсюджуватися або міхуру, і подумайте робити якісь вибори після невеликого тайм-ауту, щоб переконатися, що Safari не визнає послідовність як тригера клавіатури.


Це чудове пояснення того, чим займається сафарі. Дякую!
Джеремі

2

Я бачу, як люди тут роблять якісь дивні речі з JavaScript або функцією перегляду і вимикають усе масштабування вручну на пристроях. На мою думку, це не повинно бути рішенням. Якщо додати цей фрагмент CSS, вимкніть автоматичне збільшення iOS, не змінюючи розмір шрифту на фіксовану цифру, наприклад, 16 пікселів.

За замовчуванням я використовую розмір шрифту 93,8% (15 пікселів) у полях введення, а додаючи мій фрагмент CSS цей показник залишається на рівні 93,8%. Не потрібно змінювати 16px або робити це фіксованим номером.

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

5
Це не працює для мене, протестовано як з останніми iOS 6, так і з iOS 9.2.1. Ось мінімально відтворена сторінка: pastebin.com/bh5Zhe9h Вона все ще збільшує фокус. Дивно, що це було розміщено у 2015 році та оновлено, але не працює в iOS 6.
Олександр Дієло

2

Встановлення розміру шрифту (для полів введення), рівного розміру шрифту тіла, здається, є тим, що заважає браузерові зменшувати чи зменшувати. Я б запропонував використовувати його font-size: 1remяк більш елегантне рішення.


1

Оскільки автоматичне збільшення (без збільшення) все ще анонімне на iPhone, ось JavaScript заснований на пропозиції dlo, що працює з фокусом / розмиттям.

Масштабування вимикається, як тільки введення тексту вимикається та повторно вмикається, коли вхід залишиться.

Примітка. Деякі користувачі можуть не цінувати редагування текстів невеликим введенням тексту! Тому я особисто вважаю за краще змінювати розмір тексту введення під час редагування (див. Код нижче).

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

Наступний код змінить розмір тексту вводу на 16 пікселів (обчислюється, тобто, в поточному розмірі масштабу) під час елемента, що має фокус. Тому iPhone не автоматично збільшує масштаб.

Примітка. Коефіцієнт масштабування обчислюється на основі екрана window.innerWidth та дисплея iPhone із 320 пікселів. Це дійсно лише для iPhone у портретному режимі.

<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

Знадобилося трохи часу, щоб знайти його, але ось найкращий код, який я знайшов ...... 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

На основі відповіді Стівена Уолша ... Цей код працює без зміни розміру шрифту входів на фокус (який виглядає кульгавим), плюс він все ще працює з FastClick , який я пропоную додати до всіх мобільних сайтів, щоб допомогти залучити "спритний". Відрегулюйте "ширину перегляду" відповідно до ваших потреб.

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

Якщо користувач уже трохи збільшив масштаб перед тим, як натиснути на елемент керування входом, чи призведе це рішення до того, що огляд перегляду раптово "зніме масштаб"?
Бруно Торквато

Так, це так, але це виглядає не більше, ніж попередній ефект "збільшення", який відбувався кожного разу, коли користувач натискав на вхід.
Піт

1

У коментарі до головної відповіді щодо встановлення розміру шрифту на 16 пікселів запитували, як це рішення, а що, якщо ви хочете, щоб шрифт був більшим / меншим.

Я не знаю про вас усіх, але використання px для розміру шрифту - це не найкращий спосіб, ви повинні використовувати em.

Я зіткнувся з цим питанням на своєму чуйному сайті, де моє текстове поле перевищує 16 пікселів. У мене був встановлений контейнер форми на 2rem, а моє поле для введення 1,4em. У своїх мобільних запитах я змінюю розмір шрифту html залежно від вікна перегляду. Оскільки HTML за замовчуванням дорівнює 10, моє поле введення обчислюється до 28 пікселів на робочому столі

Щоб зняти автоматичне збільшення, мені довелося змінити вхід на 1.6ем. Це збільшило розмір мого шрифту до 32 пікселів. Просто трохи вище і ледь помітно. На своєму iPhone 4 і 5 я змінюю розмір шрифту HTML на 15 пікселів для портретного і назад на 10 пікс. Для пейзажу. Здається, що солодке місце для цього пікселя було 48 пікселів, тому я змінив з 1,4ем (42 пікселів) на 1,6ем (48 пікселів).

Що вам потрібно зробити, це знайти солодке місце за розміром шрифту, а потім перетворити його назад у ваші розміри rem / em.


1

Ось хак, який я використав для одного зі своїх проектів:

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

Закінчив початкові стилі та масштаби, які я хотів, але не збільшував фокус.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.