Skip to content

Instantly share code, notes, and snippets.

@joaocunha
Last active December 10, 2023 13:05
Show Gist options
  • Save joaocunha/6273016 to your computer and use it in GitHub Desktop.
Save joaocunha/6273016 to your computer and use it in GitHub Desktop.
How to hide <select> dropdown's arrow in Firefox when using "-moz-appearance: none;".

This is no longer a bug. I'm keeping the gist for historical reasons, as it helped to get it fixed. Make sure to read the notes by the end of the post.

How to remove hide the select arrow in Firefox using -moz-appearance:none;

TL;DR (or, the fix)

  1. Set -moz-appearance to none. This will "reset" the styling of the element;
  2. Set text-indent to 0.01px. This will "push" the text a tiny bit[1] to the right;
  3. Set text-overflow to '' (an empty string). This will change anything that extends beyond the element's width to... nothing - and this includes the infamous arrow!

Firefox select element with no arrow

Continue reading for the full lowdown.

Background

I was experimenting on custom styling the <select> elements of a form I was building. One of the things I tried implementing was truncating the text with an ellipsis in case it extended beyond the <select>'s width. It didn't look consistent through browsers, but I discovered something nice.

The bug

Firefox <select> with appearance attribute set to none (Ubuntu):

Buggy select element on Firefox

Chrome <select> with appearance attribute set to none (Ubuntu):

Okay select element on Chrome

As this 2011 bug report states, there is an issue regarding Firefox's -moz-appearance and <select> elements: it was supposed to ditch the <select>'s arrow (like Chrome's implementation) but it simply doesn't. People were raging about the subject all over the internetz.

Live example

http://codepen.io/joaocunha/pen/qLgCG

(Firefox only, duh)

Final considerations

  • Firefox doesn't remove the arrow, it hides it. You will have some white space on the right[2] (same width of the now-hidden arrow);
  • Chrome removes the arrow by default with -webkit-appearance:none; instead of hiding. No white space on the right;
  • Chrome doesn't support the text-overflow:''. No evenly-cut text;
  • Your best bet is to set some padding-right in order to provide right space for your styled version of the arrow. Just keep in mind that Firefox will take the ghost arrow width into account;
  • Turns out that Windows doesn't require the -moz-appearance: none; declaration at all. Tested on 8;
  • Firefox for Android needs the whole width of the arrow as text-indent. It means you need to set it to at least 5px, but take care since Firefox seems to double the text-indent value on <select> elements.
  • Zooming out (ctrl mousewheeldown, ctrl -, etc) reveals[3] the default arrow. No big deal;
  • The appearance attribute is not well supported through browsers, so take this workaround with a grain of salt when developing your crossbrowser solution.

Support

Tested on latest versions of Ubuntu, Windows, Mac and Android.

Follow me

@joaocunha

Thanks

[1]Binyamin for improving it from 1px to 0.01px.

[2]RussellUresti for noticing the white space.

[3]MathiasaurusRex for noticing the zoom issue.

Notes

Edit 4: Mozilla released Firefox v35 and, indeed, the bug is patched. https://developer.mozilla.org/en-US/Firefox/Releases/35

Edit 3: Mozilla addressed the issue! Target milestone is v35. Yay!

Edit 2: Todd Parker from Filament Group tweeted about a CSS only alternative that works pretty much everywhere. You can check it here.

Edit: this trick stopped working as of Firefox 30 realeased in 2014-06-10. Join the comments section to help finding an alternative, and please upvote the bug on Bugzilla for a definitive fix. If you now have double arrows on Firefox, this might solve your issue.

Don't use any other value of -moz-appearance as the styles inherited are not customisable.

@YemSalat
Copy link

Doesn't work anymore, your codepen demo as well. Win7, firefox 30

@barnettjw
Copy link

@YemSalat, @hom-nic

In firefox 30 this works:

<div class="styled-select">
     <select>
         <option>Here is the first option</option>
         <option>The second option</option>
         <option>The thrid option</option>
     </select>
</div>
.styled-select { 
  overflow: hidden; 
  width: 200px;
}

@-moz-document url-prefix(){
  .styled-select select { width: 110%; }
}

For a cross-browser solution (Tested in IE 8-11, Firefox 30, Chrome 35), here's what I use: http://codepen.io/jamesbarnett/pen/JhHjK

@sorahn
Copy link

sorahn commented Jun 19, 2014

@barnettjw the problem with your solution is that you cannot click the arrow.

I have an updated solution that I've implemented at work, but I haven't had time to build a pen yet.

// Strip away all the browser styles for a select box.
// The syntax for this needs to be as follows.
//
// <div class="select--clean">
//   <select>...</select>
//   <i class="fa fa-caret-down">
// </div>
//
// To add custom style overrides, either wrap the whole div inside another
// class, or add a class to the div with 'select--clean'.
//
// Example: http://codepen.io/drbrts/pen/JAbyF

.select--clean
  display: inline-block
  overflow: hidden
  position: relative

  select
    @include appearance(none)
    width: 100%

    border: 0
    outline: 0
    border-radius: 0
    margin: 0
    padding-right: 15px

    letter-spacing: inherit
    background: transparent

    &:-moz-focusring
      color: transparent

    &::-ms-expand
      display: none

    &,x:-moz-any-link,x:default
      padding-right: 0
      width: -moz-calc(100% + 17px)
      width: calc(100% + 17px)

  option
    border: 0

  i
    pointer-events: none
    position: absolute
    right: 0
    top: 2px
    color: inherit

@mixin select-colors($color: #000000, $bg: #ffffff)
  color: $color
  background: $bg

  select
    color: $color

    &:-moz-focusring
      text-shadow: 0 0 0 $color

  option
    color: $color
    background: $bg

  i
    color: $color

@joaocunha
Copy link
Author

Guys, don't use any other value of -moz-appearance (like window, tabpanels, etc) as the inherited styles are not customisable.

@samira-ranjbar
Copy link

Hi, is there any way to remove the default select arrow in firefox and use our image? I have put these two code, but still doesn't work.
-moz-appearance: none;
-webkit-appearance: none;
thanks

@sanarena
Copy link

I have used suggestion from barnettjw and it works on Firefox 30

Copy link

ghost commented Jun 25, 2014

Here is a work around

<div class="selectwrap">
      <select>
        <option>Option 1</option>
        <option>Option 1</option>
        <option>Option 1</option>
      </select>
</div>
select{
border:1px solid #ccc;
height: 34px;
width: 250px;
padding: 6px 12px;
}
.selectwrap{
position: relative;
float: left;
}
.selectwrap:after{
content:"↓";
text-align: center;
line-height:32px;
position: absolute;
width: 32px;
height: 32px;
background: #fff;
right: 1px;
top: 1px;
pointer-events: none;
}

http://codepen.io/anoopjohn/pen/GcJoL

@keksa
Copy link

keksa commented Jun 25, 2014

Hi, I managed to find way to hide select arrow in Firefox 31.0 (beta), I actually don't really know how it works, but it works. Here is pen: http://codepen.io/keksa/pen/hpqyx

@joaocunha
Copy link
Author

Nice finding, @keksa!

@nathankc
Copy link

@aj9666 code works for me - the only thing I did different was modified:

content: " "; //didn't want the arrow at all
color: #fff; //ensure there is no character visible

@marcospita
Copy link

Hi.
Do someone found a way not including div?

@iamalfonse
Copy link

Unfortuantely with @keska's fix, you can't apply padding or margins to the actual <select> tag else the arrow will show up again.

@rludgero
Copy link

Hi,
if you are interested, my solution is using vendor pseudo class :-moz-any() and pointer events only for mozilla because both is valid since version 3.6.

here is a jsbin example
http://jsbin.com/pozomu/4/edit

@kwarkjes
Copy link

kwarkjes commented Jul 8, 2014

Rodrigo-Ludgero's solution works also

@sstur
Copy link

sstur commented Jul 11, 2014

@iamalfonse: I was able to sort of emulate border and padding in @keska's solution by using inset box-shadow for border and color: transparent with an offset text-shadow for padding. See: http://jsfiddle.net/sstur/2EZ9f/

@VR51
Copy link

VR51 commented Sep 10, 2014

@anupjon's solution worked for me.

@Matt633
Copy link

Matt633 commented Oct 2, 2014

@joaocunha - Just used your URL prefix method to hide my custom arrow in FF33. Thanks a ton.

@vienhoang
Copy link

This issue is quite annoying, tested a couple hacks from here and there, but @anupjon's solution works for me as well in Win 7, FF32.
However I haven't figured out to make it appear as a working cursor, "cursor: pointer;" doesn't seems to work with "pointer-events: none;". If anyone figured that out let me know :)

@LeaveAirykson
Copy link

@joaocunha's third solution worked for me. Thank you!
https://gist.github.com/joaocunha/6273016/#comment-1244649

@iLenTheme
Copy link

This solution is elegant ;)

@-moz-document url-prefix() {
 select {
    overflow:hidden; /* optional */
    width: 120%;
 }
}

@Martskin
Copy link

Short option labels (like numbers 1, 2, 3...) were causing the select arrow to peak out with width: 120% for me.
This seems to be more flexible:

@-moz-document url-prefix() {
 select {
   width: calc(100% + 16px);
 }
}

@rdebeasi
Copy link

-moz-appearance: none; will support select elements in Firefox 35. That version comes out in January, and the Developer Edition has this feature now. Here's the Bugzilla ticket.

Edit: Whoops, just realized that the content at the top of the gist already explains that. Sorry for the extra comment!

@lagden
Copy link

lagden commented Nov 25, 2014

Well, well!!!

The solution is very near of us... maybe in next Firefox release!!!
I made a workaround in the meantime:

Tested on Chrome 39, Safari 8 and FF 33 and FF 35 Developer Edition

🍻

@seleckis
Copy link

seleckis commented Dec 9, 2014

Solution does not work if border: 0.
FF 33.1, Win7

@l4ci
Copy link

l4ci commented Jan 8, 2015

A modified combination of @Martskin and @iLenElFuerte comment worked best for me, as overflow: hidden would break the layout for me:

@-moz-document url-prefix() {
   select{
        overflow: -moz-hidden-unscrollable;
        width: calc(100% + 16px);
    }
}

@gijsroge
Copy link

Use this codepen if you want to support firefox: http://codepen.io/gijs/pen/MYKreR
It uses pseudo child's to hide the down arrows. (firefox, ie10+, chrome, safari, etc..)

@MPMoughan
Copy link

@anupjon FTW!!! Thanks for posting that solution it worked for me. Just need to adjust to account for screen breaks.

UPDATE - If you are following @anupjon 's solution, just be aware of the float: left; set on the "selectwrap" div - It will cause a slight issue with various breakpoints.

@mernstackman
Copy link

Too much words...

It should be formatted like this for faster and better reading!
-- code example with few names --
-- very long explanation goes after all of the primary codes --

anyway, thank you for sharing... 😊

@skynet01
Copy link

Great solution @gijsroge , i like how you just used a character to create the arrow, there is similar tutorial on how to do this here (also works in firefox) https://fabriceleven.com/design/clever-way-to-change-the-drop-down-selector-arrow-icon/

@rajupatel1000
Copy link

rajupatel1000 commented Oct 5, 2018

How to select box text show in 2 line?
Not working my css in ( Mozilla Browser )...But support in Chrome ...

MY CSS
select {
white-space: normal;
line-height: normal;
}

my select box images

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment