O hirunewani blog

余計なDOMを追加せずにinput[type="file"]を装飾する

Created at

file-selector-buttonを利用してinput[type="file"]を装飾する方法とその是非について。

::file-selector-buttonが利用することで、input[type="file"]を装飾することが出来る。

しかし::file-selector-button疑似要素は、2021年時点で全てのモダンブラウザでサポートされたが、あまり利用されているイメージがない。

https://developer.mozilla.org/en-US/docs/Web/CSS/::file-selector-button

実装例

次のように装飾することが出来る。

<div>
  <style>
    input[type="file"] {
      border: 2px dotted #cbd5e1;
      padding: 16px;
      background-color: #f1f5f9;
      border-radius: 8px;
      cursor: pointer;
      transition: 0.2s ease-out;
      &::file-selector-button {
        background-color: white;
        border: 1px solid #ff7f50;
        line-height: 24px;
        cursor: pointer;
        color: coral;
        font-weight: bolder;
        padding: 12px 16px;
        border-radius: 16px;
        margin-inline-end: 16px;
        transition: 0.2s ease-out;
      }
      &:hover {
        border-color: #a6c1e0;
        &::file-selector-button {
          color: #ff5b1f;
          border-color: #ff5b1f;
        }
      }
    }
  </style>
  <input type="file" />
</div>

余計なDOMを追加する手法との比較

Pros

  • File input本来のアクセシビリティの恩恵をそのまま受けられる。
  • 余計なDOMを追加して実装する場合、考慮するべきことが多い。
    • input要素をdisplay: noneなどで隠すと、requiredなどが効かなくなる。
    • label要素で外見を作ってしまうと、クリックイベントなどを発火出来なくなる。
    • 実装に依るがinput要素自体に元々あるドラッグ&ドロップ機能を自前で実装する必要がある。

Cons

  • コンテンツの位置調整が困難。
    • ::file-selector-buttonと文字列を子要素のように扱えるわけではないため、input要素をGridやFlexboxにして位置を調整することは出来ない。positionやfloatなどのプロパティは効く。
  • 入力要素の文章を差し替えることは出来ない。
    • 無理やり消して、::before::afterで挿入することは出来るが、アクセシビリティの観点からも推奨できない。