`<input type = number>`のスクロールを無効にする


121

入力数値フィールドの数値を変更するスクロールホイールを無効にすることはできますか?私はスピナーを削除するためにwebkit固有のCSSをいじりましたが、この動作を完全に取り除きたいと思います。type=numberiOSで素晴らしいキーボードが表示されるので、使用するのが好きです。


7
type = numberを使用する代わりに、入力タイプtel(type = "tel")を使用してください。iOS numキーボードをポップアップします。
Praveen Vijayan 2012年

中にonscrollハンドラーを追加するとどうevent.preventDefault()なりますか?
robertc

14
私の控えめな意見では、私はこれが機能であるべきだとは思っていません。ブラウザ開発で何か発言があったら、おそらくこの機能を削除するように強く勧めます。煩わしいだけで、実際に使ってくれる人は誰もいません。
カークランド

3
私は完全にあなたのカークランドに同意します。フォームを使用してページをスクロールしているのは単に悪いUXであり、数値入力要素がマウスの下に移動すると、数値が増加し始め、ページのスクロールが停止します。完全に見当識障害。
kjs3 2014年

3
@PraveenVijayan:これは回避策ですが、新しいhtml5入力タイプを使用する理由にはなりません。将来的には、電話で連絡先などから番号を選択できるようになる可能性があります。これを別の種類の番号にしようとすると、非常に奇妙に見えます。
2015

回答:


92

他の人が提案したようなinput-number要素でのマウスホイールイベントのデフォルトの動作を防止します(「blur()」を呼び出すのは、ユーザーが望むものではないため、通常は推奨される方法ではありません)。

だが。すべてのinput-number要素でマウスホイールイベントを常にリッスンすることは避け、要素がフォーカスされているとき(つまり、問題が存在するとき)だけそれを実行します。それ以外場合、マウスポインターがinput-number要素の上にある場合、ユーザーはページをスクロールできません

jQueryのソリューション:

// disable mousewheel on a input number field when in focus
// (to prevent Cromium browsers change the value when scrolling)
$('form').on('focus', 'input[type=number]', function (e) {
  $(this).on('wheel.disableScroll', function (e) {
    e.preventDefault()
  })
})
$('form').on('blur', 'input[type=number]', function (e) {
  $(this).off('wheel.disableScroll')
})

(フォーカスイベントを周囲のフォーム要素に委譲します-パフォーマンスに悪影響を与える多くのイベントリスナーを回避します。)


2
すばらしい答えです。今日これを行っている場合、Modernizr.touchを使用して、非タッチデバイスに条件付きでイベントリスナーを適用すると思います。基本的にuser2863715は以下のように言っています。
kjs3 2014年

すばらしい答えですが、少なくともWebkitでは、カーソルが入力要素の上にあるときにウィンドウがスクロールするのを防ぎます。マウスホイールのイベントもバブルするはずだと思いました。
Ryan McGeary 2014年

要素がフォーカスされているときに無効化スクロール機能を要素に適用するだけで、マウスが入力要素上にあるときにスクロールが妨げられないはずです。ただし、要素にフォーカスがあるときに、ウィンドウがスクロールされなくなります。そして、はい、なぜ
マウスホイール

6
これは、そもそも存在してはならない動作に対する適切な修正です。
ジョニー

これは、ほとんどのUNIXタイプのプラットフォームgnome、osx、android(マウスを使用)では機能しません。スクロール動作では、入力にフォーカスする必要がないためです。あるいは、テキストタイプの入力を使用して、それに数値制限を加えただけです(上/下キーのショートカットはありませんが、jsで追加することもできます)
zeachco

40
$(document).on("wheel", "input[type=number]", function (e) {
    $(this).blur();
});

2
これは完璧なものです。
Patrik Laszlo、

それはうまくいきます。ありがとうございました。
Vijay S

20

それらすべてを支配する1つのイベントリスナー

これは純粋なjsでの@Simon Perepelitsa回答に似ていますが、ドキュメント要素に1つのイベントリスナーを配置し、フォーカスされた要素が数値入力であるかどうかをチェックするため、少し単純です。

document.addEventListener("wheel", function(event){
    if(document.activeElement.type === "number"){
        document.activeElement.blur();
    }
});

一部のフィールドで値のスクロール動作をオフにしたいが、他のフィールドではオフにしたくない場合は、代わりにこれを行います。

document.addEventListener("wheel", function(event){
    if(document.activeElement.type === "number" &&
       document.activeElement.classList.contains("noscroll"))
    {
        document.activeElement.blur();
    }
});

これとともに:

<input type="number" class="noscroll"/>

入力にnoscrollクラスがある場合、スクロール時に変更されません。それ以外の場合、すべてが同じままです。

JSFiddleでここでテストする


これは反対投票されているようです。問題がある場合は、反対票にもコメントを残してください。何かを逃した場合、それが何であるかを学びたいと思います。ありがとう。
Peter Rakmanyi

1
最新のブラウザでは、のwheel代わりにイベントを使用してくださいmousewheel。参照:developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event PS。反対票を投じたのは私ではありません。
VEE

19
input = document.getElementById("the_number_input")
input.addEventListener("mousewheel", function(event){ this.blur() })

http://jsfiddle.net/bQbDm/2/

jQueryの例とクロスブラウザソリューションについては、関連する質問を参照してください。

数値入力スクロール用のHTML5イベントリスナー-Chromeのみ


2
Seymonのおかげで、jQuery $(':input[type=number]' ).live('mousewheel',function(e){ $(this).blur(); });を使用してすべての数値入力に対してこの方法でなんとかできました。デフォルトを防止する代わりにぼかしを使用したので、ページのスクロールがブロックされません!
Thibaut Colson 2013

ぼかしについての素晴らしい追加、私はあなたがまだページスクロールを許可できることを知りませんでした。回答を更新しました。
Simon Perepelitsa 2013

13
FYI live()は非推奨です。今、あなたは使うべきですon()$(':input[type=number]').on('mousewheel',function(e){ $(this).blur(); });
Saeid Zebardast 2013年

3
@SaeidZebardastあなたのコメントは回答に値します
snumpy

最新のブラウザでは、のwheel代わりにイベントを使用してくださいmousewheel。参考:developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event
VEE

16

単にHTML onwheel属性を使用できます。

このオプションは、ページの他の要素のスクロールには影響しません。

そして、すべての入力のリスナーを追加すると、動的に作成された後の入力では機能しません。

さらに、CSSで入力矢印を削除できます。

input[type="number"]::-webkit-outer-spin-button, 
input[type="number"]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}
input[type="number"] {
    -moz-appearance: textfield;
}
<input type="number" onwheel="this.blur()" />


1
ありがとう兄貴!!Angular-Material 6
Nasiruddin Saiyedで


このCSSは多くのソースで見つけることができます。とにかく、CSSは単なるボーナスです。この質問に対する実際の解決策は、HTML onwheel属性です。;-)
Maikon Matheus

5
私はこの解決策が好きです!ありがとう。私の場合、これonBlur()は期待どおりではありませんでした。return false代わりに、本当に「ホイールで何もしない」ようにシンプルな設定をしました。 <input type="number" onwheel="return false;">
ダニエル

14

@Semyon Perepelitsa

これにはより良い解決策があります。ぼかしは入力からフォーカスを削除しますが、これは望ましくない副作用です。代わりにevt.preventDefaultを使用してください。これにより、ユーザーがスクロールしたときの入力のデフォルトの動作が妨げられます。これがコードです:

input = document.getElementById("the_number_input")
input.addEventListener("mousewheel", function(evt){ evt.preventDefault(); })

6
動作しますが、イベントはバブルしないため、ページはスクロールしません。ぼやけずにデフォルトの動作(ページスクロール)を維持する方法はありますか?
GuiGS 2014

最新のブラウザでは、のwheel代わりにイベントを使用してくださいmousewheel。参考:developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event
VEE

7

まず、次のいずれかの方法でマウスホイールイベントを停止する必要があります。

  1. それを無効にする mousewheel.disableScroll
  2. 傍受 e.preventDefault();
  3. 要素からフォーカスを削除することにより el.blur();

最初の2つの方法はどちらもウィンドウのスクロールを停止し、最後の方法は要素からフォーカスを削除します。どちらも望ましくない結果です。

回避策の1つはel.blur()、遅延の後で要素を使用して再フォーカスすることです。

$('input[type=number]').on('mousewheel', function(){
  var el = $(this);
  el.blur();
  setTimeout(function(){
    el.focus();
  }, 10);
});

3
見栄えの良いソリューションですが、テストの結果、このソリューションにはフォーカスを奪うという副作用があることがわかりました。私はこれを微調整しました:要素にフォーカスがあるかどうかを確認するためのテスト:var hadFocus = el.is(':focus');ぼかしの前に、そしてhadFocsがtrueの場合にのみタイムアウトを設定するガード。
Rob Dawson

2

提供された回答はFirefox(Quantum)では機能しません。イベントリスナーをマウスホイールからホイールに変更する必要があります:

$(':input[type=number]').on('wheel',function(e){ $(this).blur(); });

このコードは、Firefox QuantumおよびChromeで動作します。


2

Reactで作業し、解決策を探している人のために。最も簡単な方法は、次のように入力コンポーネントでonWheelCaptureプロップを使用することです。

onWheelCapture={e => { e.target.blur() }}


2

Typescript Variation

Typescriptは、タイプセーフのためにHTMLElementを使用していることを認識する必要があります。そうでないと、多くのProperty 'type' does not exist on type 'Element'タイプのエラーが表示されます。

document.addEventListener("mousewheel", function(event){
  let numberInput = (<HTMLInputElement>document.activeElement);
  if (numberInput.type === "number") {
    numberInput.blur();
  }
});

1

自分のためにこれを解決しようとしている間、私はそれがの親要素の上に再火災に巻き込まイベントを試みることによって、番号の変更を無効にしながら、入力のページのスクロールやフォーカスを維持するために実際に可能だということに気づいた<input type="number"/>、それがキャッチされました、単にこのように:

e.target.parentElement.dispatchEvent(e);

ただし、これはブラウザーコンソールでエラーを引き起こし、意図的に無効なコードであるため、おそらくすべての場所で動作することが保証されていません(私はFirefoxでのみテストしました)。

少なくともFirefoxとChromiumでうまく機能する別の解決策は、次のように一時的に<input>elementを作成することreadOnlyです。

function handleScroll(e) {
  if (e.target.tagName.toLowerCase() === 'input'
    && (e.target.type === 'number')
    && (e.target === document.activeElement)
    && !e.target.readOnly
  ) {
      e.target.readOnly = true;
      setTimeout(function(el){ el.readOnly = false; }, 0, e.target);
  }
}
document.addEventListener('wheel', function(e){ handleScroll(e); });

私が気付いた副作用の1つは、別のスタイルを使用している場合、フィールドが一瞬ちらつく可能性があることです。 readOnly、少なくとも私の場合、これは問題ではないようです。

同様に、(Jamesの回答で説明されているように)readOnlyプロパティを変更する代わりにblur()、フィールドとfocus()から戻す使用するスタイルによっては、ちらつきが発生する場合があります。

または、ここの他のコメントで述べたようpreventDefault()に、代わりにイベントを呼び出すことができます。wheelフォーカスがあり、マウスカーソルの下にある数値入力のイベントのみを処理すると仮定すると(上記の3つの条件が意味することです)、ユーザーエクスペリエンスへの悪影響はほとんどありません。


1

JavaScriptを必要としないソリューションが必要な場合は、一部のHTML機能をCSS疑似要素と組み合わせるとうまくいきます。

span {
  position: relative;
  display: inline-block; /* Fit around contents */
}

span::after {
  content: "";
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0; /* Stretch over containing block */
  cursor: text; /* restore I-beam cursor */
}

/* Restore context menu while editing */
input:focus {
  position: relative;
  z-index: 1;
}
<label>How many javascripts can u fit in u mouth?
  <span><input type="number" min="0" max="99" value="1"></span>
</label>

これは、コンテンツをクリックすると機能します。 <label>は、フォームフィールドに関連付けられているのするとフィールドがフォーカスされるため機能します。ただし、フィールド上の疑似要素の「ウィンドウペイン」は、マウスホイールイベントがそれに到達するのをブロックします。

欠点は、上下のスピナーボタンが機能しなくなることですが、とにかくそれらを削除したと言っていました。


理論的には、最初に入力にフォーカスする必要なしにコンテキストメニューを復元できます。ユーザーがスクロールして:hoverスタイルは発生しません。ブラウザーはパフォーマンス上の理由でスクロール中に再計算を回避するためですが、ブラウザー/デバイスを完全にクロスしていませんそれをテストしました。


0
function fixNumericScrolling() {
$$( "input[type=number]" ).addEvent( "mousewheel", function(e) {
    stopAll(e);     
} );
}

function stopAll(e) {
if( typeof( e.preventDefault               ) != "undefined" ) e.preventDefault();
if( typeof( e.stopImmediatePropagation     ) != "undefined" ) e.stopImmediatePropagation();
if( typeof( event ) != "undefined" ) {
    if( typeof( event.preventDefault           ) != "undefined" ) event.preventDefault();
    if( typeof( event.stopImmediatePropagation ) != "undefined" ) event.stopImmediatePropagation();
}

return false;
}

0

最も簡単な解決策はonWheel={ event => event.currentTarget.blur() }}、入力自体を追加することです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.