Grow your CSS skills. Land your dream job.

Add (+/-) Button Number Incrementers

Published by Chris Coyier

Text inputs on forms can be used to submit numbers. A common use would be a "quantity" input on an eCommerce site. Changing the quantity value, from the user's perspective entails tabbing or clicking to the input, deleting it's current content, and typing in a new value. Expected behavior that nobody is going to yell at you for, but these number inputs could be a little friendlier. Through use of JavaScript (yes, jQuery), let's do just that.

Clean HTML

Here the form markup. Nothing extra added, just clean HTML. Without JavaScript, this form will function perfectly well and not have anything extraneous.

<form method="post" action="">
    <div>
        <label for="name">French Hens</label>
        <input type="text" name="french-hens" id="french-hens" value="3">
    </div>
    <div>
        <label for="name">Turtle Doves</label>
        <input type="text" name="turtle-doves" id="turtle-doves" value="2">
    </div>
    <div>
        <label for="name">Partridges</label>
        <input type="text" name="partridge" id="partridge" value="1">
    </div>
    
    <input type="submit" value="Submit" id="submit">
</form>

The CSS...

... isn't very interesting. Maybe a few things to note. Everything is floated left and the DIV's have overflow hidden to clear the floats. The labels are display block and text-align right to get the grid thing going. Pixel adjustments are made here and there to get things lining up right. I didn't spend much time on this, so you may see some cross-browser differences.

Make Some Buttons

Photoshop up a couple of buttons. Might as well use a sprite eh? I'll include the PSD in the download just in case you want to use these.

Appending Increment Buttons

We need to append these buttons to each input. You'll notice in the markup that each label/input pair is wrapped in a DIV. This is good practice so that label inputs get broken onto their own line (better readability) for when CSS is turned off. It's also required for validation with some DOCTYPES. AND, it's the perfect little hook we can target for appending these buttons.

$(function() {

    $("form div").append('<div class="inc button">+</div><div class="dec button">-</div>');

});

Two classes each, one generic "button" class which will be 90% of the styling and the class we'll use to bind the click event. The other unique class to adjust the background position and utilize the sprite.

Make Them Work

The "plain English":

  1. Cache the selector
  2. Save the "old" value of the input (value at time of clicking)
  3. If the "plus" button is clicked...
  4. ...increment value up one
  5. Else if the "minus" button is clicked...
  6. ...decrement the value down one
  7. Drop the new value into the input
$(".button").on("click", function() {

  var $button = $(this);
  var oldValue = $button.parent().find("input").val();

  if ($button.text() == "+") {
	  var newVal = parseFloat(oldValue) + 1;
	} else {
   // Don't allow decrementing below zero
    if (oldValue > 0) {
      var newVal = parseFloat(oldValue) - 1;
    } else {
      newVal = 0;
    }
  }

  $button.parent().find("input").val(newVal);

});

The above code does everything we described, with a little extra logic. Before it decrements the value, it makes sure the number is at least a value of 1 or higher. This prevents the value from ever going negative (at least through using these buttons). This is a no-brainer for "quanity" style inputs, but if your use doesn't need this just remove that "if" wrapper.

There are also a couple of commented lines about AJAX saving. If your application is all dynamic-cool-like that, you might wish to save the value automatically after a button is pressed, making it feel a little more desktop-application-y.

If you were to do that, you could put some code like this (perhaps):

var id = $button.attr("id");
$.ajax({
  type: "POST",
  url: "dosomething.php?id=" + id + "&newvalue=" + newVal,
  success: function() {
    $button.parent().find("input").val(newVal);
  }
});

You'd probably remove the bottom line of the click function where it updates the value and leave that in the "success" sub function above. That way the number doesn't get visually updated unless the AJAX save was successful.

Check it

View DemoDownload Files

MooTools

And as always, David Walsh with a port to MooTools.

Comments

  1. Permalink to comment#

    One thing you could try and add is if the user holds the mouse button down it continues adding to the total.

  2. kongondo
    Permalink to comment#

    Thx Chris!

    Nice tut. I disagree about the “easier than typing” bit though; at least it’s not always so. I think typing anything larger than 10 (20, 30…..1000) is easier than using buttons.

    cheers/k

    • Permalink to comment#

      Definitely. Even 10 is too many, I agree. You’d have to balance this technique with the application.

      For example, an inventory application where you need to reduce the inventory when sales come in. The average sale is 1-5 things. Having to do the math in your head every single time and manually type in the new number would kinda suck, not to mention be more error prone. Far easier to just look at the number sold and click the button that many times.

    • TeMc
      Permalink to comment#

      Not to forget that the user doesn’t *have to* use the buttons. The input field is still an fully working operational input field !

  3. A good walk-through, thanks. I’d rather not see this too often, though, like kongondo says, typing in a number is my preference too.

    Maybe useful for mobile apps, though, and for cases where typing in the number isn’t the point as much as “more” and “less” on a scale, but then why not just click along the range ( ie with star ratings ).

  4. heldopslippers
    Permalink to comment#

    ohw this is very nice !,
    i don’t agree with David S. you are not obligated to use these buttons and can decide to type in the number.

    As we all know, users do not read they just “look”, i think adding this kind of functionality gives the user a bit more information about the data they should enter here.

  5. A Player Name JJ
    Permalink to comment#

    Once again I visit this page and like clock-work Chris you always have something I’m either looking for or could use on my current designs.

    Thanks a ton for doing what you do!

  6. Permalink to comment#

    And use parseInt escape when some fool types in only letters. Currently you’ll get NaN error.

  7. Great tut… but it would be nice to teach us how to use “mouse scrool”.

  8. Permalink to comment#

    nice one again chris :) !

  9. daniel
    Permalink to comment#

    very nice technique and as heldopslippers said, it’s up to the users if they prefer to type in the number or if they want a really high value.

    A neat addition to this, I think, would be to be able to change the value by using the scroll wheel while hovering the input. That, and hitting the up and down arrow keys.

  10. Permalink to comment#

    A nice addition to that would be to detect mouse down (for a long time that is) and increase accordingly.

    A little feedback for the user would be to make a small onclick picture change (like hover state sprites), (and it shouldn’t be too much of a problem too).

  11. Andy
    Permalink to comment#

    Might be a little Safari bug (or intended, I don’t know).

    When you click on the + or – buttons, it highlights the image and some of the background…..

    Not sure what the easiest way around it though!

    • Andy
      Permalink to comment#

      Sorry…Just figured out what it is. Its if you click too fast, Safari sees it as a double click and instead of going forward, it highlights the image.

      Any ideas?

    • Permalink to comment#

      What probably helps in all browsers and in my opinion is already a lot better to use is instead of adding the buttons in a div, create them as input type=”image”.
      And you keep tabbing functionality(tho in this case users who use their keyboard can just fill in the numbers)

  12. Permalink to comment#

    Hey Chris, don’t get me wrong I love the mini tutorials you put in, but I think you are losing focus on ‘css-tricks’ ;)

    • Permalink to comment#

      This site hasn’t been about only CSS Tricks in a long long time. The new slogan is more like “all things web design.”

    • Pawan
      Permalink to comment#

      Time to change the domain name to web-tricks.com ? :-))

    • Pawan
      Permalink to comment#

      And yes… your tutorials and site is amazing… always the first to browse every morning… took me around 2 weeks to watched almost all the screencasts you did…

      Great work Chris !

      Keep it Up !

  13. Permalink to comment#

    Interesting. I’ll try it out. Thanks.

    • Kicks
      Permalink to comment#

      Cool, thanks Chris. Love this site man it rocks!

      Keep it up.

  14. jQuery UI has this already. It also supports auto-incrementing while holding your mouse button down, and optional mousewheel support.

    http://docs.jquery.com/UI/Spinner

  15. Permalink to comment#

    Nice. I think a good addition to this would be to make it so that you can use the mosue wheel to change the value while hovering over it.

  16. adam chow
    Permalink to comment#

    Would be better if you can restrict the input boxes only accept numbers.

  17. Evan Jones
    Permalink to comment#

    Just realized the nod at the Twelve Days of Christmas lol.

    It’s the little things in life. Keep it up Chris!

  18. Jack Watson-Hamblin
    Permalink to comment#

    I’ve made this into a plugin for myself, but I want to publish it to the plugins.jquery.com website. I just wanted to know if that was OK? I also wanted to know if it was OK to use the images you made for the buttons in it and to add some extra things to it?

    Thanks

  19. Permalink to comment#

    Nice! Thank you, now I will use.

  20. Permalink to comment#

    Very handy, thanks for this!

  21. Permalink to comment#

    Nice article.
    btw cant it go lower than 0 i.e. in negative lolz ?

  22. Permalink to comment#

    I definitely like the idea and with the feature Baylor Rae’ mentioned this would really be awesome.

  23. Hunter
    Permalink to comment#

    I was wondering if this is doable… adding it so that you can hold the button down on click, which will continually increase the integer and then speeding the quantity up?

  24. Permalink to comment#

    Wow! This looks awesome and we definitely will use this in our next design. So handy!

    Cheers,

  25. Permalink to comment#

    i’m a big fan of the blog, thanks again.

  26. Not sure it matters at this pint or anything for this particular article, but I just finished up some research on the name used for the spinner widget. Take a look when you get a chance. Other users might find this info helpful if they are researching the best way to implement this functionality…

    Is “Numeric Spinner” the best name for this?

    http://uxfindings.blogspot.com/2014/06/is-numeric-spinner-best-name-for-this.html

  27. Wow Chris, I checked out the demo and saw the update that we should use type=”number” instead. Saved me a good bit of time. Thanks!

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".