customising the look of f.file.field in rails

2020-08-17 07:36发布

问题:

    <div id="photo_attachment_container">
        <%= f.file_field :photo %>
    </div>

Currently this just looks like a button, how can I add some css and customise the look (e.g dimensions background etc) of this button? Thanks

回答1:

The HTML file field has been, and remains, one of the most least customizable of the HTML form controls. The other problem is that it is rendered so differently between browsers and OSes. The best way to style these controls is to render the file control as a transparent element on top of another button or set of elements that is styled the way you want. The file control does not need to be visible to be activated with a user click, but it does need to be on the top most layer (sending it click or focus events doesn't work in my tests).

Here's some example HTML:

<div id="test">
    <div class="wrapper">
        <input type="file" />
    </div>
    <button>Select a file</button>
</div>

The CSS renders the wrapper div and button as absolutely positioned elements. The button is visible and styled while the wrapper which contains the file field is transparent. I've set the wrapper field to reduce transparency when you hover over it to illustrate its positioning relative to the styled button underneath.

#test {
    position: relative;
}

#test .wrapper {
    opacity: 0;
    cursor: pointer;
    position: absolute;
    top: 0;
    z-index: 2;
}

#test .wrapper:hover {
    opacity: 0.5;
}

#test button {
    background-color: #ccc;
    border: none;
    color: #666;
    padding: 3px 5px;
    border-radius: 5px;
    position: relative;
    top: 0;
    z-index: 1;
}

Example on JS fiddle.

http://jsfiddle.net/JgDuh/

EDIT:

To answer the question you asked in your comment, you would structure the above answer in your Rails view template like this:

<div id="photo_attachment_container">
  <div class="wrapper">
    <%= f.file_field :photo %>
  </div>
</div>

This would render as (Note that I used user as the substitute for whatever model you passed in form_for):

<div id="photo_attachment_container">
  <div class="wrapper">
    <input type="file" id="user_photo" name="user[photo]" />
  </div>
</div>