CSS-客製 File 元件

現在才發現的小技巧。

簡述

以往要做 File 元件時我都是用 absolute + opaicty 的障眼法來把原生元件覆蓋在客制元件上,就能享有原生自動跳出 dialog 的功能。

dialog

這邊的 HTML 和 CSS 大概會這樣設計:

1
2
3
4
5
6
<div class="custom-upload-wrapper">
<div class="custom-upload-element">
<span>Filename goes here...</span>
<input class="custom-upload-native" type="file" />
</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
.custom-upload-wrapper {
margin: 20px auto;
max-width: 300px;
.custom-upload-element {
position: relative;
display: block;
border: 1px solid #033076;
border-radius: 4px;
padding: 9px 10px;
font-size: 14px;
color: #021f54;
transition: all 0.3s;
&:hover {
box-shadow: 0 0 0 2px rgba(2, 31, 84, 0.2);
}
}
.custom-upload-native {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
cursor: pointer;
// hide native element
opacity: 0;
z-index: 999;
text-indent: -999px;
}
}

不過其實除了這種作法之外,有一個更簡單的技巧是透過 <label> 來處理,這個技巧是把 input file 包在 <label> 裡面,並且設為 display: none

1
2
3
4
<label class="custom-upload-wrapper">
<span class="custom-upload-element">Filename goes here...</span>
<input class="custom-upload-native" type="file" />
</label>

你會發現神奇的事情發生了,照理說你應該是沒辦法點擊到 input 的,不過因為 label 的特性就是會把事件反應到對應的 input 元件上,所以即便設為 display: none 也一樣能觸發 dialog 的功能!

所以 CSS 可以簡化許多:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
.custom-upload-wrapper {
display: block;
margin: 20px auto;
max-width: 300px;
.custom-upload-element {
display: block;
border: 1px solid #033076;
border-radius: 4px;
padding: 9px 10px;
font-size: 14px;
color: #021f54;
transition: all 0.3s;
cursor: pointer;
&:hover {
box-shadow: 0 0 0 2px rgba(2, 31, 84, 0.2);
}
}
// no need to worry about this
.custom-upload-native {
display: none;
}
}

現在事情好辦了,你完全不需要對原生元件做額外處理,只要專注在你的客制元件上就行了。

這邊的實際範例可以到 Codepen 上參考。

Next.js-架構 Ant Design-Upload 相關的 Props
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×