How to Remove Arrow on Input type Number with Tailwind CSS

Created July 10, 2024

When designing forms with Tailwind CSS, you might want to remove the default arrows (also known as spinners) from number input fields. These arrows can interfere with custom designs and are challenging to style consistently across different browsers.

In this tutorial, we'll explore how to achieve this using Tailwind CSS, both with inline styles and through a global CSS approach. We'll also address accessibility concerns and provide examples for styling custom buttons.

The Problem

By default, browsers add increment and decrement arrows to <input type="number"> elements. While functional, these arrows often clash with custom designs and can be difficult to style uniformly across various browsers.

Default number input with arrows

The Solution

We'll use Tailwind CSS utility classes to remove these arrows and create clean, customized number inputs. We'll also look at how to apply this styling globally for larger projects and how to add accessible custom controls.

Inline Approach

Let's start with an example that uses inline Tailwind classes:

<form class="max-w-md mx-auto mt-8 p-6 bg-white rounded-lg shadow-md">
  <div class="mb-4">
    <label for="quantity" class="block text-sm font-medium text-gray-700 mb-2">Quantity</label>
    <input type="number" id="quantity" name="quantity" 
      class="block w-full px-3 py-2 bg-white border border-gray-300 rounded-md text-sm shadow-sm
      focus:outline-none focus:border-sky-500 focus:ring-1 focus:ring-sky-500
      [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none">
  </div>
  
  <div class="mb-4">
    <label for="price" class="block text-sm font-medium text-gray-700 mb-2">Price</label>
    <input type="number" id="price" name="price" step="0.01"
      class="block w-full px-3 py-2 bg-white border border-gray-300 rounded-md text-sm shadow-sm
      focus:outline-none focus:border-sky-500 focus:ring-1 focus:ring-sky-500
      [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none">
  </div>
  
  <button type="submit" class="w-full bg-blue-500 text-white py-2 px-4 rounded-md hover:bg-blue-600 transition-colors">
    Submit
  </button>
</form>

The key classes for removing the arrows are:

Number input without arrows

Global Approach

For larger projects, you might want to apply this styling to all number inputs. You can do this by adding styles to your global CSS file:

  1. Open your global.css file (or equivalent, like app.css or styles.css) depending on your framework and setup.

  2. Add the following CSS:

/* In your global.css file */
@layer utilities {
  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;
  }
}
  1. Ensure this CSS file is imported in your main Tailwind CSS file or included in your HTML.

After adding these global styles, you can simplify your HTML:

<form class="max-w-md mx-auto mt-8 p-6 bg-white rounded-lg shadow-md">
  <div class="mb-4">
    <label for="quantity" class="block text-sm font-medium text-gray-700 mb-2">Quantity</label>
    <input type="number" id="quantity" name="quantity" 
      class="block w-full px-3 py-2 bg-white border border-gray-300 rounded-md text-sm shadow-sm
      focus:outline-none focus:border-sky-500 focus:ring-1 focus:ring-sky-500">
  </div>
  
  <div class="mb-4">
    <label for="price" class="block text-sm font-medium text-gray-700 mb-2">Price</label>
    <input type="number" id="price" name="price" step="0.01"
      class="block w-full px-3 py-2 bg-white border border-gray-300 rounded-md text-sm shadow-sm
      focus:outline-none focus:border-sky-500 focus:ring-1 focus:ring-sky-500">
  </div>
  
  <button type="submit" class="w-full bg-blue-500 text-white py-2 px-4 rounded-md hover:bg-blue-600 transition-colors">
    Submit
  </button>
</form>

Notice that we've removed the arrow-removing classes from individual inputs, as they're now handled by the global CSS.

Adding Custom Arrows

While removing default arrows improves design consistency, it's crucial to maintain accessibility. Here's how to create custom, accessible increment/decrement buttons that match our form's design:

<div class="mb-4">
  <label for="quantity" class="block text-sm font-medium text-gray-700 mb-2">Quantity</label>
  <div class="relative flex items-center">
    <input type="number" id="quantity" name="quantity" 
      class="block w-full px-3 py-2 bg-white border border-gray-300 rounded-md text-sm shadow-sm
      focus:outline-none focus:border-sky-500 focus:ring-1 focus:ring-sky-500
      [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none">
    <div class="absolute right-0 flex items-center">
      <button type="button" 
              class="px-2 h-full border-l border-gray-300 text-gray-500 hover:text-sky-500 focus:outline-none focus:ring-2 focus:ring-sky-500 focus:ring-offset-2"
              onclick="document.getElementById('quantity').stepUp()"
              aria-label="Increase quantity">
        <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
          <path stroke-linecap="round" stroke-linejoin="round" d="M4.5 15.75l7.5-7.5 7.5 7.5" />
        </svg>
      </button>
      <button type="button" 
              class="px-2 h-full border-l border-gray-300 text-gray-500 hover:text-sky-500 focus:outline-none focus:ring-2 focus:ring-sky-500 focus:ring-offset-2"
              onclick="document.getElementById('quantity').stepDown()"
              aria-label="Decrease quantity">
        <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4">
          <path stroke-linecap="round" stroke-linejoin="round" d="M19.5 8.25l-7.5 7.5-7.5-7.5" />
        </svg>
      </button>
    </div>
  </div>
</div>

Key accessibility and styling improvements:

  1. We've added aria-label attributes to the buttons, providing context for screen readers.
  2. The focus states now include a visible ring (focus:ring-2 focus:ring-sky-500 focus:ring-offset-2) to improve keyboard navigation visibility.
  3. The buttons are styled consistently with the input field, maintaining the form's overall design.

Important Considerations

There are a few things that you should consider:

  1. Accessibility: While removing default arrows can improve visual design, it's crucial to maintain accessibility. Always provide alternative methods for incrementing/decrementing values, such as custom buttons with proper ARIA labels.

  2. Keyboard Navigation: Ensure that your custom controls are fully accessible via keyboard. This includes proper focus states and the ability to activate buttons using the keyboard.

  3. Cross-browser Compatibility: This solution works in modern browsers. Older browsers may require additional CSS or JavaScript.

Conclusion

By implementing these techniques, you can effectively remove the default arrows from number inputs across your project while maintaining accessibility and consistent styling. Remember to always test your forms with various input methods (mouse, keyboard, touch) and assistive technologies to ensure a great user experience for all.

For those looking to improve their Tailwind CSS development process further, check out the DevDojo Tails page builder, which can help you create amazing designs with ease.

Happy coding!