{"id":4828,"date":"2017-12-07T10:26:21","date_gmt":"2017-12-07T10:26:21","guid":{"rendered":"http:\/\/a1webdesignteam.com\/blog\/?p=4828"},"modified":"2017-12-07T10:26:21","modified_gmt":"2017-12-07T10:26:21","slug":"customizing-file-inputs","status":"publish","type":"post","link":"https:\/\/a1webdesignteam.com\/blog\/customizing-file-inputs\/","title":{"rendered":"Customizing File Inputs"},"content":{"rendered":"<p>here are quite a few techniques for \u201ccustomizing\u201d the\u00a0<code>&lt;input type=\"file\" \/&gt;<\/code>\u00a0element. I tried most of them, but none was good enough to have on\u00a0Readerrr\u00a0(for importing feeds by uploading a file). Probably the worst technique was the one where the input element is put into a container (which imitates a button), and the input follows the cursor so that when you click anywhere on the container, you actually click the input. Sounds interesting and weird at the same time, right? Anyway, it had some unacceptable drawbacks (usability,\u00a0<em>touch<\/em>).<\/p>\n<p>As as result, I tried\u00a0<em>googling<\/em>\u00a0for an unseen solution. Once it seemed that there was nothing new, my I eyes were caught by a comment on StackOverflow. It had just a few\u00a0<em>up votes<\/em>\u00a0and was lost somewhere in the middle of the page, but most importantly it contained a magic word \u2013\u00a0<code>&lt;label&gt;<\/code>! As you may know, pressing a label basically triggers the focus event for the\u00a0<abbr title=\"Is inside a label or referenced by &quot;for&quot; attribute\">bound<\/abbr>\u00a0input. Interesting thing is that, if it is a file input, it works out as a click event, resulting in opening a file browser. This is great for crafting a semantic solution.<\/p>\n<pre class=\"brush:html; hljs xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-title\">input<\/span> <span class=\"hljs-attribute\">type<\/span>=<span class=\"hljs-value\">\"file\"<\/span> <span class=\"hljs-attribute\">name<\/span>=<span class=\"hljs-value\">\"file\"<\/span> <span class=\"hljs-attribute\">id<\/span>=<span class=\"hljs-value\">\"file\"<\/span> <span class=\"hljs-attribute\">class<\/span>=<span class=\"hljs-value\">\"inputfile\"<\/span> \/&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-title\">label<\/span> <span class=\"hljs-attribute\">for<\/span>=<span class=\"hljs-value\">\"file\"<\/span>&gt;<\/span>Choose a file<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-title\">label<\/span>&gt;<\/span><\/pre>\n<p>So, pressing any of these two elements gives us the same result. That means that the most difficult part is\u2026 solved! No JavaScript, no other complex solutions like cursor position tracking, just these two lines. See for yourself:<\/p>\n<p><img loading=\"lazy\" class=\"aligncenter size-full wp-image-24838\" src=\"https:\/\/codropspz-tympanus.netdna-ssl.com\/codrops\/wp-content\/uploads\/2015\/09\/smart-custom-file-input-1.gif\" alt=\"\" width=\"760\" height=\"556\" \/><\/p>\n<p>Now let\u2019s just style it and make this look like a\u00a0<em>normal<\/em>\u00a0button.<\/p>\n<h2>Hiding the\u00a0<code>&lt;input&gt;<\/code><\/h2>\n<p>First off, we need to hide the ugly duckling. CSS properties such as\u00a0<code>display: none<\/code>\u00a0or\u00a0<code>visibility: hidden<\/code>\u00a0<strong>will<\/strong>\u00a0<strong>not work<\/strong>\u00a0out. The reasons are: the input value will not be sent to the server on form submit; the input will be excluded out of tab order (you want your website to be accessible, right?). I set up a combination of CSS properties\/values for hiding the input visually but keeping it\u00a0<em>visible<\/em>\u00a0for the browser:<\/p>\n<pre class=\"brush:css; hljs css\"><span class=\"hljs-class\">.inputfile<\/span> <span class=\"hljs-rules\">{\r\n\t<span class=\"hljs-rule\"><span class=\"hljs-attribute\">width<\/span>:<span class=\"hljs-value\"> <span class=\"hljs-number\">0.1px<\/span><\/span><\/span>;\r\n\t<span class=\"hljs-rule\"><span class=\"hljs-attribute\">height<\/span>:<span class=\"hljs-value\"> <span class=\"hljs-number\">0.1px<\/span><\/span><\/span>;\r\n\t<span class=\"hljs-rule\"><span class=\"hljs-attribute\">opacity<\/span>:<span class=\"hljs-value\"> <span class=\"hljs-number\">0<\/span><\/span><\/span>;\r\n\t<span class=\"hljs-rule\"><span class=\"hljs-attribute\">overflow<\/span>:<span class=\"hljs-value\"> hidden<\/span><\/span>;\r\n\t<span class=\"hljs-rule\"><span class=\"hljs-attribute\">position<\/span>:<span class=\"hljs-value\"> absolute<\/span><\/span>;\r\n\t<span class=\"hljs-rule\"><span class=\"hljs-attribute\">z-index<\/span>:<span class=\"hljs-value\"> -<span class=\"hljs-number\">1<\/span><\/span><\/span>;\r\n<span class=\"hljs-rule\">}<\/span><\/span>\r\n<\/pre>\n<p>I see you are wondering why\u00a0<code>width<\/code>\u00a0and\u00a0<code>height<\/code>\u00a0are set to\u00a0<code>0.1px<\/code>\u00a0instead of just\u00a0<code>0px<\/code>. Setting the property values to zero ends up throwing the element out of tab party in some browsers. And\u00a0<code>position: absolute<\/code>\u00a0guarantees the element does not interfere with the sibling elements.<\/p>\n<h2>Styling the\u00a0<code>&lt;label&gt;<\/code><\/h2>\n<p>Since the\u00a0<code>&lt;label&gt;<\/code>\u00a0element is visually the button, you can use all of your creative CSS juices on it. I\u2019m sticking to something very simple for now:<\/p>\n<pre class=\"brush:css; hljs css\"><span class=\"hljs-class\">.inputfile<\/span> + <span class=\"hljs-tag\">label<\/span> <span class=\"hljs-rules\">{\r\n    <span class=\"hljs-rule\"><span class=\"hljs-attribute\">font-size<\/span>:<span class=\"hljs-value\"> <span class=\"hljs-number\">1.25em<\/span><\/span><\/span>;\r\n    <span class=\"hljs-rule\"><span class=\"hljs-attribute\">font-weight<\/span>:<span class=\"hljs-value\"> <span class=\"hljs-number\">700<\/span><\/span><\/span>;\r\n    <span class=\"hljs-rule\"><span class=\"hljs-attribute\">color<\/span>:<span class=\"hljs-value\"> white<\/span><\/span>;\r\n    <span class=\"hljs-rule\"><span class=\"hljs-attribute\">background-color<\/span>:<span class=\"hljs-value\"> black<\/span><\/span>;\r\n    <span class=\"hljs-rule\"><span class=\"hljs-attribute\">display<\/span>:<span class=\"hljs-value\"> inline-block<\/span><\/span>;\r\n<span class=\"hljs-rule\">}<\/span><\/span>\r\n\r\n<span class=\"hljs-class\">.inputfile<\/span><span class=\"hljs-pseudo\">:focus<\/span> + <span class=\"hljs-tag\">label<\/span>,\r\n<span class=\"hljs-class\">.inputfile<\/span> + <span class=\"hljs-tag\">label<\/span><span class=\"hljs-pseudo\">:hover<\/span> <span class=\"hljs-rules\">{\r\n    <span class=\"hljs-rule\"><span class=\"hljs-attribute\">background-color<\/span>:<span class=\"hljs-value\"> red<\/span><\/span>;\r\n<span class=\"hljs-rule\">}<\/span><\/span><\/pre>\n<h2>Accessibility<\/h2>\n<p>How do you know that an element on the website is\u00a0<em>pressable<\/em>? Firstly, the element should communicate a feeling that you can tap or click on it. Secondly, the cursor icon should change to an appropriate one when\u00a0<em>hovering<\/em>\u00a0the element. The former we\u2019ve solved previously, let\u2019s solve the latter, because labels do not trigger a cursor change by default:<\/p>\n<pre class=\"brush:css; hljs css\"><span class=\"hljs-class\">.inputfile<\/span> + <span class=\"hljs-tag\">label<\/span> <span class=\"hljs-rules\">{\r\n\t<span class=\"hljs-rule\"><span class=\"hljs-attribute\">cursor<\/span>:<span class=\"hljs-value\"> pointer<\/span><\/span>; <span class=\"hljs-comment\">\/* \"hand\" cursor *\/<\/span>\r\n<span class=\"hljs-rule\">}<\/span><\/span><\/pre>\n<p><img loading=\"lazy\" class=\"alignleft size-full wp-image-24839\" src=\"https:\/\/codropspz-tympanus.netdna-ssl.com\/codrops\/wp-content\/uploads\/2015\/09\/smart-custom-file-input-2.gif\" alt=\"\" width=\"300\" height=\"180\" \/><img loading=\"lazy\" class=\" size-full wp-image-24840 alignnone\" src=\"https:\/\/codropspz-tympanus.netdna-ssl.com\/codrops\/wp-content\/uploads\/2015\/09\/smart-custom-file-input-3.gif\" alt=\"\" width=\"300\" height=\"180\" \/><\/p>\n<h3>Keyboard Navigation<\/h3>\n<p>If users are unable to navigate on your website using just a keyboard, you are doing something wrong. Hiding the input itself in a correct manner was one thing, the other is indicating when the element is\u00a0<em>focused<\/em>, i.e. rendering\u00a0<code>.inputfile:focus<\/code>\u00a0on the\u00a0<code>label<\/code>:<\/p>\n<pre class=\"brush:css; hljs css\"><span class=\"hljs-class\">.inputfile<\/span><span class=\"hljs-pseudo\">:focus<\/span> + <span class=\"hljs-tag\">label<\/span> <span class=\"hljs-rules\">{\r\n\t<span class=\"hljs-rule\"><span class=\"hljs-attribute\">outline<\/span>:<span class=\"hljs-value\"> <span class=\"hljs-number\">1px<\/span> dotted <span class=\"hljs-hexcolor\">#000<\/span><\/span><\/span>;\r\n\t<span class=\"hljs-rule\"><span class=\"hljs-attribute\">outline<\/span>:<span class=\"hljs-value\"> -webkit-focus-ring-color auto <span class=\"hljs-number\">5px<\/span><\/span><\/span>;\r\n<span class=\"hljs-rule\">}<\/span><\/span><\/pre>\n<p><code>-webkit-focus-ring-color auto 5px<\/code>\u00a0is a little trick for obtaining default outline looks on Chrome, Opera and Safari. The style in the line above is for browsers that do not understand the\u00a0<code>-webkit\u2026<\/code>expression.<\/p>\n<p><img loading=\"lazy\" class=\"aligncenter size-full wp-image-24841\" src=\"https:\/\/codropspz-tympanus.netdna-ssl.com\/codrops\/wp-content\/uploads\/2015\/09\/smart-custom-file-input-4.gif\" alt=\"\" width=\"760\" height=\"180\" \/><\/p>\n<h2>Possible\u00a0<em>Touch<\/em>\u00a0Issues<\/h2>\n<p>In case you\u2019ve been using\u00a0<a href=\"https:\/\/github.com\/ftlabs\/fastclick\" target=\"_blank\" rel=\"noopener\">FastClick<\/a>\u00a0(a library for eliminating the 300ms\u00a0<em>tap-pause<\/em>\u00a0on touch-capable devices) and have plans to add some extra markup to the content of a label, the button won\u2019t work as it should, unless you use\u00a0<code>pointer-events: none<\/code>, respectively:<\/p>\n<pre class=\"brush:html; hljs xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-title\">label<\/span> <span class=\"hljs-attribute\">for<\/span>=<span class=\"hljs-value\">\"file\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;<span class=\"hljs-title\">strong<\/span>&gt;<\/span>Choose a file<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-title\">strong<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-title\">label<\/span>&gt;<\/span><\/pre>\n<pre class=\"brush:css; hljs css\"><span class=\"hljs-class\">.inputfile<\/span> + <span class=\"hljs-tag\">label<\/span> * <span class=\"hljs-rules\">{\r\n\t<span class=\"hljs-rule\"><span class=\"hljs-attribute\">pointer-events<\/span>:<span class=\"hljs-value\"> none<\/span><\/span>;\r\n<span class=\"hljs-rule\">}<\/span><\/span><\/pre>\n<h2>JavaScript Enhancement<\/h2>\n<p>Probably and hopefully the last thing missing is indicating if\u00a0files were\u00a0selected. The file input does usually indicate that, but in our case the input is visually hidden. Luckily, there is a way out: a tiny JavaScript enhancement. The text of a label becomes the name of the selected file. If there were multiple files selected, the text will tell us how many of them were selected.<\/p>\n<pre class=\"brush:html; hljs java\">&lt;input type=<span class=\"hljs-string\">\"file\"<\/span> name=<span class=\"hljs-string\">\"file\"<\/span> id=<span class=\"hljs-string\">\"file\"<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span><\/span>=<span class=\"hljs-string\">\"inputfile\"<\/span> data-multiple-caption=<span class=\"hljs-string\">\"{count} files selected\"<\/span> multiple \/&gt;<\/pre>\n<pre class=\"brush:js; hljs javascript\"><span class=\"hljs-keyword\">var<\/span> inputs = <span class=\"hljs-built_in\">document<\/span>.querySelectorAll( <span class=\"hljs-string\">'.inputfile'<\/span> );\r\n<span class=\"hljs-built_in\">Array<\/span>.prototype.forEach.call( inputs, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span><span class=\"hljs-params\">( input )<\/span>\r\n<\/span>{\r\n\t<span class=\"hljs-keyword\">var<\/span> label\t = input.nextElementSibling,\r\n\t\tlabelVal = label.innerHTML;\r\n\r\n\tinput.addEventListener( <span class=\"hljs-string\">'change'<\/span>, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span><span class=\"hljs-params\">( e )<\/span>\r\n\t<\/span>{\r\n\t\t<span class=\"hljs-keyword\">var<\/span> fileName = <span class=\"hljs-string\">''<\/span>;\r\n\t\t<span class=\"hljs-keyword\">if<\/span>( <span class=\"hljs-keyword\">this<\/span>.files &amp;&amp; <span class=\"hljs-keyword\">this<\/span>.files.length &gt; <span class=\"hljs-number\">1<\/span> )\r\n\t\t\tfileName = ( <span class=\"hljs-keyword\">this<\/span>.getAttribute( <span class=\"hljs-string\">'data-multiple-caption'<\/span> ) || <span class=\"hljs-string\">''<\/span> ).replace( <span class=\"hljs-string\">'{count}'<\/span>, <span class=\"hljs-keyword\">this<\/span>.files.length );\r\n\t\t<span class=\"hljs-keyword\">else<\/span>\r\n\t\t\tfileName = e.target.value.split( <span class=\"hljs-string\">'\\\\'<\/span> ).pop();\r\n\r\n\t\t<span class=\"hljs-keyword\">if<\/span>( fileName )\r\n\t\t\tlabel.querySelector( <span class=\"hljs-string\">'span'<\/span> ).innerHTML = fileName;\r\n\t\t<span class=\"hljs-keyword\">else<\/span>\r\n\t\t\tlabel.innerHTML = labelVal;\r\n\t});\r\n});<\/pre>\n<p>There is also a jQuery version of this code presented in the source of the demo files. Make sure to check them out.<\/p>\n<p>A little explanation:<\/p>\n<ul>\n<li>Having the native\u00a0<code>[multiple]<\/code>\u00a0attribute allows users to select more than one file per upload. Whereas\u00a0<code>[data-multiple-caption]<\/code>\u00a0is a\u00a0<em>fictive<\/em>\u00a0attribute for expressing the message if multiple files were selected. Here you can set a custom message. The use of the\u00a0<code>{count}<\/code>\u00a0phrase is optional and the fragment\u00a0is replaced with the number of files selected. The reason I use an additional HTML attribute instead of assigning this sentence as a value for a JavaScript variable is because it\u2019s much easier to maintain the copy when it is in one place.<\/li>\n<li>HTML attribute\u00a0<code>[multiple]<\/code>\u00a0is not supported in IE 9 and below and neither is the\u00a0<code>files<\/code>\u00a0property of JavaScript. For the latter case, we simply rely on\u00a0<code>value<\/code>. Since it usually has a value of\u00a0<code>C:\\fakepath\\filename.jpg<\/code>\u00a0format, the\u00a0<code>split( '\\\\' ).pop()<\/code>\u00a0extracts what\u2019s actual \u2013 the name of the file.<\/li>\n<li>An interesting thing is that you can unset a value of the input by pressing the\u00a0<em>ESC<\/em>\u00a0button while in the file browser. This is possible\u00a0only in Chrome and Opera. Therefore, we use\u00a0<code>labelVal<\/code>\u00a0for storing the default value of the label and bringing it back when necessary.<\/li>\n<\/ul>\n<p>This\u00a0is how the final result looks like:<\/p>\n<p><img loading=\"lazy\" class=\"aligncenter size-full wp-image-24842\" src=\"https:\/\/codropspz-tympanus.netdna-ssl.com\/codrops\/wp-content\/uploads\/2015\/09\/smart-custom-file-input-5.gif\" alt=\"\" width=\"760\" height=\"480\" \/><\/p>\n<h3>What if JavaScript is not available?<\/h3>\n<p>Since there is no JavaScript-less way to indicate if any files were selected, it would be better to rely on the default looks of the file input for the sake of usability. All we need to do is to add a\u00a0<code>.no-js<\/code>\u00a0class name to the\u00a0<code>&lt;html&gt;<\/code>\u00a0element and then use JavaScript and replace it with\u00a0<code>.js<\/code>\u00a0\u2013 that\u2019s how we will know if JavaScript is available.<\/p>\n<pre class=\"brush:html; hljs xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-title\">html<\/span> <span class=\"hljs-attribute\">class<\/span>=<span class=\"hljs-value\">\"no-js\"<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-title\">head<\/span>&gt;<\/span>\r\n        <span class=\"hljs-comment\">&lt;!-- remove this if you use Modernizr --&gt;<\/span>\r\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-title\">script<\/span>&gt;<\/span><span class=\"javascript\">(<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span><span class=\"hljs-params\">(e,t,n)<\/span><\/span>{<span class=\"hljs-keyword\">var<\/span> r=e.querySelectorAll(<span class=\"hljs-string\">\"html\"<\/span>)[<span class=\"hljs-number\">0<\/span>];r.className=r.className.replace(<span class=\"hljs-regexp\">\/(^|\\s)no-js(\\s|$)\/<\/span>,<span class=\"hljs-string\">\"$1js$2\"<\/span>)})(<span class=\"hljs-built_in\">document<\/span>,<span class=\"hljs-built_in\">window<\/span>,<span class=\"hljs-number\">0<\/span>);<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-title\">script<\/span>&gt;<\/span>\r\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-title\">head<\/span>&gt;<\/span>\r\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-title\">html<\/span>&gt;<\/span><\/pre>\n<p>The CSS part accordingly:<\/p>\n<pre class=\"brush:css; hljs css\"><span class=\"hljs-class\">.js<\/span> <span class=\"hljs-class\">.inputfile<\/span> <span class=\"hljs-rules\">{\r\n    <span class=\"hljs-rule\"><span class=\"hljs-attribute\">width<\/span>:<span class=\"hljs-value\"> <span class=\"hljs-number\">0.1px<\/span><\/span><\/span>;\r\n    <span class=\"hljs-rule\"><span class=\"hljs-attribute\">height<\/span>:<span class=\"hljs-value\"> <span class=\"hljs-number\">0.1px<\/span><\/span><\/span>;\r\n    <span class=\"hljs-rule\"><span class=\"hljs-attribute\">opacity<\/span>:<span class=\"hljs-value\"> <span class=\"hljs-number\">0<\/span><\/span><\/span>;\r\n    <span class=\"hljs-rule\"><span class=\"hljs-attribute\">overflow<\/span>:<span class=\"hljs-value\"> hidden<\/span><\/span>;\r\n    <span class=\"hljs-rule\"><span class=\"hljs-attribute\">position<\/span>:<span class=\"hljs-value\"> absolute<\/span><\/span>;\r\n    <span class=\"hljs-rule\"><span class=\"hljs-attribute\">z-index<\/span>:<span class=\"hljs-value\"> -<span class=\"hljs-number\">1<\/span><\/span><\/span>;\r\n<span class=\"hljs-rule\">}<\/span><\/span>\r\n\r\n<span class=\"hljs-class\">.no-js<\/span> <span class=\"hljs-class\">.inputfile<\/span> + <span class=\"hljs-tag\">label<\/span> <span class=\"hljs-rules\">{\r\n    <span class=\"hljs-rule\"><span class=\"hljs-attribute\">display<\/span>:<span class=\"hljs-value\"> none<\/span><\/span>;\r\n<span class=\"hljs-rule\">}<\/span><\/span><\/pre>\n<p><img loading=\"lazy\" class=\"aligncenter size-full wp-image-24845\" src=\"https:\/\/codropspz-tympanus.netdna-ssl.com\/codrops\/wp-content\/uploads\/2015\/09\/smart-custom-file-input-6.gif\" alt=\"\" width=\"760\" height=\"200\" \/><\/p>\n<h2>Firefox Bug<\/h2>\n<p>It is quite unexpected that Firefox completely ignores the\u00a0<code>input[type=\"file\"]:focus<\/code>\u00a0expression, whereas\u00a0<code>:hover<\/code>\u00a0and\u00a0<code>:active<\/code>\u00a0work just fine! Surprisingly, Firefox allows to\u00a0<em>catch<\/em>\u00a0the\u00a0<code>focus<\/code>\u00a0event in JavaScript, so the workaround is adding a class to the file input element that let\u2019s us control the focus style:<\/p>\n<pre class=\"brush:js; hljs php\">input.addEventListener( <span class=\"hljs-string\">'focus'<\/span>, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span><span class=\"hljs-params\">()<\/span><\/span>{ input.classList.add( <span class=\"hljs-string\">'has-focus'<\/span> ); });\r\ninput.addEventListener( <span class=\"hljs-string\">'blur'<\/span>, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span><span class=\"hljs-params\">()<\/span><\/span>{ input.classList.remove( <span class=\"hljs-string\">'has-focus'<\/span> ); });<\/pre>\n<pre class=\"brush:css; hljs css\"><span class=\"hljs-class\">.inputfile<\/span><span class=\"hljs-pseudo\">:focus<\/span> + <span class=\"hljs-tag\">label<\/span>,\r\n<span class=\"hljs-class\">.inputfile<\/span><span class=\"hljs-class\">.has-focus<\/span> + <span class=\"hljs-tag\">label<\/span> <span class=\"hljs-rules\">{\r\n    <span class=\"hljs-rule\"><span class=\"hljs-attribute\">outline<\/span>:<span class=\"hljs-value\"> <span class=\"hljs-number\">1px<\/span> dotted <span class=\"hljs-hexcolor\">#000<\/span><\/span><\/span>;\r\n    <span class=\"hljs-rule\"><span class=\"hljs-attribute\">outline<\/span>:<span class=\"hljs-value\"> -webkit-focus-ring-color auto <span class=\"hljs-number\">5px<\/span><\/span><\/span>;\r\n<span class=\"hljs-rule\">}<\/span><\/span><\/pre>\n<p>Check out the example styles in the demo to see how to style the file input element according to your needs. Make sure to take a look at the source code of the demo and feel free to use this technique in your projects. Happy uploading!<\/p>\n<p><a class=\"demo\" href=\"http:\/\/tympanus.net\/Tutorials\/CustomFileInputs\/\">View demo<\/a>\u00a0<a class=\"download\" href=\"http:\/\/tympanus.net\/Tutorials\/CustomFileInputs\/CustomFileInputs.zip\">Download source<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>here are quite a few techniques for \u201ccustomizing\u201d the\u00a0&lt;input type=&#8221;file&#8221; \/&gt;\u00a0element. I tried most of them, but none was good enough to have on\u00a0Readerrr\u00a0(for importing feeds by uploading a file). Probably the worst technique was the one where the input element is put into a container (which imitates a button), and the input follows the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":4830,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0},"categories":[8,9,5,22,7],"tags":[139,138,51,119,131],"_links":{"self":[{"href":"https:\/\/a1webdesignteam.com\/blog\/wp-json\/wp\/v2\/posts\/4828"}],"collection":[{"href":"https:\/\/a1webdesignteam.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/a1webdesignteam.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/a1webdesignteam.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/a1webdesignteam.com\/blog\/wp-json\/wp\/v2\/comments?post=4828"}],"version-history":[{"count":0,"href":"https:\/\/a1webdesignteam.com\/blog\/wp-json\/wp\/v2\/posts\/4828\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/a1webdesignteam.com\/blog\/wp-json\/wp\/v2\/media\/4830"}],"wp:attachment":[{"href":"https:\/\/a1webdesignteam.com\/blog\/wp-json\/wp\/v2\/media?parent=4828"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/a1webdesignteam.com\/blog\/wp-json\/wp\/v2\/categories?post=4828"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/a1webdesignteam.com\/blog\/wp-json\/wp\/v2\/tags?post=4828"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}