Search code examples
htmlcsswidthblockfixed-width

CSS: How to make custom file upload button take full width (button works)


I am new to CSS and hope someone here can help me with this.

I am trying to apply a simple custom style to a file upload button (as part of an HTML form) to make it look similar to other buttons on my page and to get a similar look cross-browser.

So far I have the following which works as intended. My only problem now is that I would like the button to take the full width of its parent div (in my case this will span across 9/12 ('col-9') of the page).

I tried adding width: 100%; to the CSS but then the button doesn't work anymore.

My HTML:

<div class="col-3 frmCaption">Attachments:</div>
<div class="col-9">
    <div class="customUpload btnUpload btnM">
        <span>Upload files</span>
        <input type="file" class="upload" />
    </div>
</div>

My CSS:

.btnDefault, .btnUpload {
    background-color: #FFFFFF;
    border: 1px solid #CCCCCC;
    color: #333333;
    cursor: pointer;
    font-weight: 400;
    display: inline-block;
    padding: 6px 12px;
    text-align: center;
    text-decoration: none;
    vertical-align: middle;
}       
.btnDefault:focus, .btnDefault:hover, .btnUpload:focus, .btnUpload:hover {
    background-color: #E6E6E6;
}
.btnM {
    border-radius: 4px;
    font-size: 14px;
    padding: 6px 12px;
}
.customUpload {
    overflow: hidden;
    position: relative;
}
.customUpload input.upload {
    cursor: pointer;
    margin: 0;
    opacity: 0;
    filter: alpha(opacity=0);
    padding: 0;
    position: absolute;
    right: 0;
    top: 0;
}

Solution

  • To style input elements, you need to actually style its label element.

    From MDN,

    The HTML Label Element () represents a caption for an item in a user interface. It can be associated with a control either by placing the control element inside the element, or by using the for attribute. Such a control is called the labeled control of the label element.

    So, whenever you click a label, the attached input gets triggered.

    So, just wrap the input element in a label instead of a div and stretch as much as you want. That will fix your issue.

    .btnDefault,
    .btnUpload {
      background-color: #FFFFFF;
      border: 1px solid #CCCCCC;
      color: #333333;
      cursor: pointer;
      font-weight: 400;
      display: inline-block;
      padding: 6px 12px;
      text-align: center;
      text-decoration: none;
      vertical-align: middle;
    }
    .btnDefault:focus,
    .btnDefault:hover,
    .btnUpload:focus,
    .btnUpload:hover {
      background-color: #E6E6E6;
    }
    .btnM {
      border-radius: 4px;
      font-size: 14px;
      padding: 6px 12px;
    }
    .customUpload {
      overflow: hidden;
      position: relative;
      display: block;
    }
    .customUpload input.upload {
      cursor: pointer;
      margin: 0;
      opacity: 0;
      filter: alpha(opacity=0);
      padding: 0;
      position: absolute;
      right: 0;
      top: 0;
    }
    <div class="col-3 frmCaption">Attachments:</div>
    <div class="col-9">
      <label class="customUpload btnUpload btnM"> <span>Upload files</span>
    
        <input type="file" class="upload" />
      </label>
    </div>

    Working Fiddle