In my codepen example the arrow is created using the :after pseudo element and absolutely placing a ‘css triangle” on top of the element. (I also used the before element to create a background to hide any text that might be near the arrow.)
The example in the codepen uses a ‘trick’ where you wrap the select in an element that is set to be about 30px smaller width than the width set on the select. This means the select sticks out of the parent which is just enough room for the browser select arrow to be outside the main parent. You then hide the overflow on the parent and that means the arrow is now missing. Using the after element you can then absolutely place something on top of the select to represent the new arrow and it will be the same in all modern browsers. I used the css triangle trick but there is no reason why it couldn’t be a real image instead.
You can only do this in modern browsers because normally placing something on top means that you can’t then click the element underneath which is where ‘pointer-events’ comes into play and allows the click to pass through this new element and interact with the select beneath.
Hope that explains it :)