Bootstrap4自定义文件输入:解决文件名与默认文本拼接问题
解决Bootstrap4自定义文件输入框文件名与默认文本拼接问题
我在使用Bootstrap4开发文件输入组件时,通过CSS伪元素定义了"Choose file"、"Browse"和"Upload"文本,代码如下:
.CHOOSE_FILE_LABEL::before{content: 'Choose file';} .BROWSE_BTN_LABEL::after{content: 'Browse';} .UPLOAD_BTN_LABEL::after{content: 'Upload';}
对应的HTML结构:
<div class="input-group"> <div class="custom-file"> <input type="file" class="custom-file-input" id="customFileInput"> <label class="custom-file-label CHOOSE_FILE_LABEL BROWSE_BTN_LABEL" for="customFileInput"></label> </div> <div class="input-group-append"> <button class="btn btn-success UPLOAD_BTN_LABEL" type="button" id="uploadBtn"></button> </div> </div>
原本希望选中文件后,用JS把"Choose file"替换成文件名,但执行以下代码后,文件名和"Choose file"会拼接在一起:
document.getElementById("customFileInput").addEventListener('change', function (e) { e.preventDefault(); var file_input = document.getElementById("customFileInput"); var file_name = file_input.files[0].name; var next_sibling = e.target.nextElementSibling; next_sibling.innerText = file_name; });
问题原因
"Choose file"是通过.CHOOSE_FILE_LABEL::before伪元素生成的内容,而JS设置的是label标签的innerText——这两部分内容属于不同的渲染层,会同时显示,所以出现了叠加效果。
两种解决思路
思路一:CSS类切换控制伪元素显示
通过新增一个CSS类,用来隐藏伪元素的默认文本,再通过JS在选中文件时添加该类,取消选择时移除:
- 修改CSS,新增隐藏类:
.CHOOSE_FILE_LABEL::before{content: 'Choose file';} /* 新增类:隐藏默认的Choose file文本 */ .CHOOSE_FILE_LABEL.hide-default::before{content: '';} .BROWSE_BTN_LABEL::after{content: 'Browse';} .UPLOAD_BTN_LABEL::after{content: 'Upload';}
- 调整JS逻辑:
document.getElementById("customFileInput").addEventListener('change', function (e) { const fileInput = e.target; const label = fileInput.nextElementSibling; if (fileInput.files.length > 0) { // 有选中文件时,设置文件名并隐藏默认文本 label.innerText = fileInput.files[0].name; label.classList.add('hide-default'); } else { // 无选中文件时,恢复默认状态 label.innerText = ''; label.classList.remove('hide-default'); } });
思路二:纯CSS逻辑控制伪元素显示
利用CSS的:not(:empty)选择器,当label标签有内容时,自动隐藏伪元素的默认文本,无需修改JS:
.CHOOSE_FILE_LABEL::before{content: 'Choose file';} /* 当label不为空时,隐藏伪元素的默认文本 */ .CHOOSE_FILE_LABEL:not(:empty)::before{content: '';} .BROWSE_BTN_LABEL::after{content: 'Browse';} .UPLOAD_BTN_LABEL::after{content: 'Upload';}
原JS代码保持不变即可,设置innerText后,label不再为空,伪元素的"Choose file"会自动隐藏。
方案选择
- 思路一更灵活,适合需要手动控制显示状态的场景;
- 思路二更简洁,纯CSS实现逻辑,无需额外的类操作代码。
内容的提问来源于stack exchange,提问作者nicc96
相关产品推荐
相关产品推荐

