精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

原生 CSS + JS 實現一個標簽輸入框

開發 前端
在各種框架大行其道的氛圍下,有些原生的屬性和方法可能都不太關注了,這也不失為是一種損失。

最近在項目中需要做一個標簽輸入框,還挺實用的,演示效果如下:

主要交互要求是這樣的:

  • 點擊輸入框可以輸入內容。
  • 按回車可以生成標簽。
  • 按退格鍵可以刪除標簽。
  • 點擊標簽上的關閉按鈕可以刪除標簽。

習慣了各種 react 框架或者UI庫,大家有多久沒接觸沒有原生開發了呢?有時候頁面比較簡單,沒必要引入一個完整的框架,原生實現就完全滿足了,一起看看吧!

一、自適應輸入框布局

不管什么組件,布局都是最重要的。這個布局分為標簽和輸入框兩個部分,假設 HTML 如下:

<div class="tags-content">
<tag>CSS<a class="tag-close"></a></tag>
<input class="tags-input" placeholder="添加標簽">
</div>

簡單修飾一下:

.tags-content{
display: flex;
flex-wrap: wrap;
align-items: flex-start;
gap: 6px;
width: 400px;
box-sizing: border-box;
padding: 8px 12px;
border: 1px solid #D9D9D9;
border-radius: 4px;
font-size: 16px;
line-height: 24px;
color: #333;
outline-color: #4F46E5;
overflow: auto;
cursor: text;
}
tag{
display: flex;
align-items: center;
padding: 4px 0 4px 8px;
font-size: 16px;
line-height: 24px;
background: #F5F5F5;
color: rgba(0, 0, 0, 0.85);
cursor: default;
}
tag-close{
width: 18px;
height: 18px;
cursor: pointer;
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;
}
.tags-input{
flex: auto;
border: 0;
outline: 0;
padding: 4px 0;
line-height: 24px;
font-size: 16px;
}
.tags-content:focus-within,
.tags-content:active{
outline: auto #4F46E5;
}

注意幾點實現技巧:

  • 標簽的間隔可以用 gap 實現。
  • 為了讓輸入框的區域鋪滿剩余空間,這里用到了flex: auto。
  • 為了讓父級處于聚焦狀態,這里用到了:focus-within。

效果如下:

但是這里的輸入框用 input 還是有些問題的,如下所示:

由于 input 輸入內容無法跟隨寬度自適應,所以有時候會出現文字被截斷的情況:

理想情況下,當輸入內容較多時,應該整體換行。如何實現呢?可以用普通的 div 來實現。

<div class="tags-content">
<tag>CSS<a class="tag-close"></a></tag>
<div class="tags-input" placeholder="添加標簽"></div>
</div>

可以通過添加contenteditable或者以下 CSS 來實現:

.tags-input{
-webkit-user-modify: read-write-plaintext-only;
}

這個屬性表示只允許輸入純文本,有興趣的可以參考張鑫旭的這篇文章:小tip: 如何讓contenteditable元素只能輸入純文本[1]。

這樣可以自適應內容寬度了。

二、輸入框占位提示

由于輸入框已經從 input 換成了普通的 div 標簽,并沒有 placeholder 特性。不過,我們仍然可以通過其他 CSS 特性來實現占位效果,當輸入框沒有內容時,就可以匹配到 :empty選擇器,然后通過偽元素::before動態生成 placeholder 內容,具體實現如下:

.tags-input:empty::before{
content: attr(placeholder);
color: #828282;
}

效果如下:

這樣就幾乎和 input 的占位效果一致了。

另外還有一種情況,如果需要僅在沒有任何標簽的情況下才顯示占位,如何實現呢?可以想想,在沒有任何標簽的情況下,HTML 就變成了這樣:

<div class="tags-content">
<div class="tags-input" placeholder="添加標簽"></div>
</div>

這種情況,就僅剩輸入框唯一元素了,唯一元素可以通過:only-child來匹配,所以實現如下:

.tags-input:only-child:empty::before{
content: attr(placeholder);
color: #828282;
}

這樣添加一個偽類就解決了。

兩種需求都符合認知,看設計如何決定了。

三、標簽的輸入與刪除

要實現標簽的輸入與刪除就需要 JS 出馬了,只需要監聽鍵盤的“回車”和“退格”兩個鍵值。需要注意的是,默認情況下,普通 contenteditable元素在回車時,會出現換行,如下:

因此,在監聽鍵盤事件時需要阻止默認事件,然后動態創建標簽元素,通過 before添加到輸入框前面,具體實現如下:

// TagInput是輸入框
TagInput.addEventListener('keydown', function(ev) {
if (ev.key === 'Enter') {
ev.preventDefault()
if (this.innerText) { // 輸入框內容通過 innerText 獲取
const tag = document.createElement('TAG');
tag.innerHTML = this.innerText + '<a class="kalos-tag-close"></a>';
this.before(tag);
this.innerText = '';
}
}
})

這樣就能正常創建標簽了。

然后是標簽的刪除。

這里有兩種途徑,首先看鍵盤的刪除,具體邏輯是當輸入框內容為空時刪除標簽,很簡單,刪除的標簽就是輸入框的前面一個元素,通過previousElementSibling獲取,具體實現如下:

TagInput.addEventListener('keydown', function(ev) {
if (ev.key === 'Backspace' && !this.innerText) {
this.previousElementSibling?.remove(); // 需要判斷前一個元素是否存在
}
})

然后是點擊刪除圖標的刪除。由于標簽是動態生成的,所以這里需要用事件委托的方式來添加刪除事件。

// TagContent是父級容器
TagContent.addEventListener('click', function(ev) {
if (ev.target.className === 'tag-close') {
ev.target.parentNode.remove();
}
TagInput.focus(); //點擊任意地方輸入框都需要聚焦
})

這樣就實現了文章開頭的所示效果:

完整代碼可以訪問:「文章底部原文鏈接」input-tag[2]。

四、選擇框架還是原生?

總結一下!

整體實現并不算復雜,不少交互邏輯 CSS 也可以輕松實現,JS 也就 10 來行代碼,這里總結一下實現要點:

  • 普通 div 元素輸入純文本可以使用 -webkit-user-modify: read-write-plaintext-only
  • 普通 div 元素輸入可以自適應內容寬度
  • 普通 div 元素輸入框的 placeholder 占位可以通過 :empty 結合偽元素實現
  • 回車事件需要阻止默認事件,不然會換行
  • 在一個元素的前面新增元素可以用 before 方法
  • 刪除一個元素的前面一個元素,可以用 previousElementSibling.remove 方法
  • 給動態生成的元素綁定事件可以用事件委托的方式

在各種框架大行其道的氛圍下,有些原生的屬性和方法可能都不太關注了,這也不失為是一種損失。當然,我本身也是各種框架都會用,特別是大型、復雜的交互頁面,一般比較小的交互,比如文章這個例子,在 ant design 中有相關的組件,也使用過,因為整體 UI 全是這種風格,設計也是按照這個設計的。后來需要單獨開發一個 chrome 插件,也用到了這樣一個交互,但是僅僅用了這樣一個組件,引入整個框架就過于累贅了,所以還是選擇直接原生實現,簡單方便。

責任編輯:武曉燕 來源: 前端偵探
相關推薦

2020-09-24 14:06:19

Vue

2017-09-11 17:46:48

設計

2024-06-13 15:43:04

2023-05-22 09:10:53

CSSloading 效

2025-05-07 08:10:43

2025-10-24 08:13:17

2023-04-17 09:08:27

CSS計時器

2011-07-22 15:32:53

iPhone 按鈕 對話框

2022-10-20 11:49:49

JS動畫幀,CSS

2023-10-20 08:02:25

圖形編輯器前端

2021-09-27 14:44:48

鴻蒙HarmonyOS應用

2016-10-19 14:54:46

css選擇器css3css

2021-09-13 06:03:42

CSS 技巧搜索引擎

2024-10-12 16:38:09

2011-10-25 09:28:30

Node.js

2020-08-07 10:40:56

Node.jsexpress前端

2019-03-07 14:45:07

聊天工具富文本輸入框前端

2023-08-03 09:12:02

2022-11-07 11:27:00

JS游戲開發

2020-10-29 16:00:03

Node.jsweb前端
點贊
收藏

51CTO技術棧公眾號

欧美日日夜夜| 老司机福利在线视频| 国产一区观看| 日韩女优制服丝袜电影| 日韩不卡视频一区二区| 999久久久久久| 欧美另类女人| 亚洲黄在线观看| www.四虎成人| 网友自拍视频在线| 国产精品一区二区你懂的| 九九精品在线播放| 亚洲免费观看在线| 欧美sm一区| 国产午夜精品久久久久久免费视| 日韩免费观看av| 波多野结衣欲乱| 一区二区三区欧洲区| 欧美视频一区二区三区…| 日韩免费一区二区三区| 国产又粗又猛又爽又黄的| 欧美成人综合| 国产丝袜一区二区三区| 久久99爱视频| 美女航空一级毛片在线播放| 久久久精品欧美丰满| 国产一区二区在线播放| 欧美黑吊大战白妞| 一区二区美女| 日韩一区二区视频| 国产精品-区区久久久狼| 男人的天堂在线视频免费观看 | 亚洲欧美日韩在线高清直播| 奇米影视四色在线| av小说在线播放| 国产精品蜜臀av| 国产美女精品在线观看| 国产精品xxxxxx| 欧美福利专区| 一区二区三区黄色| 国产精品久久久久久亚洲av| 中文字幕在线视频久| 1024精品合集| 久久久久久精| 精品久久久久久亚洲综合网站| 每日更新成人在线视频| 欧美大片欧美激情性色a∨久久| 在线不卡av电影| 电影一区二区在线观看| 欧美丰满嫩嫩电影| 免费激情视频在线观看| 国产福利电影在线播放| 亚洲视频一区在线观看| 日韩av不卡播放| 天堂在线观看视频| 国产超碰在线一区| 成人精品一区二区三区| 国产精品自拍第一页| 亚洲日产国产精品| 日韩中文字在线| 日韩精品无码一区二区三区久久久| 视频一区中文字幕精品| 欧美放荡的少妇| 91制片厂毛片| gogo亚洲高清大胆美女人体| 欧美日韩国产色视频| 久久精品xxx| 在线不卡日本v二区707| 中文成人综合网| 欧美凹凸一区二区三区视频| 韩国av永久免费| 国产很黄免费观看久久| 91精品视频在线免费观看| 中文字幕在线观看视频网站| 在线成人欧美| 久久99精品视频一区97| 日本福利片在线观看| 婷婷六月综合| 日韩在线观看免费高清完整版| 欧美黄色一级生活片| 香蕉久久夜色精品国产更新时间| 亚洲精品福利资源站| 亚洲av网址在线| 亚洲人成网站77777在线观看| 亚洲精品不卡在线| 免费在线观看成年人视频| 天堂一区二区三区四区| 亚洲精品中文字幕女同| 亚洲午夜精品久久久久久高潮 | 欧美美女喷水视频| 中文字幕国产免费| 国产精品1区| 欧美一区二区在线免费播放| 夜夜爽久久精品91| 一区二区三区四区高清视频| 欧美成人性战久久| av黄色一级片| 欧州一区二区| 久久九九亚洲综合| 日本三级免费看| 乱码第一页成人| 国产九九精品视频| 成 人 黄 色 片 在线播放| 成人一区二区三区| 精品国产乱码久久久久软件| 欧美女v视频| 国产精品女主播av| 国产a级黄色大片| 美女高潮在线观看| 欧美在线免费播放| 欧美日韩一区二区三区69堂| 日韩一级淫片| 亚洲品质视频自拍网| 亚洲怡红院在线观看| 欧美午夜一区二区福利视频| 欧美专区在线视频| 国产精品一区二区黑人巨大| 不卡一区二区在线| 亚洲午夜久久久影院伊人| 国产写真视频在线观看| 精品国产鲁一鲁一区二区张丽| 青青青在线视频免费观看| 精品视频一二| 亚洲一区二区久久| 99热6这里只有精品| 国产欧美欧美| 96国产粉嫩美女| 可以直接在线观看的av| 中文字幕一区日韩精品欧美| 日韩精品一区二区免费| 欧美videos粗暴| 亚洲国产精品99久久| 国产3级在线观看| 欧美亚洲一区| www.成人三级视频| 蜜桃av在线免费观看| 疯狂做受xxxx欧美肥白少妇| 亚洲色图久久久| 鲁大师精品99久久久| 久久天堂电影网| 天天综合网久久综合网| 风间由美性色一区二区三区| 日本视频一区二区不卡| 男女在线视频| 欧美一区二区精品| 长河落日免费高清观看| 免费久久99精品国产自在现线| 成人欧美一区二区三区视频| 日本精品在线| 91精品1区2区| 无码国产69精品久久久久同性| 亚洲视频福利| 99高清视频有精品视频| 91福利在线视频| 欧洲日韩一区二区三区| 日韩av一二区| 91久久夜色精品国产九色| 99免费在线观看视频| caoporn免费在线| 欧美裸体bbwbbwbbw| 大吊一区二区三区| 免费人成网站在线观看欧美高清| 欧美亚洲爱爱另类综合| 蜜桃在线视频| 日韩精品在线免费播放| 国产又爽又黄的视频| 成年人午夜久久久| 国产激情在线看| 成人精品视频在线观看| 久久精品人人做人人爽| 亚洲综合网av| 中文字幕在线观看一区二区| 亚洲男人天堂av在线| 93在线视频精品免费观看| 国产精品中文字幕久久久| 午夜精品一区| 91麻豆精品国产91久久久使用方法| 久久国产波多野结衣| 国产一区二区三区蝌蚪| 国产911在线观看| 久久九九全国免费精品观看| 亚洲欧美色图视频| 亚洲欧美成人| 免费国产在线精品一区二区三区| 91精品论坛| 亚洲欧美激情视频| 自拍偷拍福利视频| 中文字幕人成不卡一区| 亚欧美在线观看| 五月婷婷六月综合| 国产精品区一区二区三含羞草| 国产精品一区hongkong| 亚洲护士老师的毛茸茸最新章节| 日韩黄色在线播放| 国产精品区一区二区三区| 91pony九色| 国产视频一区三区| 亚洲激情一区二区三区| 精品国产亚洲日本| 国产69精品99久久久久久宅男| 日本亚洲欧美| 欧美日产在线观看| 日本中文字幕在线免费观看| 国产亚洲精品7777| 三日本三级少妇三级99| 日韩五码在线| 亚洲精品国产精品国自产| 欧美激情啪啪| 97成人精品视频在线观看| 国产高清视频在线播放| 欧美天堂一区二区三区| 欧美三根一起进三p| 91亚洲午夜精品久久久久久| 嫩草视频免费在线观看| 日韩午夜在线| 一本—道久久a久久精品蜜桃| 国产精品中文字幕制服诱惑| 国产精品男人的天堂| 国产精品偷拍| 久久精品2019中文字幕| 亚洲三级黄色片| 欧美一区三区二区| 日韩在线 中文字幕| 亚洲美女免费在线| 青青草成人免费视频| 国产在线精品一区二区夜色| 成年人视频网站免费观看| 亚洲综合小说| 久久超碰亚洲| 精品国产亚洲日本| 国产成人在线亚洲欧美| av在线不卡免费| 伊人久久五月天| 天天综合天天综合| 日韩欧美一区在线| 中文字幕日韩国产| 欧美性色19p| 久久激情免费视频| 亚洲免费观看高清| 99在线视频免费| 久久久久久久一区| 逼特逼视频在线观看| 国产综合色精品一区二区三区| 成人在线免费播放视频| 国产精品一区毛片| av中文字幕av| 国产精品久久久久久久免费观看 | 日韩va亚洲va欧美va清高| av在线播放成人| 日本女人性视频| 久久99精品久久久久久国产越南| 日韩国产一级片| 黄色工厂这里只有精品| 9色视频在线观看| 66国产精品| 一区二区不卡视频| 成人综合一区| 日韩欧美精品一区二区三区经典| 欧美日韩导航| 99在线观看视频| 日韩精品视频一区二区三区| 亚洲一区美女视频在线观看免费| 高清一区二区中文字幕| 91日韩在线播放| 欧美影院精品| 国产精品国产三级欧美二区| 亚洲精品在线a| 91超碰在线电影| 亚洲性视频在线| yy111111少妇影院日韩夜片| 欧美日韩免费电影| 国产日韩精品在线| 亚洲影视资源| 亚洲淫片在线视频| 亚洲1区在线| 国产精品一区二区三区免费观看| 国产毛片精品| 日本一区二区三区免费观看 | 一区二区三区黄色| 成人短视频在线| 午夜精品一区二区三区av| 日本h片久久| a级国产乱理论片在线观看99| 天堂日韩电影| 在线视频精品一区| 亚洲美女少妇无套啪啪呻吟| 伊人国产在线视频| 国产99久久久精品| 真实乱视频国产免费观看| 亚洲男人电影天堂| 六月丁香激情综合| 制服丝袜在线91| 日韩a在线观看| 中文字幕av一区中文字幕天堂| 都市激情久久综合| 国产日韩欧美另类| 亚洲免费成人av在线| 黄色小视频大全| 日韩电影在线一区二区三区| www.555国产精品免费| 国产精品三级av| 欧美性猛交bbbbb精品| 欧美精品丝袜中出| 亚洲av电影一区| 欧美激情一级欧美精品| 国产成人77亚洲精品www| 国产在线一区二| 影音先锋日韩在线| 男女污污的视频| av一区二区久久| www.超碰在线观看| 欧美日韩美女一区二区| 日韩毛片在线一区二区毛片| 欧美俄罗斯乱妇| 91精品网站在线观看| 日本欧洲国产一区二区| 国产婷婷精品| 91九色蝌蚪porny| 亚洲男女毛片无遮挡| 中文字幕视频二区| 亚洲视频一区二区三区| 白浆在线视频| 国产超碰91| 欧美成人日韩| 在线观看av免费观看| 18欧美乱大交hd1984| 亚洲性在线观看| 中国china体内裑精亚洲片| 亚洲欧美一区二区三区| 国产主播一区二区三区四区| 影音先锋久久资源网| 91porn在线| 亚洲狠狠爱一区二区三区| 国产福利资源在线| 免费av一区二区| 亚洲三区欧美一区国产二区| gogogo免费高清日本写真| 久久99在线观看| 日韩av手机在线免费观看| 欧美片网站yy| 看黄网站在线观看| 亚洲free性xxxx护士hd| 91精品电影| 污免费在线观看| 亚洲精品免费在线观看| 国内精品久久久久久久久久久| 欧美成人免费视频| 九色精品蝌蚪| 日韩精品免费一区| 成人av网址在线| 五月天综合激情| 亚洲精品自在久久| 国产综合av| 色涩成人影视在线播放| 蜜桃久久久久久| 538任你躁在线精品视频网站| 日韩一区二区三区精品视频| bl在线肉h视频大尺度| 欧美极品jizzhd欧美| 日本va欧美va欧美va精品| 天天操天天干天天操天天干| 欧美日韩国产影片| 色婷婷av在线| 久久一区二区三区欧美亚洲| 久久成人亚洲| 妖精视频在线观看免费| 日韩美女在线视频| 蜜桃视频动漫在线播放| 日韩欧美激情一区二区| 国产一区二区三区香蕉| 久久久久久久国产视频| 亚洲欧美一区二区三区四区| 精品美女一区| 日韩精品久久一区二区| 久久亚洲一级片| 亚洲天堂视频在线| 久久久免费电影| 久久综合欧美| 免费不卡av网站| 一本在线高清不卡dvd| 日本高清视频在线观看| 国产精品综合久久久久久| 日韩中文欧美在线| 久久久久99精品成人片毛片| 亚洲欧美一区二区激情| 精品视频一区二区三区| 日本精品免费在线观看| 亚洲欧美另类在线| 精品成人一区二区三区免费视频| 91人成网站www| 久久久久久色| 久一视频在线观看| 在线中文字幕日韩| 欧美日韩一本| 国产精品久久久久久久av福利| 欧美日韩亚洲高清| 成人影院在线看| 欧洲一区二区在线| 国产aⅴ精品一区二区三区色成熟| www.亚洲激情|