HTMLのinputボタンのtype属性にnumberを指定すると
数字以外の入力が不可になり
さらに上の画像のように、増減ボタンが右端につくのですが、
この増減ボタンにはブラウザによって
見た目がコロコロ変わってしまうという困った問題があります。
そこで本日は
CSSとjavascriptを駆使してこの増減ボタンのデザインを
自分の好きな見た目に変更する方法をご紹介します。
デモとソースコード
まずは実物をば。
上にあるのが今回作成する入力フィールドです。
ボタンを押して頂ければ数値が増減しますし、
ソースを見ればHTMLとCSSをボタンが再現していることも
ご確認頂けるかと思います。
<div class="p-qty js-qty"> <div class="__arrow __up js-qty_up"></div> <div class="__arrow __down js-qty_down"></div> <input type="number" class="p-qty__input js-qty_target" value="1"> </div>
/* デフォルトの装飾は消しておく */ /* Chrome/Safari */ input[type="number"]::-webkit-outer-spin-button, input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; } /* Firefox */ input[type="number"] { -moz-appearance: textfield; } .p-qty { position: relative; display: inline-block; } .p-qty > .__arrow { position: absolute; top: calc(50% - 9px); right: 10px; transform: translate(0px, -50%); display: inline-block; border-width: 6px 4px; border-style: solid; border-color: transparent transparent rgb(0, 0, 0); cursor: pointer; } .p-cart_detail .p-qty > .__arrow { top: calc(50% - 7px); border-width: 5px 3px; border-style: solid; border-color: transparent transparent rgb(0, 0, 0); } .p-qty > .__arrow.__down { top: calc(50% + 9px); border-bottom: 6px solid transparent; border-top: 6px solid rgb(0, 0, 0); } .p-cart_detail .p-qty > .__arrow.__down { border-bottom: 5px solid transparent; border-top: 5px solid rgb(0, 0, 0); top: calc(50% + 7px); } .p-qty__input { width: 91px; height: 40px; border: 1px solid rgb(112, 112, 112); border-radius: 5px; padding-left: 25px; }
//vanilla jsで親要素探索する用の関数 function getParents(el, parentSelector /* optional */) { if (parentSelector === undefined) { return false; } var p = el.parentNode; while (!p.classList.contains(parentSelector)) { var o = p; p = o.parentNode; } return p; } document.addEventListener('click',function(e){ e = e || window.event; var target = e.target || e.srcElement, text = target.textContent || target.innerText; var val = 0; //クリックしたDOMが.js-qty_upだったら if(target.classList.contains('js-qty_up')){ val = 1; } else if(target.classList.contains('js-qty_down')) { val = -1; } else { return false; } var parent = getParents(target,'js-qty');//親の.js-qtyを取得して var input = parent.querySelectorAll('.js-qty_target');//親の.js-qtyの子の.js-qty_targetを取得して //Nodelistを回す for (let i = 0; i < input.length; i++) { if(input[i].classList.contains('js-qty_target')){ //.js-qty_target持ってるDOMに対して var num = parseInt(input[i].value); num = isNaN(num) ? 1 : num; input[i].value = num + val < 1 ? 1 : num + val; } } },false);
コードはこんな感じ。
HTMLとCSSはともかくjavascriptが処理の内容に比べて
やたら長くなっているのは今回あえてjQueryを使わず
vanillaJSで実装したからです。
最初はjQueryでサクッと行けるかと思ったのですが、
実装途中で「一度でも数値以外の文字列を入力すると
その後javascriptでinput内のvalueを書き換えられなくなる※」という問題が発生。
色々頑張ったがどうにも解決できなかったので
もしかしたらと思いvanillaJSで書いたらいい感じに動いてくれたという次第でした。
原因まではちょっと断定できなかったのですが
調べた限りではどうもinput[type=number]の仕様が関係しているみたいです。
User agents must not allow the user to set the value to a non-empty string that is not a valid floating point number.
4.10.7.1.13 Number state — HTML5
コメント