CSSで、数値の入力欄の上下ボタンを消す方法
<input type="number"> の右端に出る上下ボタンは、::-webkit-inner-spin-button という擬似要素に -webkit-appearance: none を書くと消えます。個数や金額のような数値を入れる欄で、スピンボタンとも呼ばれるこの上下ボタンを見せたくないときに使えます。MDN の appearance のページに例がある appearance: textfield は、検証環境の Chromium では効きませんでした。ボタンを消しても、↑↓キーやマウスのホイールでは値が変わるので、その動きと止め方もあわせて確かめました。
検証環境は Ubuntu 24.04、Node.js 22.23.4、Playwright 1.63.0、Chromium 153 です。画面の画素やキー操作の結果は、Playwright で Chromium を動かして調べました。Firefox と Safari、スマートフォンでの表示や入力は試していません。各ブラウザーの対応バージョンは、互換性データ(@mdn/browser-compat-data 8.1.8)の値です。

擬似要素に -webkit-appearance: none を書く
上下ボタンを消す CSS は、次のとおりです。
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
-webkit-appearance: none;
}
検証環境の Chromium では、上下ボタンはふだんは描かれず、カーソルを重ねたときやフォーカスしたときに出ます。そこで、入力欄の右端 18px の範囲にある白以外の画素を数えました。何も書かないときは、カーソルを重ねると 40 個、フォーカスすると 42 個ありました。上の CSS を書くと、カーソルを重ねたときは 0 個になりました。フォーカスしたときは 2 個で、どちらも数えた範囲の右上と右下の角にある灰色の画素でした。上下ボタンは描かれませんでした。
MDN の ::-webkit-inner-spin-button のページによると、これはどの標準にも含まれていない擬似要素で、WebKit と Blink のブラウザーでだけ使えます。互換性データでは、Chrome 6、Edge 79、Safari 5(iOS 版は 4.2)から対応していて、Firefox は対応していません。
上の CSS は、2つの擬似要素を並べています。検証環境の Chromium で効いていたのは ::-webkit-inner-spin-button のほうでした。こちらだけに書いても上下ボタンは消え、::-webkit-outer-spin-button だけに書いたときは消えませんでした。互換性データにも、::-webkit-outer-spin-button の項目はありません。
同じ擬似要素に、-webkit- を付けない appearance: none や、display: none を書いても、上下ボタンは消えました。カーソルを重ねたときの画面は、display: none と -webkit-appearance: none とで1画素も違いませんでした。この CSS に margin: 0 を添える書き方もありますが、検証環境では、書いても書かなくても、カーソルを重ねたときの画面は変わりませんでした。
Chromium では、appearance: textfield を書いても消えない
MDN の appearance のページには、数値の入力欄に appearance: textfield を書く例があり、ブラウザーによっては上下ボタンが見えなくなると書かれています。
検証環境の Chromium 153 では、input に appearance: textfield を書くと、計算値は textfield になりました。それでも、カーソルを重ねると上下ボタンが出ました(上の画像の2つ目)。右端の白以外の画素も、何も書かないときと同じ 40 個でした。-webkit-appearance: textfield や、input 自体への appearance: none も同じで、上下ボタンは残りました。Chromium で消すには、input ではなく、擬似要素のほうに書きます。
ボタンを消しても、キーやホイールでは値が変わる
上下ボタンを消しても、入力欄は数値の入力欄のままです。↑↓キーで値が変わります。

検証環境では、min="0" max="10" step="1" で値が 5 の入力欄を使い、何も書かない場合と上下ボタンを消した場合を比べました。何も書かない入力欄では、右端の上半分をクリックすると値は 6 になりました。上下ボタンを消した入力欄では、同じ場所をクリックしても 5 のままでした。キーの動きは、どちらも同じでした。↑キーで 6、続けて↓キーを2回で 4 になり、さらに↑キーを10回押しても max の 10 で止まりました。アクセシビリティツリーでの役割も、どちらも spinbutton のままでした。MDN の appearance のページにも、appearance プロパティは機能には影響せず、上下のカーソルキーで値を増減できると書かれています。
ホイールでも値が変わります。上下ボタンを消した入力欄にフォーカスがある状態で、入力欄の上でホイールを下に回すと、値は 5 から 4 になり、ページはスクロールしませんでした。フォーカスがないときは値は変わらず、ページがスクロールしました。
ホイールで値が変わるのを止めたいときは、wheel イベントの既定の動作を止めます。
const input = document.querySelector('input[type="number"]');
input.addEventListener(
'wheel',
(e) => {
if (document.activeElement === input) {
e.preventDefault();
}
},
{ passive: false },
);
検証環境では、フォーカスがある状態でホイールを回しても、値は 5 のままでした。このとき、ページもスクロールせず、フォーカスは入力欄に残りました。フォーカスがないときは止めないので、コードを入れる前と同じく、ページは 100px スクロールしました。
ページをスクロールさせたいときは、preventDefault() の代わりに、input.addEventListener('wheel', () => input.blur()); のように、ホイールを回したときにフォーカスを外す書き方もあります。検証環境では、値は 5 のままで、ページは 100px スクロールし、フォーカスは入力欄から外れました。
上下ボタンがいらないなら、type="text" と inputmode="numeric" を使う
MDN の input type="number" のページの「アクセシビリティの考慮」では、上下ボタンが大事な機能でないなら type="number" を使わず、inputmode="numeric" と pattern 属性を使うよう勧めています。同じ節では、type="number" だと、ほかの操作をしようとして、誤って値を増やしてしまうおそれがあることも、理由に挙げています。
<input type="text" inputmode="numeric" pattern="[0-9]*">
検証環境では、CSS を書かなくても、この入力欄にカーソルを重ねたときに上下ボタンは描かれませんでした。↑キーを押しても、値は 5 のまま変わりませんでした。アクセシビリティツリーでの役割は textbox です。
数字以外の文字が入ったかは、pattern で調べられます。「12a」と入れると validity.patternMismatch が true になり、「12」なら validity.valid が true でした。値を数値で受け取るときは、自分で変換します。「12」を入れたとき、valueAsNumber は type="number" なら 12、type="text" なら NaN でした。





