使 html 文本输入字段在我键入时增长?

Posted

技术标签:

【中文标题】使 html 文本输入字段在我键入时增长?【英文标题】:make html text input field grow as I type? 【发布时间】:2011-11-02 09:08:36 【问题描述】:

我可以在 css 中设置初始文本输入大小,如下所示:

width: 50px;

但我希望它在我输入时增长,直到达到例如 200 像素。 这可以直接用css、html完成吗,最好不用javascript

当然也要发布您的 js/jquery 解决方案,但如果没有它们也可行 - 那太好了。

我在这里尝试:

http://jsfiddle.net/jszjz/2/

【问题讨论】:

我认为这个 SO 问题会对您有所帮助:***.com/questions/1288297/… 为了记录,不是我。似乎是一个有效的问题,尽管与我链接的问题相似。 Andre:请尽量让 cmets 保持建设性。 您可以使用带有 contenteditable 的段落。当您自己输入时,它会扩展。 【参考方案1】:

这是一个只有 CSS 和 Content Editable 的示例:

jsFiddle Example

CSS

span 

    border: solid 1px black;

div 

    max-width: 200px;   

HTML

<div>
    <span contenteditable="true">sdfsd</span>
</div>

关于contenteditable的重要说明

制作 HTML 元素 contenteditable 允许用户将复制的 HTML 元素粘贴到该元素中。这可能不适合您的用例,因此在选择使用它时请记住这一点。

【讨论】:

耶。我刚刚在 IE6-9、最新的 Opera、Firefox 和 Chrome - 和 OMG - 它在任何地方都可以使用! 对于 Chrome 中的我来说,当元素达到最大宽度时,它会将元素向下延伸一行。如果输入是表单的一部分,它也不会起作用。 对于多行输入字段(自定义换行符),将span 替换为div。请注意,word-wrap: break-word 是必需的,否则超过 max-width 的字词会溢出 div 框:jsfiddle.net/YZPmC/157 确保清除不需要的 html,这些 html 可能通过复制和粘贴进入 contenteditable 范围。 这是否与表格一起发送?【参考方案2】:

我只是为你写的,希望你喜欢 :) 不能保证它是跨浏览器的,但我认为它是 :)

(function()
    var min = 100, max = 300, pad_right = 5, input = document.getElementById('adjinput');

    input.style.width = min+'px';
    input.onkeypress = input.onkeydown = input.onkeyup = function()
        var input = this;
        setTimeout(function()
            var tmp = document.createElement('div');
            tmp.style.padding = '0';
            if(getComputedStyle)
                tmp.style.cssText = getComputedStyle(input, null).cssText;
            if(input.currentStyle)
                tmp.style.cssText = input.currentStyle.cssText;
            tmp.style.width = '';
            tmp.style.position = 'absolute';
            tmp.innerHTML = input.value.replace(/&/g, "&amp;")
                                       .replace(/</g, "&lt;")
                                       .replace(/>/g, "&gt;")
                                       .replace(/"/g, "&quot;")
                                       .replace(/'/g, "&#039;")
                                       .replace(/ /g, '&nbsp;');
            input.parentNode.appendChild(tmp);
            var width = tmp.clientWidth+pad_right+1;
            tmp.parentNode.removeChild(tmp);
            if(min <= width && width <= max)
                input.style.width = width+'px';
        , 1);
    
)();

JSFiddle

【讨论】:

感谢这个。我决定用 contenteditable 属性来做,虽然它不需要 js。 “我刚刚为你写了这个”。 +1 努力:) 我如何允许它使用id='adjinput'定位超过 1 (4) 个输入 非常有创意我喜欢它 这假定内容更改仅通过使用键盘发生。【参考方案3】:

如果将 span 设置为 display: inline-block,自动水平和垂直调整大小效果很好:

<span contenteditable="true" 
      style="display: inline-block;
             border: solid 1px black;
             min-width: 50px; 
             max-width: 200px">
</span>

【讨论】:

【参考方案4】:

以编程方式修改输入的 size 属性怎么样?

在语义上(imo),这个解决方案比公认的解决方案更好,因为它仍然使用输入字段进行用户输入,但它确实引入了一点 jQuery。 Soundcloud 为他们的标记做了类似的事情。

<input size="1" />

$('input').on('keydown', function(evt) 
    var $this = $(this),
        size = parseInt($this.attr('size'), 10),
        isValidKey = (evt.which >= 65 && evt.which <= 90) || // a-zA-Z
                     (evt.which >= 48 && evt.which <= 57) || // 0-9
                     evt.which === 32;

    if ( evt.which === 8 && size > 0 ) 
        // backspace
        $this.attr('size', size - 1);
     else if ( isValidKey ) 
        // all other keystrokes
        $this.attr('size', size + 1);
    
);

http://jsfiddle.net/Vu9ZT/

【讨论】:

如果您突出显示文本并按退格键,这将不起作用,因为它仅计为 size-1 而不是 size- $('input').val().length 我想计数value.length会更容易也更可靠。 删除键使这个增长【参考方案5】:

我想到了几件事:

在您的文本字段中使用onkeydown 处理程序,测量文本*,并相应地增加文本框大小。

:focus css 类附加到具有较大宽度的文本框。然后你的盒子在聚焦时会更大。这不是您所要求的,但类似。

* 在 javascript 中测量文本并不简单。查看this question 了解一些想法。

【讨论】:

迄今为止的最佳答案。 :focus width: 100% 【参考方案6】:

发件人:Is there a jQuery autogrow plugin for text fields?


在此处查看演示:http://jsbin.com/ahaxe

插件:

(function($)

    $.fn.autoGrowInput = function(o) 

        o = $.extend(
            maxWidth: 1000,
            minWidth: 0,
            comfortZone: 70
        , o);

        this.filter('input:text').each(function()

            var minWidth = o.minWidth || $(this).width(),
                val = '',
                input = $(this),
                testSubject = $('<tester/>').css(
                    position: 'absolute',
                    top: -9999,
                    left: -9999,
                    width: 'auto',
                    fontSize: input.css('fontSize'),
                    fontFamily: input.css('fontFamily'),
                    fontWeight: input.css('fontWeight'),
                    letterSpacing: input.css('letterSpacing'),
                    whiteSpace: 'nowrap'
                ),
                check = function() 

                    if (val === (val = input.val())) return;

                    // Enter new content into testSubject
                    var escaped = val.replace(/&/g, '&amp;').replace(/\s/g,'&nbsp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
                    testSubject.html(escaped);

                    // Calculate new width + whether to change
                    var testerWidth = testSubject.width(),
                        newWidth = (testerWidth + o.comfortZone) >= minWidth ? testerWidth + o.comfortZone : minWidth,
                        currentWidth = input.width(),
                        isValidWidthChange = (newWidth < currentWidth && newWidth >= minWidth)
                                             || (newWidth > minWidth && newWidth < o.maxWidth);

                    // Animate width
                    if (isValidWidthChange) 
                        input.width(newWidth);
                    

                ;

            testSubject.insertAfter(input);

            $(this).bind('keyup keydown blur update', check);

        );

        return this;

    ;

)(jQuery);

【讨论】:

【参考方案7】:

在这里你可以尝试这样的事情

编辑:修订示例(添加了一个新解决方案) http://jsfiddle.net/jszjz/10/

代码说明

var jqThis = $('#adjinput'), //object of the input field in jQuery
    fontSize = parseInt( jqThis.css('font-size') ) / 2, //its font-size
    //its min Width (the box won't become smaller than this
    minWidth= parseInt( jqThis.css('min-width') ), 
    //its maxWidth (the box won't become bigger than this)
    maxWidth= parseInt( jqThis.css('max-width') );

jqThis.bind('keydown', function(e) //on key down
   var newVal = (this.value.length * fontSize); //compute the new width

   if( newVal  > minWidth && newVal <= maxWidth ) //check to see if it is within Min and Max
       this.style.width = newVal + 'px'; //update the value.
);

而且css也很简单

#adjinput
    max-width:200px !important;
    width:40px;
    min-width:40px;
    font-size:11px;

编辑:另一种解决方案是让用户输入他想要的内容并模糊(聚焦),抓住字符串(以相同的字体大小)将它放在一个 div 中 - 计算 div 的宽度 - 然后用一个漂亮的动画用很酷的缓动效果更新输入字段的宽度。唯一的缺点是在用户键入时输入字段将保持“小”。或者你可以添加一个超时:)你也可以在上面的小提琴上检查这种解决方案!

【讨论】:

font-size 不是一个完美的解决方案。不错,当然不值得投反对票,但是尝试多次输入字母i,您会看到大小非常不准确的结果。请参阅我的答案以解决此问题。 请参阅我的小提琴中的第二个示例,它不使用字体大小并选择平滑度。第一个是为了速度和速度而添加的——同时保持提问者想要的。对于我来说,每次都必须创建一个 div 附加文本、计算其宽度等,这对我来说似乎“很重”。 我不知道为什么,但你的第二个例子对我来说根本没有调整大小。还要记住,我的解决方案(它确实创建了一个临时 div 等)可以在现代浏览器中平均每秒运行大约 800 次,并且在 99.5 上可能不会比每秒 100 次慢很多目前仍在使用的计算机的百分比)【参考方案8】:

我知道这是一篇很老的帖子 - 但无论如何我的回答可能对其他人有用,所以就这样吧。 我发现如果我对 contenteditable div 的 CSS 样式定义的最小高度为 200 而不是高度为 200 ,那么 div 会自动缩放。

【讨论】:

【参考方案9】:

如果您只是对增长感兴趣,您可以将width 更新为scrollWidth,只要input 元素的内容发生变化。

document.querySelectorAll('input[type="text"]').forEach(function(node) 
  node.onchange = node.oninput = function() 
    node.style.width = node.scrollWidth+'px';
  ;
);

但这不会缩小元素。

【讨论】:

【参考方案10】:

当然,您使用哪种方法取决于您的最终目标是什么。如果您想使用表单提交结果,那么使用本机表单元素意味着您不必使用脚本来提交。此外,如果关闭脚本,则回退仍然有效,没有花哨的增长-收缩效果。如果你想从 contenteditable 元素中获取纯文本,你也可以随时使用像 node.textContent 这样的脚本来去除浏览器在用户输入中插入的 html .

此版本使用原生表单元素,对之前的一些帖子进行了细微的改进。

它也允许内容缩小。

将此与 CSS 结合使用以获得更好的控制。

<html>

<textarea></textarea>
<br>
<input type="text">


<style>

textarea 
  width: 300px;
  min-height: 100px;


input 
  min-width: 300px;



<script>

document.querySelectorAll('input[type="text"]').forEach(function(node) 
  var minWidth = parseInt(getComputedStyle(node).minWidth) || node.clientWidth;
  node.style.overflowX = 'auto'; // 'hidden'
  node.onchange = node.oninput = function() 
    node.style.width = minWidth + 'px';
    node.style.width = node.scrollWidth + 'px';
  ;
);

你可以在

document.querySelectorAll('textarea').forEach(function(node) 
  var minHeight = parseInt(getComputedStyle(node).minHeight) || node.clientHeight;
  node.style.overflowY = 'auto'; // 'hidden'
  node.onchange = node.oninput = function() 
    node.style.height = minHeight + 'px';
    node.style.height = node.scrollHeight + 'px';
  ;
);

这在 Chrome 上不会闪烁,其他浏览器的结果可能会有所不同,所以测试一下。

【讨论】:

【参考方案11】:

您可以使用display: inline-grid

const dummy = document.querySelector(".dummy");
const input = document.querySelector("input");

const update = () => dummy.innerText = input.value;
input.oninput = update;
update();
.growing-input 
  display: inline-grid;


.growing-input .dummy,
.growing-input input 
  grid-area: 1 / 1;
  
  /* Following properties just need to be consistent,
  to ensure the .dummy and the input take up the same space */
  font: inherit;
  padding: 0 0.25em;
  margin: 0;
  border: 1px solid grey;
  border-radius: 2px;


.growing-input .dummy 
  visibility: hidden;
  white-space: pre-wrap;
Here's an 
<span class="growing-input">
  <input type="text" value="auto-resizing input" size="1" />
  <span class="dummy"></span>
</span>; have fun!

这个想法是创建一个包含与input 相同内容的虚拟元素,然后设置input 的宽度以匹配虚拟元素的宽度。上面我们使用 JavaScript 来同步文本,并使用 display: inline-grid 技巧来设置 input 的宽度以匹配。

(此方法取自this article;我已将其浓缩为基本要素。)

【讨论】:

【参考方案12】:

这是一种对我有用的方法。当您在字段中键入时,它会将文本放入隐藏范围,然后获取其新宽度并将其应用于输入字段。它会随着您的输入而增长和缩小,当您删除所有输入时,它可以防止输入几乎消失。在 Chrome 中测试。 (编辑:在编辑时适用于 Safari、Firefox 和 Edge)

function travel_keyup(e)

    if (e.target.value.length == 0) return;
    var oSpan=document.querySelector('#menu-enter-travel span');
    oSpan.textContent=e.target.value;
    match_span(e.target, oSpan);

function travel_keydown(e)

    if (e.key.length == 1)
    
        if (e.target.maxLength == e.target.value.length) return;
        var oSpan=document.querySelector('#menu-enter-travel span');
        oSpan.textContent=e.target.value + '' + e.key;
        match_span(e.target, oSpan);
    

function match_span(oInput, oSpan)

    oInput.style.width=oSpan.getBoundingClientRect().width + 'px';


window.addEventListener('load', function()

    var oInput=document.querySelector('#menu-enter-travel input');
    oInput.addEventListener('keyup', travel_keyup);
    oInput.addEventListener('keydown', travel_keydown);

    match_span(oInput, document.querySelector('#menu-enter-travel span'));
);
#menu-enter-travel input

	width: 8px;

#menu-enter-travel span

	visibility: hidden;
    position: absolute;
    top: 0px;
    left: 0px;
<div id="menu-enter-travel">
<input type="text" pattern="^[0-9]1,4$" maxlength="4">KM
<span>9</span>
</div>

【讨论】:

【参考方案13】:

如果您被允许使用 ch 测量(等宽),它完全解决了我想要做的事情。

onChange(e => 
    e.target.style.width = `$e.target.lengthch`;
)

这正是我需要的,但我不确定它是否适用于动态宽度字体系列。

【讨论】:

【参考方案14】:

对于那些严格寻找适用于输入或文本区域的解决方案的人,this 是我遇到的最简单的解决方案。只有几行CSS和一行JS。

JavaScript 在元素上设置一个 data-* 属性等于 输入值。输入设置在 CSS 网格中,其中 grid 是一个伪元素,它使用 data-* 属性作为它的 内容。该内容是将网格扩展到适当的 大小基于输入值。

【讨论】:

【参考方案15】:

您需要做的就是,获取您想要在输入和 CSS 中增长的输入字段的元素,将输入的宽度设置为自动并将最小宽度设置为 50 像素。

【讨论】:

欢迎来到 Stack Overflow。请阅读如何回答。 ***.com/questions/how-to-answer

以上是关于使 html 文本输入字段在我键入时增长?的主要内容,如果未能解决你的问题,请参考以下文章

输入时如何将文本字段格式设置为十进制?

单击时HTML字段中的文本消失?

UITextField(有时)在键入时使应用程序崩溃

键入另一个文本字段时,动态文本字段数据将丢失

如何使用软键盘在输入编辑文本字段区域中键入自定义字体? [关闭]

在文本字段中输入值后如何显示*