`<input type = number>`에서 스크롤 비활성화


121

입력 번호 필드의 번호를 변경하는 스크롤 휠을 비활성화 할 수 있습니까? 스피너를 제거하기 위해 웹킷 관련 CSS를 엉망으로 만들었지 만이 동작을 모두 제거하고 싶습니다. type=numberiOS에서 멋진 키보드가 나오기 때문에 사용 하는 것이 좋습니다.


7
type = number 대신 입력 유형 tel (type = "tel")을 사용하십시오. iOS 숫자 키보드가 나타납니다.
Praveen Vijayan 2012 년

그 안에 onscroll핸들러 를 추가하면 event.preventDefault()어떻게 되나요?
robertc

14
겸손한 의견으로는 이것이 기능이되어야한다고 생각조차하지 않습니다. 브라우저 개발에 대한 발언이 있다면 아마도이 기능을 제거하도록 강요 할 것입니다. 성가신 일뿐이며 실제로 사용하는 사람을 알지 못합니다.
Kirkland 2014 년

3
커클랜드에 전적으로 동의합니다. 폼이있는 페이지를 스크롤하는 것은 나쁜 UX 일 뿐이며 숫자 입력 요소가 마우스 아래에 있으면 증가하기 시작하고 페이지 스크롤이 중지됩니다. 완전히 방향 감각 상실.
kjs3 2014 년

3
@PraveenVijayan : 이것은 해결 방법이지만 새로운 html5 입력 유형을 사용하는 이유에 위배됩니다. 미래에는 전화가 연락처 등에서 번호를 선택할 수있는 가능성을 제공 할 수 있으며, 다른 종류의 번호를 의미한다면 매우 이상하게 보일 것입니다.
경외

답변:


92

다른 사람들이 제안한 것과 같이 입력 번호 요소에서 마우스 휠 이벤트의 기본 동작을 방지합니다 ( "blur ()"호출은 일반적으로 사용자가 원하는 것이 아니기 때문에 선호하는 방법이 아닙니다).

그러나. 항상 모든 input-number 요소에서 mousewheel 이벤트를 수신하지 않고 요소에 초점이 맞춰져있을 때만 수행합니다 (문제가 존재하는 경우). 그렇지 않으면 마우스 포인터가 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

좋은 대답이지만 적어도 웹킷에서는 커서가 입력 요소 위에있는 동안 창이 스크롤되는 것을 방지합니다. 마우스 휠 이벤트도 버블 링되어야한다고 생각했습니다.
Ryan McGeary 2014 년

포커스가있을 때 스크롤 비활성화 기능을 요소에 적용하는 경우에만 마우스가 입력 요소 위에있을 때 스크롤을 방지해서는 안됩니다. 그러나 요소에 포커스가있을 때 창을 스크롤하는 것을 방지합니다. / : 그리고 네, 왜 마우스 휠 이벤트가 ... 버블 링되지 않습니다
Grantzau

6
이것은 처음에 존재해서는 안되는 동작에 대한 좋은 수정입니다.
Jonny

스크롤 동작은 입력에 초점을 맞출 필요가 없기 때문에 대부분의 유닉스 유형 플랫폼 그놈, osx, 안드로이드 (마우스 포함)에서는 작동하지 않습니다. 또한, 난 그냥 입력의 텍스트 유형을 사용하고 내 수 제한을 넣어 (단축키 UP / DOWN을 lossing 만 아니라 JS로 추가 할 수 있습니다)
zeachco


20

모두를 지배하는 하나의 이벤트 리스너

이것은 순수한 js에서 @Simon Perepelitsa대답 과 비슷 하지만 문서 요소에 하나의 이벤트 리스너를 놓고 포커스가있는 요소가 숫자 입력인지 확인하므로 조금 더 간단합니다.

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
참고로, live()더 이상 사용되지 않습니다. 이제 다음을 사용해야합니다 on(). $(':input[type=number]').on('mousewheel',function(e){ $(this).blur(); });
Saeid Zebardast 2010 년

3
귀하의 의견은 해답이 될 자격이 @SaeidZebardast
snumpy

최신 브라우저의 경우 wheel대신 이벤트를 사용하십시오 mousewheel. 참조 : developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event
vee

16

HTML onwheel 속성을 사용하기 만하면됩니다 .

이 옵션은 페이지의 다른 요소를 스크롤하는 데 영향을주지 않습니다.

그리고 모든 입력에 대한 리스너를 추가하면 사후에 동적으로 생성 된 입력에서 작동하지 않습니다.

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


이 CSS는 여러 소스에서 찾을 수 있습니다. 어쨌든 CSS는 보너스 일뿐입니다. 질문에 대한 진정한 해결책은 HTML onwheel 속성입니다. ;-)
Maikon Matheus

5
나는이 해결책을 좋아한다! 감사. 제 경우에는 onBlur()예상과 다릅니다. 나는 return false정말로 "아무것도하지 않는"대신 간단한 것을 설정했다 . <input type="number" onwheel="return false;">
Daniel

14

@Semyon Perepelitsa

이것에 대한 더 나은 해결책이 있습니다. 블러 는 입력에서 초점을 제거하고 원하지 않는 부수적 인 영향입니다. 대신 evt.preventDefault를 사용해야합니다. 이것은 사용자가 스크롤 할 때 입력의 기본 동작을 방지합니다. 다음은 코드입니다.

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

6
작동하지만 이벤트가 버블 링되지 않으므로 페이지가 스크롤되지 않습니다. 흐리게 처리하지 않고 기본 동작 (페이지 스크롤)을 유지하는 방법이 있습니까?
GuiGS

최신 브라우저의 경우 wheel대신 이벤트를 사용하십시오 mousewheel. 참조 : developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event
vee

7

먼저 다음 중 하나를 수행하여 마우스 휠 이벤트를 중지해야합니다.

  1. 다음으로 비활성화 mousewheel.disableScroll
  2. 가로 채기 e.preventDefault();
  3. 요소에서 초점을 제거하여 el.blur();

처음 두 가지 방법은 창 스크롤을 중지하고 마지막 두 가지 방법은 요소에서 포커스를 제거합니다. 둘 다 바람직하지 않은 결과입니다.

한 가지 해결 방법은 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가 참인 경우에만 타임 아웃을 설정하는 가드.
Rob Dawson

2

제공된 답변은 Firefox (Quantum)에서 작동하지 않습니다. 이벤트 리스너는 마우스 휠에서 휠로 변경해야합니다.

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

이 코드는 Firefox Quantum 및 Chrome에서 작동합니다.


2

React로 작업하고 솔루션을 찾는 모든 사람을 위해. 가장 쉬운 방법은 다음과 같이 입력 구성 요소에서 onWheelCapture prop을 사용하는 것입니다.

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


2

Typescript 변형

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>요소를 만드는 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); });

내가 발견 한 한 가지 부작용은 필드에 대해 다른 스타일을 지정하면 필드가 잠시 깜박일 수 있다는 것입니다 readOnly. 그러나 제 경우에는 적어도 이것은 문제가되지 않는 것 같습니다.

마찬가지로 (James의 답변에서 설명했듯이) readOnly속성 을 수정하는 대신 blur()필드를 한 다음 focus()다시 되돌릴 수 있지만 사용하는 스타일에 따라 약간의 깜박임이 발생할 수 있습니다.

또는 여기의 다른 의견에서 언급했듯이 preventDefault()대신 이벤트를 호출 할 수 있습니다 . wheel포커스가 있고 마우스 커서 아래에있는 숫자 입력에 대해서만 이벤트를 처리한다고 가정하면 (위의 세 가지 조건이 의미하는 것입니다) 사용자 경험에 대한 부정적인 영향은 거의 없을 것입니다.


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.