We Blog Weblog

スピンボタン

Web

2024年6月15日

みなさんこんにちは。
ケミストのWeb担当みやのです。

「Web」記事では、これまでに得たWebに関する知識を記録として残していきたいと思います。

今回はinput type="number"における「スピンボタン」を作ってみたいと思います。

スピンボタンとは

input type="number"にマウスカーソルを乗せる、またはフォーカスすると右側に現れる数値の増減ボタンのことをスピンボタン(スピナーボタン)というらしいです。

スマホではスピンボタンは表示されません。

単に「スピナー」だと、画面読み込み時によく出てくるグルグルするやつ のことを指すみたいですね。

Chrome
Edge
Firefox
Safari

ちっちゃくて押しにくい気がしますね。

アレンジしてみよう

・スマホでも表示されて
・ボタンを押しやすい大きさにして
・長押しで連続で増減できる
ようにしてみましょう。

とりあえず試作品はこちらです。

参考:PisukeCode|CSSでinput type="number"のスピンボタンをカスタマイズ!コード例

input type="number"と増減ボタンを設置します。

<label class="number-spinner-wrap">
  <input type="number" value="0">
  <button class="spinner spinner-down">-</button>
  <button class="spinner spinner-up">+</button>
</label>

CSSはこんな感じです。

html {
  touch-action: manipulation;
}

body {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
}

.number-spinner-wrap {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 4rem;
}

.number-spinner-wrap input::-webkit-outer-spin-button, .number-spinner-wrap input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}

.number-spinner-wrap input {
  width: calc(100% - 8rem);
  height: 100%;
  text-align: center;
  margin: 0 auto;
  font-size: 2.5rem;
  border-radius: 0;
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  box-shadow: none;
  background: transparent;
  border: 2px solid #eee;
}

.number-spinner-wrap input:focus {
  outline: none;
  box-shadow: none;
  border-color: #32bdeb;
}

.number-spinner-wrap .spinner {
  position: absolute;
  top: 50%;
  width: 4rem;
  height: 4rem;
  transform: translate(0, -50%);
  font-size: 3rem;
  cursor: pointer;
  user-select: none;
  display: flex;
  justify-content: center;
  align-items: center;
}

.number-spinner-wrap .spinner-down {
  left: 0;
}

.number-spinner-wrap .spinner-up {
  right: -4px;
}

中央揃えがわからなかったのでヤケクソでdisplay:flex、justify-content:center、align-items:centerをぶち込んでみましたが合ってるかはわかりません。


スクリプトはちょっとだけChatGPTに手伝ってもらいました。

const $wrap = document.querySelector('.number-spinner-wrap');
const $input = $wrap.querySelector('input');
let intervalId;
$wrap.querySelector('.spinner-down').onclick = () => {
  $input.stepDown()
}
$wrap.querySelector('.spinner-up').onclick = () => {
  $input.stepUp()
}
$wrap.querySelector('.spinner-down').addEventListener('mousedown', startInterval);
$wrap.querySelector('.spinner-up').addEventListener('mousedown', startInterval);
$wrap.querySelector('.spinner-down').addEventListener('touchstart', startInterval);
$wrap.querySelector('.spinner-up').addEventListener('touchstart', startInterval);
document.addEventListener('mouseup', stopInterval);
document.addEventListener('touchend', stopInterval);

function startInterval() {
  intervalId = setInterval(() => {
    if (this.classList.contains('spinner-down')) {
      $input.stepDown();
    } else {
      $input.stepUp();
    }
  }, 100);
}

function stopInterval() {
  clearInterval(intervalId);
}

最初はonclickだったのを、長押しのためにmousedownとmouseupに変更して、さらにタッチデバイスのためにtouchstartとtouchendを追加してみたところ「しっかりクリック」「しっかりタッチ」しないと反応しなくなってしまったので、onclickも併記してみました。そしたら敏感になりすぎた

まとめ

本当は、押し続けることでだんだん加速するようにしたかったのですが、うまくいきませんでした。

この長押しで増減する機能をなんとか活動限界タイマーに組み込みたいなあ

この記事を書いた人
みやの
Web・DTP担当

Contact Us

ご意見、ご相談、料金のお見積もりなど、お気軽にお問い合わせください。

お問い合わせはこちら

TOP