textarea文本高度自定义-组件开发[textarea]

技术 · 07-30 · 访问: 148 次

textarea 在开发中常常被使用到,但默认的 textarea 效果并不能满足我们的需求,比如信息发送框,如果直接使用 input 的话,在长文本内容中会显得十分拥挤,如果直接使用 textarea 则在未填充内容时显得过于空旷,因此我们需要自定义 textarea 的样式,使其在未填充内容时也能保持一定的宽度,同时也能在长文本内容中自动换行并调整高度。效果如下:

GIF 2024-7-30 11-40-26.gif

这里主要通过监听 textarea 的 input 事件,从而获取 textarea 的内容区域高度,从而调整 textarea 的高度,实现文本内容超出宽度时高度调整的效果。

代码示例:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {padding: 0;margin: 0;box-sizing: border-box;}
        textarea {outline: none;border: none;resize: none;line-height: 20px;font-size: 14px;font-family: SF Pro Display, -apple-system, BlinkMacSystemFont, Segoe UI, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Helvetica Neue, Helvetica, Arial, sans-serif;}
        button.send {margin-left: 12px;font-size: 14px;font-weight: bold;transition: all .6s;color: #c6c6cd;outline: none;border: 0;background-color: unset;cursor: pointer;}
        button.send:hover {color: #4d53e8;}
        .textarea-with-top-rows {position: fixed;left: 50%;top: 50%;transform: translateX(-50%) translateY(-50%);}
        .textarea-with-top-rows {width: 548px;min-height: 48px;padding: 12px 12px 12px 16px;border: 1px solid #ccc;border-radius: 24px;display: flex;align-items: center;}
        .textarea-with-top-rows.input-focus {border-color: #4d53e8;}
        .textarea-with-top-rows textarea {flex: 1;padding: 2px;overflow-y: hidden;}
        .textarea-with-top-rows textarea::selection {background-color: #d0d2fb;}
        .textarea-with-top-rows textarea::placeholder {color: #ccc;}
    </style>
</head>

<body>

    <div class="textarea-with-top-rows">
        <textarea style="min-height: 24px;height: 24px;" placeholder="发送消息..."></textarea>
        <button type="button" class="send">发送</button>
    </div>

    <script>
        const textareaWithTopRows = document.querySelector('.textarea-with-top-rows');
        const textareaWithInput = document.querySelector('.textarea-with-top-rows textarea');
        const textareaWithSend = document.querySelector('.textarea-with-top-rows .send');

        // 最多显示的行数
        const rows = 6;
        // 基础高度
        const baseHeight = 24;
        // 每行高度
        const lineHeight = 20;

        const handlerTextAreaSend = function () {
            textareaWithInput.value = '';
            // 重新处理高度
            handlerTextAreaInput.apply(textareaWithInput);
        }

        // 监听 textarea 的输入事件
        const handlerTextAreaInput = function () {
            this.style.height = `${baseHeight}px`;
            const scrollHeight = this.scrollHeight;
            const height = scrollHeight - baseHeight;
            const row = Math.ceil(height / lineHeight);
            if (row >= rows) {
                this.style.height = `${rows * lineHeight + lineHeight}px`;
                return;
            }
            this.style.height = `${scrollHeight}px`;
        }

        // textarea 聚焦事件
        const handlerTextAreaFocus = function () {
            textareaWithTopRows.classList.add('input-focus');
        }

        // textarea 失焦事件
        const handlerTextAreaBlur = function () {
            textareaWithTopRows.classList.remove('input-focus');
        }

        textareaWithSend.addEventListener('click', handlerTextAreaSend);
        textareaWithInput.addEventListener('input', handlerTextAreaInput);
        textareaWithInput.addEventListener('focus', handlerTextAreaFocus);
        textareaWithInput.addEventListener('blur', handlerTextAreaBlur);
        textareaWithInput.addEventListener('change', handlerTextAreaInput);
    </script>

</body>

</html>

知识点:

  1. textarea标签的样式操作

    • resize: none; 禁用textarea的拖拽
    • outline: none; 去除textarea的轮廓
    • ::placeholder 伪元素调整textarea中的占位符样式
    • ::selection 伪元素调整textarea中选中文本时的样式
  2. 通过 input 事件监听 textarea 内容变化

    • input事件: 输入数据时触发,比如键盘输入、粘贴操作或者拖放内容等。
  3. 通过 textarea 的 scrollHeight 属性获取 textarea 的高度

    • scrollHeight: 获取元素的内容区域的总高度,包括由于溢出而不可见的部分。它是一个只读属性,返回一个以像素为单位的整数值。

步骤:

  1. 基本 html 结构以及 css 样式搭建
  2. 通过 input 事件监听 textarea 内容变化
    2.1 通过 scrollHeight 属性获取内容区域高度,从而调整 textarea 高度
    2.2 获取内容区域高度前对 textarea 高度进行初始化,如果没有此步骤则无法在文本区域缩小时进行同步调整 textarea 高度

问题:

  1. 输入内容如何再文本内容超过 textarea 宽度时进行换行

    • 解决:通过 input 事件监听 textarea 内容变化,并通过 scrollHeight 进行调整 textarea 的高度,从而实现文本内容超出宽度时高度调整的效果。
  2. 当 textarea 高度有所增高时删除文本内容高度并不会降低

    • 解决:在获取文本内容高度之前对 textarea 高度进行初始化

测试:

  1. 普通长文本输入时自动换行并自动调整 textarea 高度
  2. 执行 Enter 键时换行并自动调整 textarea 高度
  3. 复制长内容时换行并自动调整 textarea 高度
  4. 删除文本内容时自动调整 textarea 高度
前端 组件开发 textarea
icon_mrgreen.gificon_neutral.gificon_twisted.gificon_arrow.gificon_eek.gificon_smile.gificon_confused.gificon_cool.gificon_evil.gificon_biggrin.gificon_idea.gificon_redface.gificon_razz.gificon_rolleyes.gificon_wink.gificon_cry.gificon_surprised.gificon_lol.gificon_mad.gificon_sad.gificon_exclaim.gificon_question.gif
Theme Jasmine by Kent Liao