CSS和<input type='file'> - 讨论

4
我想改变网站上上传文件的输入和浏览按钮的样式,但我一直在阅读如何做到这一点似乎是不可能的。据说有几个“黑客”方法可能有效(未经测试),但在我浪费时间之前,我想知道为什么专业网站似乎没有这方面的问题。
当我说专业网站时,我的意思是求职网站,您可以上传简历;编程网站,您可以上传脚本;我大学的网站,我可以上传试卷;政府、医生等等。
我看不出他们会使用某个随机程序员的黑客方法,这可能行也可能不行,那么他们在做什么,因为他们的网站似乎运作良好且外观良好?
对此的任何意见都将不胜感激。
谢谢
Beauford
跟进:
感谢您的回复,但请注意Yi Jiang - 您发布的内容肯定已按某种方式进行了样式设置。 我在我的网站上有一个,我在5个浏览器中查看它,所有我得到的只是基本的正方形灰色浏览按钮和正方形输入字段,两者之间没有空格,而浏览按钮比输入字段略高一点,所以看起来非常破旧。 如果我能使其看起来像您的示例一样,我将非常高兴。
谢谢

他们也在使用黑客技巧,没什么特别的。 - NullUserException
2
步骤1. 找到具有自定义输入文件类型的网站。步骤2. 检查源代码。如果您不理解,请在SO上发布该网站链接并询问如何完成。但通常情况下,任何解决方案都会是“肮脏的”。 - meder omuraliev
很多网站使用Flash进行文件上传,这样他们可以自定义样式并拥有进度条。不过现在HTML5已经支持进度条了。 - Telanor
NullUserException所说的只是(希望)经过充分测试的黑客技巧。例如,您可以找到一些jQuery插件和代码行。此外,有些人会使用Flash / Java。 - Andrew Barber
1
可能是Styling an input type="file" button的重复问题。 - Shadow The Spring Wizard
显示剩余2条评论
3个回答

4
文件上传字段无法在CSS中进行大量样式设计,也无法通过JS进行脚本编写(足以使代理控件实际工作)。尽管这种情况有一些合理的安全原因,但您可能会认为它们已经被过分地采用了。
更一般地说,文件上传字段很难进行样式设计,因为您不知道文件上传字段的外观。这完全取决于浏览器。也许你会在左边得到一个文本字段,在右边得到一个“浏览”按钮/弹出窗口(在这种情况下,border适用于哪个部分?或者两者都是?);也许你只会在左边得到一个弹出窗口和一个状态图标/标签(就像在Safari中一样);也许你只会得到一个拖放字段。或其他什么东西。这完全超出了您的控制范围。
大多数“专业”网站有两种做法:
1. 不考虑它,只使用未经样式设计的普通文件上传字段。也许在请求上传时在弹出的div中(因此至少在屏幕上始终保持一致)。 2. 使用渐进增强技术,将HTML文件上传替换为基于Flash的另一种上传程序(或者不太常见的Java或Silverlight;在将来,我们将有更多支持HTML5拖放的浏览器)。
这里详细介绍了一种hack方法,它通过使真实的文件上传控件不可见并将其定位在可样式化的显示控件上方来工作。但是,它非常不可靠,具体取决于浏览器的文件上传控件的大小和响应点击的部分。它对可访问性不利(不能正确响应键盘),对可用性不利(它甚至不能在我完全正常的Firefox上排列),我不建议使用它

3
首先,这些hack并不是来自于随便一个程序员。例如,Quirksmode的这个hack非常有名,并且据我所知被广泛使用(在此处用于图像上传对话框)。另一个例子是为ajax上传脚本创建的此按钮。完全忽略Javascript,你会发现这个按钮只是纯粹地把input type="file"放在了div里面。
值得注意的是,你可以完全没有这些hack。即使大型网站也使用未经样式修饰的文件输入。以下是Hotmail的示例: alt text 以下是GMail的示例: alt text

自从PPK发布了那个黑客攻击,我对他的尊重程度大大降低了! - bobince

0

在这个帖子中发帖,因为它已经过时了,而且其他人(像我一样)可能会从谷歌上找到它,并想知道他们可以做些什么来创建外观更好的input[type=file]框!

简短的答案仍然是:你不能。

但是,如果你愿意使用一点JavaScript,你实际上可以制作出一个相当不错的样式,并适当地控制文件输入。

首先,HTML大致如下:

<a href="#" class="btn btn-upload">Choose your photo</a>
<div class="fileupload">
    <label for="picture">Your Image:</label>
    <input type='file' name="picture" id="picture" enctype = "multipart/form-data" runat="server" required />
</div>

这允许您使用fileupload div来“隐藏”真正的控件 - 但是,您不应该使用display:none - 许多浏览器将其视为安全风险。相反,尝试使用position:relativeleft:-99999px,或者height:0pxoverflow:hidden。如果您需要出于任何原因关闭此功能(例如需要支持非常旧的IE),则可以使用IE样式表或Modernizr并反转CSS以显示正常上传并隐藏您的“伪造”。

现在,适当地为您的btn-upload设置样式。无论您想要什么样式。

使用JavaScript为您单击输入文件,当有人单击您的“伪造”时(以下假定您使用jQuery):

    $(".btn-upload").click(function () {
        $(".fileupload input").trigger('click');
        return false;
    });

此外,如果您想要更改已样式化的文件输入伪造的外观,或者在用户选择文件时让您的页面以任何方式做出反应,可以使用change事件来实现。以下示例将在带有ID为image-preview的img标签中显示用户即将上传的图像(这在IE 10以下的浏览器中不起作用):
    $('input[type=file]').change(function () {
        var input = $(this);
        if (input[0].files && input[0].files[0]) {
            var reader = new FileReader();

            reader.onload = function (e) {
                $('#image-preview')
                       .attr('src', e.target.result);
            };

            reader.readAsDataURL(input[0].files[0]);
        }
    });

如果您想使用JavaScript在某个地方显示文件名,您也可以访问该文件名:

$('input[type=file]').change(function () {
    var input = $(this);
    if (input[0].files && input[0].files[0]) {
        var file = input[0].files[0]
        if (file) {
           //Put the file name into a div with the id of 'filename'
           $('#filename').html(file.name);
        }

    }
});

使用这些,您可以制作一个非常漂亮且功能正常的上传按钮。我还建议在不支持文件上传的浏览器上使用特征检测并隐藏所有内容(看着你,旧版IOS!)
文件上传功能检测示例:
function checkForInputFile() {
    var elem = document.createElement("input");
    elem.type = "file";
    if (elem.disabled) return false;
    try {
        elem.value = "Test"; // Throws error if type=file is implemented
        return elem.value != "Test";
    } catch(e) {
        return elem.type == "file";
    }
}

if(checkForInputFile()){
    console.log('i support file input type!');
} else {
    console.log('i dont :(');
}

(以上内容基于此正确答案:检测是否支持<input type="file" />

最后,如果我们想要一个按钮来清除文件类型输入怎么办?出于安全原因,这并不容易。但是这是可能的!这个解决方案是我最喜欢的:使用jQuery清除<input type='file' />

如果您懒得打开链接,这里有一个示例,使用我的示例HTML,假设我们在页面上添加了一个ID为remove-file的链接:

function resetFormInputElement(e){
    e.wrap('<form>').closest('form').get(0).reset();
    e.unwrap();
}
$('a#remove-file').click(function () {
    //Clear input file
    resetFormInputElement($('.fileupload input'));
    return false;
});

不错,但是已经有很多答案在这里了(https://dev59.com/dXRB5IYBdhLWcg3wn4UL),这个问题应该被关闭为那个其他问题的重复。 :) - Shadow The Spring Wizard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接