Libon

实现一个标签输入框

2 分钟 #HTML#CSS#JavaScript
使用原生 CSS + JS 实现一个可交互的标签输入框

ToC

代码如下:

1
<div class="tags-content">
2
<div class="tags-input" placeholder="添加标签"></div>
3
</div>
1
.tags-content {
2
display: flex;
3
flex-wrap: wrap;
4
align-items: flex-start;
5
gap: 6px;
6
width: 400px;
7
box-sizing: border-box;
8
padding: 8px 12px;
9
border: 1px solid #D9D9D9;
48 collapsed lines
10
border-radius: 4px;
11
font-size: 16px;
12
line-height: 24px;
13
color: #333;
14
outline-color: #4F46E5;
15
overflow: auto;
16
cursor: text;
17
}
18
19
.tag {
20
display: flex;
21
align-items: center;
22
padding: 4px 0 4px 8px;
23
font-size: 16px;
24
line-height: 24px;
25
background: #F5F5F5;
26
color: rgba(0, 0, 0, 0.85);
27
cursor: default;
28
}
29
/* 关闭按钮 */
30
.tag-close {
31
width: 18px;
32
height: 18px;
33
cursor: pointer;
34
background: url("data:image/svg+xml,%3Csvg width='10' height='10' viewBox='0 0 10 10' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5.578 5l2.93-3.493a.089.089 0 0 0-.068-.146h-.891a.182.182 0 0 0-.137.064l-2.417 2.88-2.416-2.88a.178.178 0 0 0-.137-.064h-.89a.089.089 0 0 0-.069.146L4.413 5l-2.93 3.493a.089.089 0 0 0 .068.146h.89a.182.182 0 0 0 .138-.064l2.416-2.88 2.417 2.88c.033.04.083.064.137.064h.89a.089.089 0 0 0 .069-.146l-2.93-3.493z' fill='%23000' fill-opacity='.45'/%3E%3C/svg%3E") center no-repeat;
35
}
36
/* 设置了 editable 的输入框 */
37
.tags-input {
38
flex: auto;
39
border: 0;
40
outline: 0;
41
padding: 4px 0;
42
line-height: 24px;
43
font-size: 16px;
44
/* 可以让元素变得可输入,且只能输入纯文本 */
45
-webkit-user-modify: read-write-plaintext-only;
46
}
47
48
/* 占位文本,当只有输入框没有标签的时候才展示 */
49
.tags-input:only-child:empty::before {
50
content: attr(placeholder);
51
color: #828282;
52
}
53
/* 当外层容器获取到焦点时展示边框 */
54
.tags-content:focus-within,
55
.tags-content:active {
56
outline: auto #4F46E5;
57
}
1
const TagContent = document.querySelector('.tags-content')
2
const TagInput = document.querySelector('.tags-input')
3
4
// 监听按下的 回车键 和 删除键
5
TagInput.addEventListener('keydown', function (ev) {
6
if (ev.key === 'Enter') {
7
ev.preventDefault()
8
// 如果是回车键则阻止默认行为,防止内容换行
9
if (this.innerText) { // 输入框内容通过 innerText 获取
23 collapsed lines
10
const tag = Object.assign(document.createElement('span'), { className: 'tag' })
11
// 设置标签内容
12
tag.innerHTML = this.innerText + '<a class="tag-close"></a>'
13
// 将标签插入到输入框之前
14
this.before(tag)
15
// 清空当前的输入框内容
16
this.innerText = ''
17
}
18
} else if (ev.key === 'Backspace' && !this.innerText) {
19
// 如果没有内容时还按了删除键则删除标签
20
this.previousElementSibling?.remove() // 需要判断前一个元素是否存在
21
}
22
})
23
24
// TagContent是父级容器
25
TagContent.addEventListener('click', function (ev) {
26
// 如果点击的是删除按钮则删除标签
27
if (ev.target.className === 'tag-close') {
28
ev.target.parentNode.remove()
29
}
30
// 保持输入框的聚焦
31
TagInput.focus() //点击任意地方输入框都需要聚焦
32
})

CD ..
接下来阅读
JSON.stringify