Pickels
Pickels

Reputation: 34632

Why does Firefox set a background color on the select arrow button when I set a custom border or background color?

A default select input looks like this in FF 37:

enter image description here

When I try to give it a different border color like this:

select { border: 1px solid silver; }

It results into this:

enter image description here

For some reason when you give a select input a different border it also adds a background and border to the arrow button.

A similar thing happens when I do the following:

select { background: transparent; }     

It ends up like this:

enter image description here

Why is this happening and how can I just change the border or background of a select input without it changing the arrow down button?

jsfiddle with example

Upvotes: 5

Views: 11720

Answers (3)

Mujahidul Islam
Mujahidul Islam

Reputation: 563

To remove this problem just set a border.

select {
     border:1px solid black;
    }

Upvotes: 0

noisy
noisy

Reputation: 6783

Answer given by Damian is not bad, but I prefered something what is easier to maintain. Basically, I also need to have a possibility to prepare one style, which I could change a color depending on theme, therefore png image (in base64) was not a good option.

This is how this can be done with SVG:

select {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;

    /* SVG background image */
    background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100' fill='%23FF0000'><polygon points='20,0 80,0 50,52'/></svg>");
    background-size: 12px;
    background-position-x: right;
    background-position-y: calc(100% - 10px);
    background-repeat: no-repeat;
}

I use scss to generate styles based on variables, so i wanted to use $base-font-color as a color of triangle. The problem was encoding.

Chrome can handle simple .. fill='"+ $base-font-color +"' .. in:

background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100' fill='"+ $base-font-color +"'><polygon points='20,0 80,0 50,52'/></svg>");

but firefox needed %23. That was a problem, bacause I store colors in variables as: $base-font-color: #3e4f5e; and not as a $base-font-color: '3e4f5e'. Solution was to convert color to string and use string replacement to replace '#' to '%23'

@function str-replace($string, $search, $replace: '') {
  $index: str-index($string, $search);

  @if $index {
    @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
  }

  @return $string;
}

@function to-string($value) {
  @return inspect($value);
}

select {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;

    /* SVG background image */
    background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100' fill='"+ str-replace(to-string($base-font-color), '#', '%23')  +"'><polygon points='20,0 80,0 50,52'/></svg>");
    background-size: 12px;
    background-position-x: right;
    background-position-y: calc(100% - 10px);
    background-repeat: no-repeat;
}

Upvotes: 0

Damian Vila
Damian Vila

Reputation: 86

To start with, styling form elements is extremely complicated and troublesome. Some progress has been made lately, but behaviour is inconsistent from browser to browser. The problem comes from the way browser have historically handled form elements (letting the OS decide the element appearance).

Now to your question: for some reason, whenever you modify FF default stylesheet, the browser applies a different style to the dropdown (this may be a bug, a bad implementation or planned behaviour, but it's clearly annoying).

One solution would be to get rid of all the "chrome" altogether, using a vendor property -x-appearance: none, like this:

select {
  border: 1px solid silver;
  -webkit-appearance: none;
  -moz-appearance: none;
  padding-right: 25px;
  background: url(data:image/gif;base64,R0lGODlhCwALAJEAAAAAAP///xUVFf///yH5BAEAAAMALAAAAAALAAsAAAIPnI+py+0/hJzz0IruwjsVADs=);
  background-repeat: no-repeat;
  background-position: 95% 42%;
}

Note that you have to re-apply the down arrow (I did this by inserting an image as a background, encoded in base64.) You can use any image of your liking.

The problem with this approach is that it doesn't work in IE: http://caniuse.com/#search=appearance

Here you have a Fiddle to test it: https://jsfiddle.net/81L844p4/4/

Hope it helps.

Upvotes: 7

Related Questions