基于原生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(); //点击任意地方输入框都需要聚焦
})

这样就实现了文章开头的所示效果:

四、选择框架还是原生

总结一下!

整体实现并不算复杂,不少交互逻辑 CSS 也可以轻松实现,JS 也就 10 来行代码,这里总结一下实现要点:

  • 普通 div 元素输入纯文本可以使用 -webkit-user-modify: read-write-plaintext-only
  • 普通 div 元素输入可以自适应内容宽度
  • 普通 div 元素输入框的 placeholder 占位可以通过 :empty 结合伪元素实现
  • 回车事件需要阻止默认事件,不然会换行
  • 在一个元素的前面新增元素可以用 before 方法
  • 删除一个元素的前面一个元素,可以用 previousElementSibling.remove 方法
  • 给动态生成的元素绑定事件可以用事件委托的方式

在各种框架大行其道的氛围下,有些原生的属性和方法可能都不太关注了,这也不失为是一种损失。当然,我本身也是各种框架都会用,特别是大型、复杂的交互页面,一般比较小的交互,比如文章这个例子,在 ant design 中有相关的组件,也使用过,因为整体 UI 全是这种风格,设计也是按照这个设计的。后来需要单独开发一个 chrome 插件,也用到了这样一个交互,但是仅仅用了这样一个组件,引入整个框架就过于累赘了,所以还是选择直接原生实现,简单方便。

以上就是基于原生CSS+JS实现一个标签输入框的详细内容,更多关于JS标签输入框的资料请关注我们其它相关文章!

(0)

相关推荐

  • JavaScript实现一个输入框组件

    本文实例为大家分享了手动实现一个输入框组件的具体代码,供大家参考,具体内容如下 背景 taro h5中想要实现一个样式如下的输入框: 问题: taro组件和taro-ui组件中都没有这种样式的组件,taro h5 中还不支持修改placeholder的样式,自己尝试着实现一个input组件,更能灵活的定义其中的样式. 实现 js代码 import Taro, { Component } from '@tarojs/taro'; import { View } from '@tarojs/comp

  • JS实现身份证输入框的输入效果

    实现如图所示的输入效果: 实现这种效果,比较简单的一种方式就是给一个input添加一个背景图片,然后通过设置字间距来达到效果. 代码: html: <input type="text" maxlength="8" class="idInput" onkeyup='this.value=this.value.replace(/\D/gi,"")'> css: .idInput{ width: 24.95rem; he

  • javascript实现输入框内容提示及隐藏功能

    有时输入框较小,希望输入内容后,出现一个有放大输入内容的提示框 实现思路 页面上先编写出提示框,然后将提示框的css属性:display设置成none,隐藏起来 获取输入框元素对象.信息提示框元素对象 为输入框元素对象绑定键盘事件- - -keyup, 事件处理程序:判断输入的内容是否为空,不为空- - -将输入框的内容赋值给信息提示框,并设置信息提示框显示:display设置成block:为空,设置提示框不显示 添加获取焦点和失去焦点事件. blur- - -失去焦点:鼠标不选中输入框,输入框

  • js模拟支付宝密码输入框

    本文实例为大家分享了js模拟支付宝密码输入框效果的具体代码,供大家参考,具体内容如下 效果图: 代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <style> input{ width:60px; height:60px; fon

  • 手动实现js短信验证码输入框

    前言 本文记录一下自己手动实现的一个前端常见的短信验证码输入组件,从需求到实现逐步优化的过程. 正文 1.需求分析 首先看一下效果图. 首先页面加载的时候,输入框获取焦点,当用户输入一个数字后,焦点自动跳转到第二个框,当四个框全部输入后,模拟发送提交请求,这里用一个弹框提示,输出输入的验证码内容.主流程之外的需求: 输入框内只能输入数字类型,不能输入字母,若强制输入非数字类型按下撤回键时候输入的验证码置空并且把当前焦点跳转至第一个输入框. 2.完整代码实现. 大致思路就是页面加载的时候,给第一个

  • 基于原生CSS+JS实现一个标签输入框

    目录 一.自适应输入框布局 二.输入框占位提示 三.标签的输入与删除 四.选择框架还是原生 最近在项目中需要做一个标签输入框,还挺实用的,演示效果如下: 主要交互要求是这样的: 点击输入框可以输入内容. 按回车可以生成标签. 按退格键可以删除标签. 点击标签上的关闭按钮可以删除标签. 习惯了各种 react 框架或者UI库,大家有多久没接触没有原生开发了呢?有时候页面比较简单,没必要引入一个完整的框架,原生实现就完全满足了,一起看看吧! 一.自适应输入框布局 不管什么组件,布局都是最重要的.这个

  • 基于Html+CSS+JS实现手动放烟花效果

    目录 效果展示 实现代码 Html Css JavaScript 雷迪森安的乡亲们,欢迎来到老实人的前端课堂,上次写了一个新春小盲盒,这大过年的,我把烟花都给你们准备好了,今天我们来写个小烟花吧. 效果展示 注意看有两种模式哦,可以自由切换,鼠标点哪里哪里有烟花,还可以自动放烟花 视频演示:html+css写一个烟花,源码请你直接拿走! 实现代码 Html <div id="tips"> <a id="manual" href="java

  • 基于HTML+CSS+JS实现纸牌记忆游戏

    目录 知识点 HTML 用户界面 CSS 部分 一些基本样式 纸牌的样式 分数面板的样式 祝贺面板的样式 动画 媒体查询 JavaScript 部分 洗牌功能 开始新游戏的功能 显示卡片的功能 当卡片匹配时的功能 当卡片不匹配时的功能 暂时禁用卡片的功能 启用卡片并禁用匹配的卡片的功能 计算玩家的动作的功能 显示游戏的时间 再次游戏功能 总结 这节实验我们将使用 HTML.CSS 和 JavaScript 制作纸牌记忆游戏. 让我们开始吧! 在线演示戳这里 知识点 animation-durat

  • 基于HTML+CSS+JS实现增加删除修改tab导航特效代码

    先给大家展示下效果图,如果大家感觉还不错,请参考实现代码哦! HTML: <div class="container iden_top"> <ul> <li> <p class='iden_add_name'>应用标识1</p> <span class="iden_top_button"></span> <div class="iden_top_dete"&

  • 基于html+css+js实现简易计算器代码实例

    使用html+css+js实现简易计算器, 效果图如下: html代码如下 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http

  • 基于JS实现一个简单的投票demo

    目录 演示 说明 源码 body设置 js实现投票的动画 css设定 演示 说明 今天没有什么好的内容分享,跟大家讲一个标签吧增长姿势. line-height CSS 属性用于设置多行元素的空间量,如多行文本的间距. 根据浏览器的解析不同,line-height的表现方式有两种 1.基线之间的距离为line-height 2.lineHeight 为,font-size的上下加上半行距 它的取值为: 1·normal: 默认.设置合理的行间距.取决于用户端.桌面浏览器(包括Firefox)使用

  • 基于原生js运动方式关键点的总结(推荐)

    主要方法:定时器的运用 setInterval(funnction(){},30); 为了避免最后时刻速度即将停止时的误差,可以采用下面的方法: if(iSpeed<1)//速度足够小的时候,让速度直接为0,避免速度的波动 { iSpeed = 0; } 绝对值的运用(主要运用于弹性运动等速度有正负的情况): Math.abs(2.5)// 2 弹性运动和摩擦力的组合: iSpeed+=(iTarget-obj.offsetLeft)/5; iSpeed*=0.7; 模拟摩擦力: iSpeed*

  • 浅谈JS对html标签的属性的干预以及对CSS样式表属性的干预

    -任何标签的任何属性都可以修改! -HTML里是怎么写, JS就怎么写 以下是一段js 作用于 css 的 href的 代码 <link id="l1" rel="stylesheet" type="text/css" href="css1.css" rel="external nofollow" /> <script> function skin1() { var oL=docum

  • ASP.NET批量操作基于原生html标签的无序列表的三种方法

    在网页开发中,经常要用到无序列表.事实上在符合W3C标准的div+css布局中,无序列表被大量使用,ASP.NET虽然内置了BulletedList控件,用于创建和操作无序列表,但感觉不太好用.本篇介绍服务器端ASP.NET批量操作基于原生html标签的无序列表的三种方法. 方法一,将li元素做成html控件,加上id,用FindControl方法. aspx代码: <form id="form1" runat="server"> <ul>

  • 基于JS实现一个随机生成验证码功能

    效果展示 实现原理 1. html:一般就是一个div: <div id="code"></div> ,样式根据需求设计. 2. JS:1)将所有的验证码所用的字符放在一个字符串中 2)在这个字符串的字符个数以内,随机生成索引号 3)根据索引号查找对应字符,拼接成验证码的字符串 代码实现 HTML: <div id="code"></div> CSS: * { margin: 0; padding: 0; } div

随机推荐