首页 > 其他分享 >使用 div 自定义 input 和 textarea

使用 div 自定义 input 和 textarea

时间:2025-01-21 16:57:13浏览次数:3  
标签:textarea 自定义 输入框 内容 inputBox input div placeholder

1. 为什么要自定义呢?

原生的 input 和 textarea 在某些特定场景下存在功能或兼容性限制,因此使用 div 元素自定义实现,突破原生输入框在样式、功能、兼容性上的限制。

1、解决火狐浏览器换行问题

某些版本的火狐浏览器中,原生 textarea 存在回车不换行而显示为空格的问题。这种行为在开发文本编辑器或多行输入框时造成不便。

2、提供更灵活的样式和内容格式

原生 input 和 textarea 元素样式定制有限,比如:无法直接改变 textarea 的行高或在内容中插入动态元素,如:标签或图标。原生输入框的内容只能是纯文本,难以直接支持复杂的文本格式,如:加粗、斜体或自定义样式。

3、跨平台或多浏览器兼容

不同的浏览器和设备对原生输入框的支持程度有所不同,尤其是一些老旧浏览器或特定版本的浏览器可能会对 input 和 textarea 产生不同的渲染结果。

2. 实现方法

contenteditable = "true" 是一个 HTML 属性,能够将 div 或其他元素变成一个可编辑的区域。用户可以输入文本,而浏览器会处理光标、输入等基本交互行为。通过监听相应的事件,可以让这个可编辑的 div 元素实现更复杂的行为和功能。

2.1 实现带 placeholder 的输入框

div 本身并没有内建的 placeholder 属性,但可以使用 CSS 和 JavaScript 来模拟该功能。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <style>
      .custom-input {
        border: 1px solid #ccc;
        padding: 5px;
        border-radius: 4px;
        outline: none;
        word-wrap: break-word; /* 自动换行 */
        white-space: pre-wrap; /* 支持空格换行 */
        overflow-y: auto;
        position: relative;
      }
      .custom-input-wrapper {
        position: relative;
      }
      .custom-input:empty::before {
        content: attr(data-placeholder); /* 使用 data-placeholder */
        color: #aaa;
        position: absolute;
        top: 5px;
        left: 8px;
        pointer-events: none;
      }
    </style>
  </head>
  <body>
    <div class="custom-input-wrapper">
      <div class="custom-input" contenteditable="true" data-placeholder="请输入内容..."></div>
    </div>

    <script>
      const inputBox = document.querySelector('.custom-input');

      // 监听输入事件,动态处理内容为空时显示 placeholder
      inputBox.addEventListener('input', () => {
        if (!inputBox.textContent.trim()) {
          inputBox.setAttribute('data-placeholder', '请输入内容...');
        } else {
          inputBox.removeAttribute('data-placeholder');
        }
      });
    </script>
  </body>
</html>

效果展示:

2.2 实现内容插入到光标位置

插入内容到光标位置是自定义输入框中非常常见的需求,例如:在文本框中插入表情符号或链接等。通过 JavaScript 中的 Range 和 Selection API,可以精确控制光标位置。

<button>插入内容</button>
<div class="custom-input" contenteditable="true" data-placeholder="请输入内容..."></div>

<script>
  function insertTextAtCursor(text) {
    const selection = window.getSelection();
    const range = selection.getRangeAt(0);
    range.deleteContents(); // 删除选中内容
    const textNode = document.createTextNode(text);
    range.insertNode(textNode); // 插入新内容
    range.setStartAfter(textNode); // 设置光标到插入文本后
    range.collapse(true); // 合并范围
    selection.removeAllRanges();
    selection.addRange(range);
  }

  document.querySelector('button').addEventListener('click', () => {
    insertTextAtCursor('插入的内容');
  });
</script>

效果展示:

3. 优缺点

3.1 优点

1、兼容性

使用 word-wrap: break-word 和 white-space: pre-wrap,可以确保不同浏览器中实现的换行行为一致。

2、灵活性

可以完全自定义样式和行为,比如控制光标的样式、输入框的大小、边框样式等。此外,使用 JavaScript 可以更加方便地动态插入和编辑内容。

3、支持插入光标位置

通过 Selection 和 Range API,可以精确的将文本插入到当前光标位置。

3.2 缺点

1、事件监听复杂

与原生的 input 和 textarea 不同,设置 contenteditable = "true" 的元素需要手动管理 placeholder 的显示与隐藏,处理焦点事件(focus、blur)和输入事件等,增加开发复杂性。

2、内容格式问题

由于 div 中的内容是可以包含 HTML 的,用户可能会误输入 HTML 标签或其他不合适的内容,要求开发者处理内容时格外小心,避免引发 XSS(跨站脚本攻击)等安全问题,且需要对输入内容进行过滤和清理。

3、性能问题

对于输入内容较长的情况,频繁的 DOM 操作可能会导致性能下降,尤其是当需要处理大量内容时,可能会影响用户体验。

4. 存在问题

4.1 控制输入内容长度

contenteditable 默认不限制输入,需要额外监听 input 事件并判断长度。

inputBox.addEventListener('input', () => {
  const maxLength = 200;
  if (inputBox.textContent.length > maxLength) {
    inputBox.textContent = inputBox.textContent.slice(0, maxLength);
  }
});
4.2 处理用户粘贴带有 HTML 内容

用户粘贴内容时,可能会不小心粘贴带有 HTML 标签的内容。我们可以通过监听 paste 事件,过滤粘贴内容,只保留纯文本:

inputBox.addEventListener('paste', (event) => {
  event.preventDefault();
  const text = event.clipboardData.getData('text/plain');
  document.execCommand('insertText', false, text);
});

总结

使用 contenteditable="true" 属性,可以实现一个高度自定义、功能强大的输入框,克服原生 input 和 textarea 的局限性。

标签:textarea,自定义,输入框,内容,inputBox,input,div,placeholder
From: https://blog.csdn.net/weixin_52648900/article/details/145032650

相关文章

  • [Tools] 自定义ESLint插件
    自定义ESLint插件ESLint插件主要是用来扩展ESLint本身没有的功能,这里包括扩展规则、扩展配置、扩展解析器。90%的ESLint插件都是以扩展规则为主,所以这些插件里面会包含大量的自定义规则。像这一类的插件,一般一条规则会对应一个JS文件,JS文件里面需要导出一个对象:module.expo......
  • CF div1+2 999 (A~E)
    赛时三题,\(D\)就差一个显然的剪枝就能过了,qwq...A显然第一步能选偶数就选偶数,之后只能选奇数。细节见代码。codeB对于选取的任意四条边,设腰为\(x\),短边为\(a\),长边为\(b\),则能形成等腰梯形的充要条件为:\(x\)出现次数\(>=2\),且\(a+2*x>b\)。两个腰选最大,并且\(a,b\)尽可能接近......
  • 写一个方法来获取div到浏览器窗口的高度
    在前端开发中,你可以使用JavaScript的getBoundingClientRect()方法来获取一个元素(比如div)相对于浏览器窗口的位置和大小。这个方法返回一个DOMRect对象,其中包含了top、right、bottom和left等属性,分别表示元素各边到视口(viewport)的距离。为了获取一个div元素到浏览器窗口顶部的高度......
  • ROS自定义消息类型
    1.std_msgs消息类型如下:来源:std_msgsMsg/SrvDocumentationstd_msgs的消息类型大致可以分为:基础类型,如Bool数组类型,如Float32MultiArray结构体类型。如Header我们可以在ROSIndex这里查到各种类型的消息包。std_msgs相对比较常用,包含各种基本的消息类型,我们在构建自......
  • Codeforces Round 998 (Div. 3) 部分题解
    写题解的时候这场在评测,就不放代码了。E.GraphComposition题意给两个无向简单图,对图\(1\)添加若干条边或删除若干条边,使得两图的连通性一致,最少需要变更多少条边。题解求出图\(2\)的连通性,考虑图\(1\)的所有边,若违背了图\(2\)联通性的要删除(图\(2\)不联通但图\(......
  • Codeforces Round 998 (Div. 3)
    题目链接:CodeforcesRound998(Div.3)总结:复建,Cwa两发,E读假题了。A.Fibonaccinesstag:签到Solution:简单模拟一下即可。voidsolve(){inta[5];for(inti=0;i<5;i++){if(i==2){continue;}cin>>a[i];......
  • CF div3 998(F,G)
    F\(dp\)+组合数学需要注意,数组中\(>1\)的数字个数不会超过\(log_{2}k\)个。先暂时不考虑\(1\)的摆放,只考虑所有\(>1\)的数:设\(f_{l,i}:\)长度为\(l\),乘积为\(i\),且所有元素均\(>1\)的数组个数考虑数组的最后一个元素\(d\),必有\(d|i\)成立,因为每个元素一定是\(i\)的因子。则......
  • FastReport调用Delphi中的自定义函数(人民币大写金额)
    人民币大写金额转换函数1functionMoneyToCn(ANumberic:Real):string;2const3s1:string='零壹贰叁肆伍陆柒捌玖';4s2:string='分角元拾佰仟万拾佰仟亿拾佰仟万';56functionStrTran(constS,s1,s2:string):string;7begin8Result:=St......
  • linux 将自定义程序做成服务开机自启动
    在linux系统中有很多方式可以将自定义程序设置成开机自启动,本文所述的方式是通过将程序设置成service来实现自启动。在/lib/systemd/system目录下新建hello.service文件touch/lib/systemd/system/hello.servicevim/lib/systemd/system/hello.service[Unit]Descrip......
  • [oeasy]python062_提示符是怎么来的_[词根溯源]prompt_input_输入函数_提示符
    提示符是怎么来的_[词根溯源]prompt_input_输入函数_提示符回忆上次内容上次讲的是从键盘输入变量的值 input函数可以接收到输入字符串存在变量里   添加图片注释,不超过140字(可选) input函数的参数叫prompt......