使用 CSS 自定义类型号输入的增量箭头

我有一个类型编号的输入,它使用以下代码呈现:

<input class="quantity" id="id_form-0-quantity" min="0" name="form-0-quantity" value="1" type="number">

它看起来像这样:

enter image description here

我想把它变成这样的东西:

enter image description here

第二个视图使用两个单独的按钮进行模拟。

我如何按照所描述的样式设计箭头?

177709 次浏览

医生:

在被私下问过很多次关于以下设置的问题后,我决定为它添加一个演示(Bootstrap 4 + jQuery + Font Awesome 输入组设置) :

$('.btn-plus, .btn-minus').on('click', function(e) {
const isNegative = $(e.target).closest('.btn-minus').is('.btn-minus');
const input = $(e.target).closest('.input-group').find('input');
if (input.is('input')) {
input[0][isNegative ? 'stepDown' : 'stepUp']()
}
})
.inline-group {
max-width: 9rem;
padding: .5rem;
}


.inline-group .form-control {
text-align: right;
}


.form-control[type="number"]::-webkit-inner-spin-button,
.form-control[type="number"]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>


<div class="input-group inline-group">
<div class="input-group-prepend">
<button class="btn btn-outline-secondary btn-minus">
<i class="fa fa-minus"></i>
</button>
</div>
<input class="form-control quantity" min="0" name="quantity" value="1" type="number">
<div class="input-group-append">
<button class="btn btn-outline-secondary btn-plus">
<i class="fa fa-plus"></i>
</button>
</div>
</div>


长(初始)答案:

本机 input[type=number]控件不能跨浏览器显示样式。要实现跨浏览器/跨设备的目的,最简单、最安全的方法是:

input[type="number"] {
-webkit-appearance: textfield;
-moz-appearance: textfield;
appearance: textfield;
}
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
}

... 它允许您使用您的自定义按钮,它可以链接到执行函数的自旋器(箭头)(.stepUp().stepDown()) ,只要您保持输入的 type="number"

例如:

input[type="number"] {
-webkit-appearance: textfield;
-moz-appearance: textfield;
appearance: textfield;
}


input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
}


.number-input {
border: 2px solid #ddd;
display: inline-flex;
}


.number-input,
.number-input * {
box-sizing: border-box;
}


.number-input button {
outline:none;
-webkit-appearance: none;
background-color: transparent;
border: none;
align-items: center;
justify-content: center;
width: 3rem;
height: 3rem;
cursor: pointer;
margin: 0;
position: relative;
}


.number-input button:before,
.number-input button:after {
display: inline-block;
position: absolute;
content: '';
width: 1rem;
height: 2px;
background-color: #212121;
transform: translate(-50%, -50%);
}
.number-input button.plus:after {
transform: translate(-50%, -50%) rotate(90deg);
}


.number-input input[type=number] {
font-family: sans-serif;
max-width: 5rem;
padding: .5rem;
border: solid #ddd;
border-width: 0 2px;
font-size: 2rem;
height: 3rem;
font-weight: bold;
text-align: center;
}
<div class="number-input">
<button onclick="this.parentNode.querySelector('input[type=number]').stepDown()" ></button>
<input class="quantity" min="0" name="quantity" value="1" type="number">
<button onclick="this.parentNode.querySelector('input[type=number]').stepUp()" class="plus"></button>
</div>


注意: 为了改变输入的值,需要找到它。为了提供灵活性,在上面的示例中,我将按钮和 <input>分组在一个共同的父级下,并使用该父级来查找 <input>(选择不依赖于它们的邻近性或 DOM 中的特定顺序)。上述方法 < em > 将把任何 input[type=number] < em > 兄弟更改为按钮 。如果不方便的话,可以使用其他方法从按钮中找到输入:

  • 作者: < em > id : .querySelector('#some-id'):
<button onclick="this.parentNode.querySelector('#some-id').stepUp()"></button>
  • 作者: < em > className : .querySelector('.some-class'):
<button onclick="this.parentNode.querySelector('.some-class').stepUp()"></button>

还要注意上面的例子只在 .parentNode中搜索,而不是在整个 document中搜索,这也是可能的:
onclick="document.getElementById('#some-id').stepUp()"

  • 作者: 近距离接触(previousElementSibling | nextElementSibling)
<button onclick="this.previousElementSibling.stepUp()"></button>
  • 确定和查找 DOM 结构中特定输入元素的任何其他方法。例如,可以使用第三方库,如 jQuery:
<button onclick="$(this).prev()[0].stepUp()"></button>

使用 jQuery 时需要注意的一点是,stepUp()stepDown()方法放在 DOM 元素上,而不是 jQuery 包装器上。DOM 元素位于 jQuery包装器的 0属性中。


关于 preventDefault()的注释 。单击 <form> 威尔中的 <button>触发表单提交。因此,如果像上面那样使用内部形式,onclick也应该包含 preventDefault();。例如:

<button onclick="$(this).prev()[0].stepUp();preventDefault()"></button>

但是,如果使用 <a>标记而不是 <button>标记,则没有必要这样做。此外,可以通过一个小的 JavaScript 代码片段对所有表单按钮进行全局设置:

var buttons = document.querySelectorAll('form button:not([type="submit"])');
for (i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', function(e) {
e.preventDefault();
});
}

或者使用 jQuery:

$('form').on('click', 'button:not([type="submit"])', function(e){
e.preventDefault();
})

你可以很容易地将第一个设计转换为第二个设计,如下所示:

超文本标示语言

<div class="quantity">
<button class="btn minus1">-</button>
<input class="quantity" id="id_form-0-quantity" min="0" name="form-0-quantity" value="1" type="number">
<button class="btn add1">+</button>

CSS

.quantity{
display:flex;
width:160px;
}


/* it will support chrome and firefox */
.quantity input[type=number]::-webkit-inner-spin-button,
.quantity input[type=number]::-webkit-outer-spin-button{
-webkit-appearance:none;
}


.quantity input,.quantity button{
width:50px;
padding:.5em;
font-size:1.2rem;
text-align:center;
font-weight:900;
background:white;
border:1px solid #aaa;
}


.quantity input{
border-left:none;
border-right:none;
}

我找到了一个好办法。只需旋转箭头键并将不透明度设置为0。然后在这些不可见的按钮上设置一个: after 和: before 元素。然后这些元素可以按照需要设置样式。

input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
transform: rotate(90deg);
height: 80px;
opacity: 0;
}


.quantity-wrapper {
position: relative;
}


.quantity-wrapper:after {
content: "+";
position: absolute;
right: 5px;
height: 100%;
top: 8px;
pointer-events: none;
}


.quantity-wrapper:before {
content: "-";
position: absolute;
left: 5px;
height: 100%;
top: 8px;
}
<div class="quantity-wrapper">
<input class="quantity" id="id_form-0-quantity" min="0" name="form-0-quantity" value="1" type="number">
</div>

数字输入可以通过以下我最近发现的脚本以这种方式程式化:

演示。

这个脚本是一个超轻量级(1.49 kb 未压缩,0.71 kb 压缩,0.35 kb 压缩) ,可用和可靠的数量输入,取代了可怕的,精细的小输入按钮内置的数字输入在浏览器中。它是使用 ES6模块编写的,因此需要为较老的浏览器进行翻译。

作者的知识库是 给你。 希望这有所帮助;)

编辑: 或者,如果您希望使用向上/向下箭头按钮,而不是加/减按钮,则使用 另一个基于 jQuery 的解决方案

Number input with up/down arrows

$(document).ready(function () {
jQuery('<div class="quantity-nav"><button class="quantity-button quantity-up">&#xf106;</button><button class="quantity-button quantity-down">&#xf107</button></div>').insertAfter('.quantity input');
jQuery('.quantity').each(function () {
var spinner = jQuery(this),
input = spinner.find('input[type="number"]'),
btnUp = spinner.find('.quantity-up'),
btnDown = spinner.find('.quantity-down'),
min = input.attr('min'),
max = input.attr('max');


btnUp.click(function () {
var oldValue = parseFloat(input.val());
if (oldValue >= max) {
var newVal = oldValue;
} else {
var newVal = oldValue + 1;
}
spinner.find("input").val(newVal);
spinner.find("input").trigger("change");
});


btnDown.click(function () {
var oldValue = parseFloat(input.val());
if (oldValue <= min) {
var newVal = oldValue;
} else {
var newVal = oldValue - 1;
}
spinner.find("input").val(newVal);
spinner.find("input").trigger("change");
});


});
});
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
min-width: 100vw;
background: #34495E;
font-size: 1rem;
}


.quantity {
position: relative;
}


input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}


input[type=number] {
-moz-appearance: textfield;
}


.quantity input {
width: 45px;
height: 42px;
line-height: 1.65;
float: left;
display: block;
padding: 0;
margin: 0;
padding-left: 20px;
border: none;
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.08);
font-size: 1rem;
border-radius: 4px;
}


.quantity input:focus {
outline: 0;
}


.quantity-nav {
float: left;
position: relative;
height: 42px;
}


.quantity-button {
position: relative;
cursor: pointer;
border: none;
border-left: 1px solid rgba(0, 0, 0, 0.08);
width: 21px;
text-align: center;
color: #333;
font-size: 13px;
font-family: "FontAwesome" !important;
line-height: 1.5;
padding: 0;
background: #FAFAFA;
-webkit-transform: translateX(-100%);
transform: translateX(-100%);
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
}


.quantity-button:active {
background: #EAEAEA;
}


.quantity-button.quantity-up {
position: absolute;
height: 50%;
top: 0;
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
font-family: "FontAwesome";
border-radius: 0 4px 0 0;
line-height: 1.6
}


.quantity-button.quantity-down {
position: absolute;
bottom: 0;
height: 50%;
font-family: "FontAwesome";
border-radius: 0 0 4px 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>


<div class="quantity">
<input type="number" min="1" max="9" step="1" value="1">
</div>

下面是另一个版本,基于@Tao 的回答,使用 font-Awesome:

input[type="number"] {
-webkit-appearance: textfield;
-moz-appearance: textfield;
appearance: textfield;
}


input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
}


.number-input {
border: 2px solid #ddd;
display: inline-flex;
}


.number-input,
.number-input * {
box-sizing: border-box;
}


.number-input button {
outline:none;
-webkit-appearance: none;
background-color: transparent;
border: none;
align-items: center;
justify-content: center;
width: 3rem;
height: 3rem;
cursor: pointer;
margin: 0;
position: relative;
}


.number-input button:after {
display: inline-block;
position: absolute;
font-family: "Font Awesome 5 Free";
font-weight: 900;
content: '\f077';
transform: translate(-50%, -50%) rotate(180deg);
}
.number-input button.plus:after {
transform: translate(-50%, -50%) rotate(0deg);
}


.number-input input[type=number] {
font-family: sans-serif;
max-width: 5rem;
padding: .5rem;
border: solid #ddd;
border-width: 0 2px;
font-size: 2rem;
height: 3rem;
font-weight: bold;
text-align: center;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/css/all.min.css" integrity="sha512-HK5fgLBL+xu6dm/Ii3z4xhlSUyZgTT9tuc/hSrtw6uzJOvgRr2a9jyxxT1ely+B+xFAmJKVSTbpM/CuL7qxO8w==" crossorigin="anonymous" />


<div class="number-input">
<button onclick="this.parentNode.querySelector('input[type=number]').stepDown()" class="minus"></button>
<input class="quantity" min="0" name="quantity" value="1" type="number">
<button onclick="this.parentNode.querySelector('input[type=number]').stepUp()" class="plus"></button>
</div>

这个代码可以帮助你

$.fn.spinInput = function (options) {
var settings = $.extend({
maximum: 1000,
minimum: 0,
value: 1,
onChange: null
}, options);


return this.each(function (index, item) {
var min = $(item).find('>*:first-child').first();
var max = $(item).find('>*:last-child').first();
var v_span = $(item).find('>*:nth-child(2)').find('span');
var v_input = $(item).find('>*:nth-child(2)').find('input');
var value = settings.value;
$(v_input).val(value);
$(v_span).text(value);
async function increment() {
value = Number.parseInt($(v_input).val());
if ((value - 1) > settings.maximum) return;
value++;
$(v_input).val(value);
$(v_span).text(value);
if (settings.onChange) settings.onChange(value);
}
async function desincrement() {
value = Number.parseInt($(v_input).val());
if ((value - 1) < settings.minimum) return;
value--
$(v_input).val(value);
$(v_span).text(value);
if (settings.onChange) settings.onChange(value);
}
var pressTimer;


function actionHandler(btn, fct, time = 100, ...args) {
function longHandler() {
pressTimer = window.setTimeout(function () {
fct(...args);
clearTimeout(pressTimer);
longHandler()
}, time);
}
$(btn).mouseup(function () {
clearTimeout(pressTimer);
}).mousedown(function () {
longHandler();
});


$(btn).click(function () {
fct(...args);
});
}


actionHandler(min, desincrement, 100);
actionHandler(max, increment, 100)
})
}








$('body').ready(function () {
$('.spin-input').spinInput({ value: 1, minimum: 1 });
});
:root {
--primary-dark-color: #F3283C;
--primary-light-color: #FF6978;
--success-dark-color: #32A071;
--sucess-light-color: #06E775;
--alert-light-color: #a42a23;
--alert-dark-color: #7a1f1a;
--secondary-dark-color: #666666;
--secondary-light-color: #A6A6A6;
--gold-dark-color: #FFA500;
--gold-light-color: #FFBD00;
--default-dark-color: #1E2C31;
--default-light-color: #E5E5E5;
}


.fx-row {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}


.fx-colum {
display: flex;
flex-direction: column;
flex-wrap: wrap;
}


.fx-colum.nowrap,
.fx-row.nowrap {
flex-wrap: nowrap;
}


.fx-row.fx-fill>*,
.fx-colum.fx-fill>* {
flex-grow: 1;
}


.spin-input {
border: 1px solid var(--secondary-light-color);
}


.spin-input>div:first-child {
cursor: pointer;
border-right: 1px solid var(--secondary-light-color);
}


.spin-input>div:first-child:active {
transform: translate3d(1px, 0px, 1px)
}


.spin-input>div:last-child {
flex: none;
border-left: 1px solid var(--secondary-light-color);
cursor: pointer;
}


.spin-input>div:last-child:active {
transform: translate3d(1px, 0px, 1px)
}


.icon {
font-weight: bold;
text-align: center;
vertical-align: middle;
padding: 12px;
font-size: 28px;
}


.icon.primary,
.icon.primary .ci {
color: var(--primary-dark-color);
}


.icon.reactive:hover .ci {
color: var(--primary-light-color);
}


.hidden {
display: none;
}
<script src="https://releases.jquery.com/git/jquery-3.x-git.min.js"></script>
<div class="spin-input nowrap fx-row fx-fill" >
<div class="icon reactive">
<span class="ci ci-minus">-</span>
</div>
<div class="icon">
<span>0</span>
<input type="text" class="hidden" value="0">
</div>
<div class="icon reactive">
<span class="ci ci-plus">+</span>
</div>
</div>

259)