Custom styled input type file upload button with pure CSS

Published: · Reading time: 6 min

In this guide I’ll show you how to create a stylish and user friendly file upload button with pure CSS and HTML.


To upload files you’ll need to use the input tag with type="file" attribute. Additionally you can specify which file types you’re allowing to upload via accept attribute.


<input type="file" accept="image/*">

This markup produces a button with a Choose file title followed by a text which indicates the file name when selected. By default it is No file chosen.


Input with type file default look differs on different browsers:

Input type file on Chrome
Input type file on Edge
Input type file on Firefox
Input type file on Safari


The upload file widget structure consists of a block that displays a button and a file name. A user can click anywhere inside the block or drag a file from the desktop and it will open up the upload window.

Styling the upload file block

If you apply styles for the input[type=file] selector it will set them for the whole widget block, that is the button and text.


input[type=file] {
  width: 350px;
  max-width: 100%;
  color: #444;
  padding: 5px;
  background: #fff;
  border-radius: 10px;
  border: 1px solid #555;

The result already looks much better as it indicates the zone where user is able to click or drag the file.


Styling the upload file button

By default, the Choose file button has a plain user-agent style. To style the button with CSS you should use the ::file-selector-button pseudo-element to select it. It is supported in all modern browsers.


input[type=file]::file-selector-button {
  margin-right: 20px;
  border: none;
  background: #084cdf;
  padding: 10px 20px;
  border-radius: 10px;
  color: #fff;
  cursor: pointer;
  transition: background .2s ease-in-out;

input[type=file]::file-selector-button:hover {
  background: #0d45a5;


Styling the the click/drop zone

If you wich to go a bit further, you can create a large zone where user can click and drag files. This large zone will make it easier for people to use the widget, as it don’t require to be that precise when dragging a file, especially on smaller screens.

To implement a large drop zone, you’ll need to wrap your file upload input into a label tag and specify a description text that will let users know how to use the widget.


<label for="images" class="drop-container">
  <span class="drop-title">Drop files here</span>
  <input type="file" id="images" accept="image/*" required>

For the layout, we need to set display to flex with flex related properties for positioning. The height and padding properties for proportion. And finally add some fancy styles like border and hover effects to highlight the file upload zone and you’re ready to go.


.drop-container {
  position: relative;
  display: flex;
  gap: 10px;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  height: 200px;
  padding: 20px;
  border-radius: 10px;
  border: 2px dashed #555;
  color: #444;
  cursor: pointer;
  transition: background .2s ease-in-out, border .2s ease-in-out;

.drop-container:hover {
  background: #eee;
  border-color: #111;

.drop-container:hover .drop-title {
  color: #222;

.drop-title {
  color: #444;
  font-size: 20px;
  font-weight: bold;
  text-align: center;
  transition: color .2s ease-in-out;



See the full example on CodePen:

See the Pen Untitled by Nikita Hlopov (@nikitahl) on CodePen.

Like this article? Share it on: