web-dev-qa-db-fra.com

Personnalisation des flèches d'incrémentation lors de la saisie du numéro de type à l'aide de CSS

J'ai une entrée de type numéro qui est rendue en utilisant le code suivant:

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

Cela ressemble à ceci:

enter image description here

Je voudrais en faire quelque chose comme ça:

enter image description here

La deuxième vue est émulée à l’aide de deux boutons distincts.

Comment pourrais-je coiffer les flèches comme décrit?

23
MadPhysicist

Les commandes natives input[type=number] Ne sont pas compatibles avec tous les styles. Le moyen le plus simple et le plus sûr d’atteindre ce que vous voulez, navigateur/appareil, est de les cacher en utilisant:

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;
}

... qui vous permet d'utiliser vos boutons personnalisés, qui pourraient être liés pour exécuter les fonctions que les spinners (flèches) feraient (.stepUp() et .stepDown()), à condition que vous conserviez les entrées type="number".

Par exemple:

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>

Note: Pour changer la valeur de l'entrée, il faut la trouver. Pour plus de flexibilité, dans l'exemple ci-dessus, j'ai groupé les boutons et le <input> Sous un parent commun et utilisé ce parent pour trouver le <input> (En choisissant de ne pas s'appuyer sur leur proximité ou leur ordre particulier dans le DOM) . La méthode ci-dessus changera tout frère input[type=number] des boutons . Si cela ne vous convient pas, vous pouvez utiliser d'autres méthodes pour rechercher l'entrée à partir des boutons:

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

Notez également que les exemples ci-dessus ne recherchent que dans le .parentNode, Pas dans le document, ce qui est également possible:
À savoir: onclick="document.getElementById('#some-id').stepUp()"

  • par proximité (previousElementSibling | nextElementSibling)
<button onclick="this.previousElementSibling.stepUp()"></button>
  • toute autre manière de déterminer et de trouver un élément d’entrée particulier dans une structure DOM. Par exemple, on pourrait utiliser des bibliothèques tierces, telles que jQuery:
<button onclick="$(this).prev()[0].stepUp()"></button>

Une remarque importante lors de l’utilisation de jQuery est que les méthodes stepUp() et stepDown() sont placées sur l’élément DOM et non sur le wrapper jQuery. L'élément DOM se trouve dans la propriété 0 Du wrapper jQuery.


Note sur preventDefault(). Cliquer sur un <button> À l'intérieur d'un <form> déclenchera la soumission du formulaire. Par conséquent, s'il est utilisé comme ci-dessus, dans les formulaires, le onclick devrait également contenir preventDefault();. Exemple:

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

Toutefois, si l’on utilisait les balises <a> Au lieu de <button>, Cela n’est pas nécessaire. En outre, la prévention peut être définie globalement pour tous les boutons de formulaire avec un petit extrait de code 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();
  });
}

... ou en utilisant jQuery:

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