私は<input>
とtype="text"
タグを持つHTMLページを作りました。 iPhoneのSafariを使ってクリックすると、ページが大きくなります(オートズーム)。誰もこれを無効にする方法を知っていますか?
Font-sizeが16px
より小さく、フォーム要素のデフォルトのfont-sizeが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;
}
上記すべてを使用する必要はありません。必要な要素をスタイルすることができます。例:just text
、number
、およびtextarea
input[type='text'],
input[type='number'],
textarea {
font-size: 16px;
}
入力要素を親スタイルから継承させるための代替解決策:
body {
font-size: 16px;
}
input[type="text"] {
font-size: inherit;
}
@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;
}
}
IOSはselectに背景を追加しないので背景を追加しました。
ユーザー入力中にSafariがテキストフィールドを自動的にズームインしないようにすることができますwithoutユーザーがズームをピンチする機能を無効にします。 maximum-scale=1
を追加するだけで、他の回答で提案されているユーザースケール属性は省略します。
ズームした場合に「浮かぶ」レイヤーのフォームがある場合、これは価値のあるオプションです。これにより、重要なUI要素が画面外に移動する可能性があります。
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
あなたのウェブサイトがモバイル機器用に適切に設計されているならば、あなたはスケーリングを許可しないことを決定することができます。
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
これはあなたのモバイルページやフォームが「浮遊」するという問題を解決します。
要約すると、答えは:フォーム要素のフォントサイズを最低16pxに設定することです。
input[type='text'],textarea {font-size:1em;}
この問題を解決する適切な方法は、メタビューポートを次のように変更することです。
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/>
私が見つけることができるきれいな方法はありませんが、これはハックです...
1)マウスオーバーイベントはズームの前に発生しますが、ズームはマウスダウンイベントまたはフォーカスイベントの前に発生します。
2)Javascriptを使ってMETAビューポートタグを動的に変更することができます( Javascriptを使ってiPhoneサファリのズームを有効/無効にする /を参照)。
だから、これを試してみてください(コンパクトさのために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" />');
}
これは間違いなくハックです...マウスオーバー/ダウンが必ずしもエントリ/終了をキャッチしない状況があるかもしれませんが、それは私のテストでうまくいったし、しっかりしたスタートです。
私は最近(今日:D)、この行動を統合しなければなりませんでした。コンボを含む元のデザイン分野に影響を与えないために、私は分野の焦点に変換を適用することを選びました:
input[type="text"]:focus, input[type="password"]:focus,
textarea:focus, select:focus {
font-size: 16px;
}
次のように user-scalable = 0 をビューポートメタに追加します。
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">
私のために働きました:)
これは@dloの回答に基づいていますが、マウスオーバーイベントとマウスアウトイベントはtouchstartイベントとtouchendイベントに置き換えられています。基本的にこのスクリプトはズーミングを防ぐためにズームが再び有効になる前に0.5秒のタイムアウトを追加します。
$("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" />');
}
私は上記のクリスティーナの解決策を使用しましたが、ブートストラップのための小さな修正とデスクトップコンピュータに適用するための別の規則があります。ブートストラップのデフォルトのfont-sizeは14pxなので、ズームが行われます。以下は、ブートストラップの「フォームコントロール」の16pxに変更して、ズームを防ぎます。
@media screen and (-webkit-min-device-pixel-ratio:0) {
.form-control {
font-size: 16px;
}
}
モバイル以外のブラウザの場合は14pxに戻ります。
@media (min-width: 768px) {
.form-control {
font-size: 14px;
}
}
.form-control:focusを使ってみましたが、フォーカスを16pxに変更していて、iOS8でのズームの問題は修正されていませんでした。少なくともiOS8を使用している私のiPhoneでは、iPhoneがページをズームしないようにするには、フォントサイズをフォーカスする前に16pxにする必要があります。
これも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
フォントサイズでデザインが崩れる場合は、インタフェース内の他の要素を調整する必要があるかもしれません。
これは私のために働いた:
input, textarea {
font-size: initial;
}
しばらくしてから私はこの解決策を思い付きました
// 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ピクセルに設定します。これはズーミングを防ぎます。フォーカスイベント時にフォントサイズを初期値に戻します。
以前に投稿されたソリューションとは異なり、これはあなたが望むものに入力のフォントサイズを設定させるでしょう。
ちなみに Bootstrap を使えば、この変種を使うことができます。
.form-control {
font-size: 16px;
}
ここでほとんど一行を読んでさまざまな解決策をテストした後、これは、解決策を共有したすべての人々のおかげで、私が思い付いたこと、テストし、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;}
}
ただし、「ホバー」状態と「フォーカス」状態の間でフォントサイズがすばやく変更されるため、顕著な「ジャンプ」とパフォーマンスへの再描画の影響があります。
本体のフォントサイズに等しいフォントサイズ(入力フィールド用)を設定すると、ブラウザがズームアウトまたはズームインできなくなります。より洗練された解決策として、font-size: 1rem
を使用することをお勧めします。
私はオランダ大学のWebサイト(フォームコントロールに15pxを使用していた)のフォームコントロールへのオートズームの問題を "修正"しなければならなかった。私は以下の一連の要件を思いついた。
これが私がこれまでに思いついたものです:
/*
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);
}
}
いくつかのメモ:
:focus
のような擬似要素は、以前のようには動作しません。 iOS 11から、あなたのメインスタイルの前に簡単なリセット宣言を追加することができます(あなたがより小さいフォントサイズでそれらをオーバーライドしない限り)。
/* Prevent zoom */
select, input, textarea {
font-size: 16px;
}
Tachyons.cssなどのCSSライブラリの場合は、フォントサイズを誤って上書きするのは簡単です。
例えば、class:f5
は:fontSize: 1rem
と同等です。ボディフォントのスケールをデフォルトのままにしておけば問題ありません。
ただし、フォントサイズクラスf6
を選択した場合、これは小さいディスプレイの上ではfontSize: .875rem
と同等になります。その場合、リセット宣言についてより具体的にする必要があります。
/* Prevent zoom */
select, input, textarea {
font-size: 16px!important;
}
@media screen and (min-width: 30em) {
/* not small */
}
私は、ここの人々がJavaScriptまたはビューポート機能を使って奇妙なことをしていて、手動でズームをすべてオフにしているのを見ています。それは私の意見では解決策ではないはずです。このCSSスニペットを追加すると、フォントサイズを16pxなどの固定数に変更せずに、iOSのオートズームがオフになります。
デフォルトでは、入力フィールドに93.8%(15px)のフォントサイズを使用していますが、CSSスニペットを追加することで93.8%のままです。 16pxに変更したり、それを固定数にする必要はありません。
input[type="text"]:focus,
textarea:focus {
-webkit-text-size-adjust: 100%;
}
自動ズームイン(ズームアウトなし)は依然としてiPhone上では厄介なので、フォーカス/ぼかしを使ったdloの提案に基づくJavaScriptです。
入力が残っているときにテキスト入力がfucusedされ再び有効にされるとすぐにズームは無効になります。
注: 一部のユーザーは、小さなテキスト入力でテキストの編集を心配しないかもしれません。したがって、私は個人的には編集中に入力のテキストサイズを変更することを好みます(下記のコードを参照)。
<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>
単純にフォントサイズを16pxに設定する代わりに、次のことができます。
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%;
}
12pxのテキストがあるように見えますが、入力フィールドは16pxの論理フォントサイズになります。
私はもう少し詳しく説明するブログ記事を持っています、そしてこの例を表示可能なHTMLとして持っています:
iPhoneのSafariで入力ズームがない、ピクセル完璧な方法
Font-sizeを16pxに設定することについてのトップの回答に対するコメントは、それがどのように解決策であるか、より大きな/より小さなフォントが必要な場合はどうなるかを尋ねました。
私はあなた全員については知りませんが、フォントサイズにpxを使うのは最善の方法ではないので、emを使うべきです。
私は私のテキストフィールドが16ピクセルより大きい私のレスポンシブサイトでこの問題に遭遇しました。フォームコンテナを2remに設定し、入力フィールドを1.4emに設定しました。モバイルクエリでは、ビューポートに応じてHTMLのフォントサイズを変更します。デフォルトのhtmlは10なので、私の入力フィールドはデスクトップで28pxになります。
オートズームを解除するには、入力を1.6emに変更する必要がありました。これは私のフォントサイズを32pxに増やしました。少しだけ高く、ほとんど目立ちません。私のiPhone 4と5では、私はhtmlのフォントサイズを縦向きに15pxに、横向きに10pxに変更しました。それは私が1.4em(42px)から1.6em(48px)に変更した理由であるそのピクセルサイズのためのスイートスポットが48pxであったように見えます。
あなたがする必要があることはfont-sizeのスイートスポットを見つけてそれからあなたのrem/emサイズにそれを逆に変換することです。
これが私のプロジェクトのひとつで使ったハックです。
select {
font-size: 2.6rem; // 1rem = 10px
...
transform-Origin: ... ...;
transform: scale(0.5) ...;
}
私が望んでいた初期のスタイルとスケールで終わりましたが、焦点のズームはありませんでした。
Stephen Walshの答えに基づく ...このコードは、フォーカスのある入力のフォントサイズを変更せずに動作し(これは不自然に見えます)、さらに 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)
});
他の多くの答えがすでに指摘しているように、これはmaximum-scale
をメタviewport
タグに追加することで実現できます。ただし、 これはAndroidデバイスのユーザーズームを無効にするというマイナスの結果になります 。 ( v10以降、iOSデバイスのユーザーズームは無効になりません 。)
デバイスがiOSの場合、JavaScriptを使用して、maximum-scale
をメタviewport
に動的に追加できます。これにより、両方の世界で最高の結果が得られます。ユーザーがズームおよびして、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) {
const content = el.getAttribute('content');
const newContent = [content, 'maximum-scale=1.0'].join(', ');
el.setAttribute('content', newContent);
}
};
const disableIosTextFieldZoom = addMaximumScaleToMetaViewport;
// https://stackoverflow.com/questions/9038625/detect-if-device-is-ios/9039885#9039885
const checkIsIOS = () =>
/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
if (checkIsIOS()) {
disableIosTextFieldZoom();
}
Angularでは、ディレクティブを使用してIOSデバイスへのフォーカスのズーミングを防ぐことができます。アクセシビリティを維持するためのメタタグはありません。
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);
}
}
<input noZoomiOS >
で宣言した後は、この*.module.ts
のように使用できます。
それを見つけるのにはしばらく時間がかかりましたが、これが私が見つけた最高のコードです...... 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));
});
この回答でも、wtfが実行されていることを把握するのに3日かかり、将来的に解決策が必要になる可能性があるため、$ 2.02を投入します。
私の状況は、説明した状況とわずかに異なっていました。
私の場合、ページのdivにコンテンツ編集可能なテキストがありました。ユーザーがDIFFERENT div、並べ替えボタンをクリックすると、contenteditable div(以前に保存およびクリアされた選択範囲)内のテキストを自動的に選択し、その選択に対してリッチテキストexecCommandを実行し、再度クリアしました。
これにより、ページ上の他の場所でのカラーdivとのユーザーインタラクションに基づいて、目に見えないようにテキストの色を変更できるようになりました。
さて、iPadのSafariでは、色のdivをクリックすると、画面上のキーボードが表示され、それを防ぐことはできませんでした。
私はついにiPadがこれをどのように行っているかを理解した。
編集可能なテキストの選択をトリガーするタッチスタートとタッチエンドのシーケンスをリッスンします。
その組み合わせが発生すると、画面キーボードが表示されます。
そのため、私が使用した解決策は、特定のカラーdivでタッチスタートとタッチエンドの両方をインターセプトすることでした。両方のハンドラーで、伝播とバブリングを停止し、falseを返します。しかし、touchendイベントでは、クリックがトリガーしたのと同じ動作をトリガーします。
そのため、以前は、Safariが「タッチスタート」、「マウスダウン」、「タッチエンド」、「マウスアップ」、「クリック」と考えていたものをトリガーしていました。
インターセプトのための新しいシーケンスは、単にテキストを選択することです。 Safariがそれを処理し、キーボード操作を行う前に、他のすべてがインターセプトされます。 touchstartおよびtouchendインターセプトは、マウスイベントもトリガーしないようにします。コンテキストでは、これはまったく問題ありません。
これを簡単に説明する方法はわかりませんが、問題に最初に遭遇してから1時間以内にこのスレッドを見つけたので、ここにあることが重要だと思います。
同じ修正が入力ボックスやその他すべてで機能することを98%確信しています。タッチイベントをインターセプトし、それらを伝播またはバブルさせずに個別に処理し、Safariがキーボードトリガーとしてシーケンスを認識しないようにするために、小さなタイムアウト後に選択を行うことを検討します。
それを動作させるためにJavascriptやハックを使わないでください。それはあなたのWeb上のプロジェクトのスコアに影響します。
これでうまくいくでしょう:
input, input:active, input:focus, input:focus-within, input:hover, input:visited {
font-size: 16px!important;
}