web-dev-qa-db-ja.com

ファイルアップロードボタンのクロスブラウザカスタムスタイル

私は自分の好みに合わせてファイルアップロードボタンのスタイルを設定しようとしていますが、JSなしでこれを行うための本当に堅実な方法は見つかりませんでした。私は twoother このテーマに関する質問を見つけましたが、そこでの答えはJavaScriptを含んでいるか、提案されました Quirksmodeのアプローチ

このQuirksmodeのアプローチの主な問題は、ファイルボタンのサイズがブラウザーで定義されているため、その下に配置されるボタンとして使用されるものに自動的に調整されないことです。それに基づいていくつかのコードを作成しましたが、ファイルボタンが通常占有するスペースを占有するだけなので、希望どおりに親divを埋めることはできません。

HTML:

<div class="myLabel">
    <input type="file"/>
    <span>My Label</span>
</div>

CSS:

.myLabel {
    position: relative;
}
.myLabel input {
    position: absolute;
    z-index: 2;
    opacity: 0;
    width: 100%;
    height: 100%;
}

このフィドル は、このアプローチが非常に欠陥があることを示しています。 Chromeでは、2番目のデモボタンの下にある!!をクリックすると、ファイルダイアログが開きますが、他のすべてのブラウザーでも、ファイルボタンはボタンの正しい領域を占有しません。

JavaScriptを使用せずに、ファイルアップロードボタンをスタイル設定するためのより堅実な方法はありますか?できればできるだけ「ハッキング」コーディングを使用しないでください(通常、ハッキングはフィドルなどの問題を伴うため)?

96
Joeytje50

これを投稿しているのは、(驚いたことに)これを推奨する他の場所が見つからなかったからです。

ブラウザで定義された入力ディメンションに制限することなく、これを行う簡単な方法があります。隠しファイルのアップロードボタンの周りで<label>タグを使用するだけです。これにより、 webkitの組み込みスタイリング で許可されるスタイリングよりもさらにスタイリングの自由度が高くなります[1]

ラベルタグは、クリックイベントを子入力に向けるという正確な目的のために作成されました。[2]、それを使用すると、クリックイベントを入力ボタンにリダイレクトするJavaScriptが不要になります。次のようなものを使用します。

label.myLabel input[type="file"] {
    position:absolute;
    top: -1000px;
}

/***** Example custom styling *****/
.myLabel {
    border: 2px solid #AAA;
    border-radius: 4px;
    padding: 2px 5px;
    margin: 2px;
    background: #DDD;
    display: inline-block;
}
.myLabel:hover {
    background: #CCC;
}
.myLabel:active {
    background: #CCF;
}
.myLabel :invalid + span {
    color: #A44;
}
.myLabel :valid + span {
    color: #4A4;
}
<label class="myLabel">
    <input type="file" required/>
    <span>My Label</span>
</label>

Internet Explorerの古いバージョンでも動作するように、固定位置を使用して入力を非表示にしました(エミュレートされたIE8-visibility:hiddenまたはdisplay:noneファイル入力での動作を拒否しました)。エミュレートされたIE7以降でテストしましたが、完全に機能しました。


  1. 残念ながら<button>s内で<label>sを使用することはできないため、ボタンのスタイルを自分で定義する必要があります。私にとって、これはこのアプローチの唯一の欠点です。
  2. for属性が定義されている場合、その値を使用して、<label>id属性と同じforで入力をトリガーします。
271
Joeytje50

すべてのブラウザで機能する方法を以下で見つけてください。基本的に、画像の上に入力を配置します。ユーザーが常にアップロードボタンをクリックするように、font-sizeを使用して大きくしています。

.myFile {
  position: relative;
  overflow: hidden;
  float: left;
  clear: left;
}
.myFile input[type="file"] {
  display: block;
  position: absolute;
  top: 0;
  right: 0;
  opacity: 0;
  font-size: 100px;
  filter: alpha(opacity=0);
  cursor: pointer;
}
<label class="myFile">
  <img src="http://wscont1.apps.Microsoft.com/winstore/1x/c37a9d99-6698-4339-acf3-c01daa75fb65/Icon.13385.png" alt="" />
  <input type="file" />
</label>
10
regisbsb

最良の例は、非表示、jQueryなし、これは完全に純粋なCSSです

http://css-tricks.com/snippets/css/custom-file-input-styling-webkitblink/

.custom-file-input::-webkit-file-upload-button {
    visibility: hidden;
}

.custom-file-input::before {
    content: 'Select some files';
    display: inline-block;
    background: -webkit-linear-gradient(top, #f9f9f9, #e3e3e3);
    border: 1px solid #999;
    border-radius: 3px;
    padding: 5px 8px;
    outline: none;
    white-space: nowrap;
    -webkit-user-select: none;
    cursor: pointer;
    text-shadow: 1px 1px #fff;
    font-weight: 700;
    font-size: 10pt;
}

.custom-file-input:hover::before {
    border-color: black;
}

.custom-file-input:active::before {
    background: -webkit-linear-gradient(top, #e3e3e3, #f9f9f9);
}
<input type="file" class="custom-file-input">
9
Shamal Sandeep

これはビジネスの面倒をよく見ているようです。 フィデはこちら:

HTML

<label for="upload-file">A proper input label</label>

<div class="upload-button">

    <div class="upload-cover">
         Upload text or whatevers
    </div>

    <!-- this is later in the source so it'll be "on top" -->
    <input name="upload-file" type="file" />

</div> <!-- .upload-button -->

CSS

/* first things first - get your box-model straight*/
*, *:before, *:after {
    -moz-box-sizing: border-box;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
}

label {
    /* just positioning */
    float: left; 
    margin-bottom: .5em;
}

.upload-button {
    /* key */
    position: relative;
    overflow: hidden;

    /* just positioning */
    float: left; 
    clear: left;
}

.upload-cover { 
    /* basically just style this however you want - the overlaying file upload should spread out and fill whatever you turn this into */
    background-color: gray;
    text-align: center;
    padding: .5em 1em;
    border-radius: 2em;
    border: 5px solid rgba(0,0,0,.1);

    cursor: pointer;
}

.upload-button input[type="file"] {
    display: block;
    position: absolute;
    top: 0; left: 0;
    margin-left: -75px; /* gets that button with no-pointer-cursor off to the left and out of the way */
    width: 200%; /* over compensates for the above - I would use calc or sass math if not here*/
    height: 100%;
    opacity: .2; /* left this here so you could see. Make it 0 */
    cursor: pointer;
    border: 1px solid red;
}

.upload-button:hover .upload-cover {
    background-color: #f06;
}
2
sheriffderek

すべてのファイル入力をカバーする簡単な方法は、input [type = button]をスタイルし、これをグローバルにドロップして、ファイル入力をボタンに変換することです。

$(document).ready(function() {
    $("input[type=file]").each(function () {
        var thisInput$ = $(this);
        var newElement = $("<input type='button' value='Choose File' />");
        newElement.click(function() {
            thisInput$.click();
        });
        thisInput$.after(newElement);
        thisInput$.hide();
    });
});

http://cssdeck.com/labs/beautiful-flat-buttons から取得したボタンCSSのサンプルを次に示します。

input[type=button] {
  position: relative;
  vertical-align: top;
  width: 100%;
  height: 60px;
  padding: 0;
  font-size: 22px;
  color:white;
  text-align: center;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
  background: #454545;
  border: 0;
  border-bottom: 2px solid #2f2e2e;
  cursor: pointer;
  -webkit-box-shadow: inset 0 -2px #2f2e2e;
  box-shadow: inset 0 -2px #2f2e2e;
}
input[type=button]:active {
  top: 1px;
  outline: none;
  -webkit-box-shadow: none;
  box-shadow: none;
}
1
Cymricus

この問題に出くわしたばかりで、Angularを使用しているユーザー向けのソリューションを作成しました。タイプファイルを使用して、コンテナ、ボタン、および入力要素で構成されるカスタムディレクティブを作成できます。 CSSを使用して、入力をカスタムボタンの上に配置しますが、不透明度は0です。コンテナの高さと幅をボタンのオフセット幅と高さに正確に設定し、入力の高さと幅をコンテナの100%に設定します。

ディレクティブ

angular.module('myCoolApp')
  .directive('fileButton', function () {
    return {
      templateUrl: 'components/directives/fileButton/fileButton.html',
      restrict: 'E',
      link: function (scope, element, attributes) {

        var container = angular.element('.file-upload-container');
        var button = angular.element('.file-upload-button');

        container.css({
            position: 'relative',
            overflow: 'hidden',
            width: button.offsetWidth,
            height: button.offsetHeight
        })

      }

    };
  });

ヒスイを使用している場合はヒスイテンプレート

div(class="file-upload-container") 
    button(class="file-upload-button") +
    input#file-upload(class="file-upload-input", type='file', onchange="doSomethingWhenFileIsSelected()")  

htmlを使用している場合、html内の同じテンプレート

<div class="file-upload-container">
   <button class="file-upload-button"></button>
   <input class="file-upload-input" id="file-upload" type="file" onchange="doSomethingWhenFileIsSelected()" /> 
</div>

cSS

.file-upload-button {
    margin-top: 40px;
    padding: 30px;
    border: 1px solid black;
    height: 100px;
    width: 100px;
    background: transparent;
    font-size: 66px;
    padding-top: 0px;
    border-radius: 5px;
    border: 2px solid rgb(255, 228, 0); 
    color: rgb(255, 228, 0);
}

.file-upload-input {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 2;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}
0
Benjamin Conant