Styling <file inputs> with CSS : the Secret Revealed

Q.How do I style file inputs?

A.Why bother? Rub a little javascript on a <text input> instead.

This is what an input of type="file" looks like

  ← ← click me

And here is what an input of type="text" looks like

  ← ← click me

Q.What's the difference?

A.You can style a text input.

Secret Sauce

<form>
   <input id="file" type="file" style="display:none">
   <input id="proxy" placeholder="Choose File - No file chosen">
</form>
<script>
var file  = document.getElementById('file');
var proxy = document.getElementById('proxy');
file.addEventListener('change', function(){ proxy.value = file.value.substr(12); });
proxy.addEventListener('click', function(){ file.click(); });
</script>

But what if I'm allergic to JavaScript?

Use the <label> element's ability to pass through a click to its associated input. Put the label around the input and style it to hide any overflow. Then, using positioning, shift the input to the left until its button is no longer visible. Raise the label's z-index to ensure the label captures the click. Note that you'll have to find another way to label the input. Here the pseudo element, :before, is used.

←   Before   →
  ← ← click me
←   After   →
  ← ← click me
HTML

<form>
  <label for='file2'>
    <input id='file2' type='file'>
  </label>
</form>

CSS

<style>
/***  css variables ***/
  :root {
    --darker   : rgba(0,0,0,.1);
    --darkest  : rgba(0,0,0,.5);
    --lighter  : rgba(255,255,255,.1);
    --lightest : rgba(255,255,255,.5);
  }

/***  label is used for capturing click  ***/
  label[for=file2]{
    z-index  : 2;                         /*  put the label in front of the input  */
    position : relative;
    display  : inline-block;              /*  inline-block allows sizing  */
    overflow : hidden;                    /*  where we hide the builtin button  */
    width    : 275px;
    height   :  30px;
    border   : 1px solid var(--darkest);
    border-radius : 4px;
    background-color : var(--darker);
  }
  
/***  pseudo-label is used for text  ***/
  label[for="file2"]:before {
    position : absolute; top:  4px; left: 3px;
    content  : 'CHOOSE FILE';         /*  <---- NOTICE!!! label text is HERE  */
    color    : deepskyblue;
    font     : bold normal 7pt/.8 sans-serif;
  }
  
/***  the input  ***/
  #file2:hover { cursor : pointer; }
  #file2 {
    z-index  : 1;
    position : relative;
    left     : -94px;    /*  hide the builtin button to the left; see NOTE  */
    display  : inline-block;                /*  inline-block allows sizing  */
    width    : 365px;
    height   :  22px;
    border   : 0;
    padding  : 9px 4px 0 0;
    color    : gold;
    font     : normal normal 10pt/.8 sans-serif;
  }
</style>

how far left depends on the font-size; IOW, set the font then
adjust "left" until the builtin button is no longer visible.