当前位置: 首页 > Web前端 > HTML5

如果没有框架呢?原生CSS+JS实现标签输入框

时间:2023-04-05 17:27:04 HTML5

欢迎关注我的公众号:前端侦探最近在项目中需要做一个标签输入框,比较实用,演示效果如下。主要的交互需求就是这样一个点击输入框可以输入内容回车生成标签。按退格键删除标签。单击标签上的关闭按钮可删除标签。我习惯了各种React框架或UI库。你有多久没有接触原生开发了?有时候页面比较简单,不需要引入完整的框架,原生实现完全满足,一起来看看吧1.自适应输入框布局无论什么组件,布局都是最重要的。这个布局分为标签和输入框两部分。假设HTML如下添加标签">

简单修改.tags-content{display:flex;弹性包装:包装;对齐项目:弹性启动;间隙:6px;宽度:400px;框大小:边框框;填充:8px12px;边框:1px实心#D9D9D9;边界半径:4px;字体大小:16px;;溢出:自动;光标:文本;}标签{显示:弹性;对齐项目:居中;填充:4px04px8px;字体大小:16px;行高:24px;背景:#F5F5F5;0,0,0,0.85);cursor:default;}tag-close{width:18px;高度:18px;游标:指针;background:url("data:image/svg+xml,%3Csvgwidth='10'height='10'viewBox='001010'fill='none'xmlns='http://www.w3.org/2000/svg'%3E%3Cpathd='M5.5785l2.93-3.493a.089.089000-.068-.146h-.891a.182.182000-.137.064l-2.4172.88-2.416-2.88a.178.178000-.137-.064h-.89a.089.089000-.069.146L4.4135l-2.933.493a.089.089000.068.146h.89a.182.18200-0.138.064l2.416-2.882.4172.88c.033.04.083.064.137.064h.89a.089.089000.069-.146l-2.93-3.493z'fill='%23000'fill-opacity='.45'/%3E%3C/svg%3E")centerno-repeat;}.tags-input{flex:auto;border:0;outline:0;padding:4px0;line-height:24px;font-size:16px;}.tags-content:focus-within,.tags-content:active{outline:auto#4F46E5;}注意一些实现技巧:标签之间的间隔可以通过gap来实现,以使输入的区域box填充剩余空间,这里使用了flex:auto来让parent保持焦点,这里使用了:focus-within效果如下,但是这里的输入框还是有些问题,如下图,因为输入内容不能跟随宽度自适应,所以有时候会出现文字被截断的情况理想情况下,当输入内容很多的时候,应该整体换行如何?可以用普通的div实现CSS
可以通过添加contenteditable或者下面的CSS.tags-input{-webkit-user-modify:read-write-plaintext-only;}这个属性表示只显示纯文本允许输入文本,有兴趣的可以参考张新旭的这篇文章:小提示:如何让contenteditable元素只输入纯文本,使其适应内容宽度。div标签,没有占位符属性。但是,我们仍然可以通过其他CSS特性来实现占位符效果。当输入框没有内容时,可以匹配:empty选择器,然后通过伪元素::before动态生成占位符内容。具体实现如下。tags-input:empty::before{content:attr(placeholder);color:#828282;}效果如下,和input的placeholder效果差不多。另外,还有一种情况,如果需要在没有标签占用的时候才显示,怎么实现呢?想一想,没有任何标签,HTML变成这样
这种情况下,输入框中只剩下only元素,only元素可以通过only-child匹配,所以实现如下。tags-input:only-child:empty::before{content:attr(placeholder);color:#828282;}这样加一个伪类就解决了两个需求,符合认知。这取决于设计如何决定。3、标签的输入和删除要实现标签的输入和删除,需要用到JS,只需要监听键盘的“Enter”和“Backspace”两个键值即可。需要注意的是,默认情况下,当输入一个普通的contenteditable元素时,会出现一个换行符,如下。所以在监听键盘事件的时候,需要阻止default事件,然后动态创建一个label元素,通过before添加到输入框的最前面。具体实现如下//TagInput为输入框TagInput.addEventListener('keydown',function(ev){if(ev.key==='Enter'){ev.preventDefault()if(this.innerText){//输入框内容通过innerText=document.createElement('TAG');tag.innerHTML=this.innerText+'';this.before获取consttag(tag);this.innerText='';}}})这样就可以正常创建标签,然后删除标签。这里有两种方式。先看键盘的删除。具体逻辑是当输入框内容为空时删除标签。这很简单。删除的标签是输入框的前一个元素,通过previousElementSibling获取。具体实现如下判断前一个元素是否存在}})然后点击删除图标上的删除。由于标签是动态生成的,所以这里需要使用事件委托来增删事件//TagContent是父容器TagContent.addEventListener('click',function(ev){if(ev.target.className==='tag-close'){ev.target.parentNode.remove();}TagInput.focus();//点击任意位置聚焦输入框})这样就实现了文章开头的效果。完整代码可以访问:input-tag4.选择framework还是native?综上所述,整体实现并不复杂。很多交互逻辑CSS也可以轻松实现。JS只需要10行左右的代码。-plaintext-only普通div元素输入可以自适应内容宽度。普通div元素输入框的占位符可以通过:empty结合伪元素实现回车事件。默认事件需要被阻止,否则会回绕。可以在元素前面添加新元素。使用before方法删除元素的前一个元素。您可以使用previousElementSibling.remove方法将事件绑定到动态生成的元素。您可以使用事件委托。在各种框架流行的氛围下,一些原生的属性和方法可能不是很好。注意,这也是一种损失。当然各种框架我也是会用的,特别是大而复杂的交互页面,一般都是小交互,比如文章的例子,antdesign里面有相关的组件,我也用过,因为整体UI都是这样的,这个款式也是按照这个设计来设计的。后来需要单独开发一个chrome插件,也用到这样的交互,但是只用这么一个组件引入整个框架太麻烦了,所以还是选择直接native实现简单方便.最后,如果觉得对你有好处和帮助,欢迎点赞、收藏、转发???欢迎关注我的公众号:前端大侦探