将输入字段的宽度调整为其输入

Posted

技术标签:

【中文标题】将输入字段的宽度调整为其输入【英文标题】:Adjust width of input field to its input 【发布时间】:2011-03-24 11:28:42 【问题描述】:
<html>
  <head>
  </head>
  <body>
    <input type="text" value="1" style="min-width:1px;" />
  </body>
</html>

这是我的代码,它不起作用。 HTML、javascriptphp 或 CSS 中是否有其他方式来设置最小宽度?

我想要一个具有动态变化宽度的文本输入字段,以便输入字段围绕其内容流动。每个输入都有一个内置的填充 2em,这是问题所在,第二个问题是 min-width 根本无法处理输入。

如果我设置的宽度超过了整个程序的混乱程度,我需要 1px 的宽度,只有在需要时才需要更多。

【问题讨论】:

这能回答你的问题吗? Creating a textarea with auto-resize 【参考方案1】:

在现代浏览器版本中,CSS 单元 ch 也可用。据我了解,它是与字体无关的单位,其中1ch 等于任何给定字体中字符0(零)的宽度。

因此,像下面这样简单的东西可以用作调整大小的功能:

var input = document.querySelector('input'); // get the input element
input.addEventListener('input', resizeInput); // bind the "resizeInput" callback on "input" event
resizeInput.call(input); // immediately call the function

function resizeInput() 
  this.style.width = this.value.length + "ch";
input font-size:1.3em; padding:.5em; 
&lt;input&gt;

该示例会将“elem”的大小调整为值的长度 + 2 个额外字符。

单位 ch 的一个潜在问题是,在许多字体(即 Helvetica)中,字符“m”的宽度超过了字符 0 的宽度,而字符“i”则窄得多。 1ch 通常比平均字符宽度宽,根据this 的帖子,通常宽约 20-30%。

【讨论】:

我很惊讶这条评论没有得到更高的评价,因为它是一个很好的解决方案,大约 95% (1) 的浏览器支持这一点。 这根本不是一个好的答案,因为测量不准确并且没有考虑input元素上可能出现的样式,例如font-styleletter-spacing和很快。我已经通过现场演示编辑了答案。 如果您使用等宽字体,效果会很好。对于其他字体,您的里程可能会有所不同,因为它显然使用了 0 字符的字符宽度。 这真的很棒。虽然请注意,当遇到. 时,它有时会出错/无法按预期工作。 如果您将输入的 box-sizing 设置为“content-box”,这将非常有效。这样,当您设置大小时,它会忽略填充。【参考方案2】:

听起来您的期望是样式会根据文本框的内容动态应用于文本框的宽度。如果是这样,您将需要一些 js 来在文本框内容更改时运行,例如 this:

<input id="txt" type="text" onkeypress="this.style.width = ((this.value.length + 1) * 8) + 'px';">

注意:此解决方案仅适用于每个字符恰好为 8px 宽的情况。您可以使用代表所选字体中字符“0”的宽度的 CSS-Unit“ch”(字符)。你可以阅读它here。

【讨论】:

@Kerc & Tahbaza:是的,但这只有在每个字符的宽度正好是 8 像素时才有效。 我同意,Marcel(并且发布的代码并不是我真正看到的用途),但它表现出所需的行为。您知道如何在考虑字体、大小、粗细、字距调整等因素的情况下计算渲染文本的实际宽度吗?如果是这样,请分享,因为我会发现那段代码有时很有用。 ——我已经认为这只是一个例子。不过,计算输入的宽度并不难。看看我的回答。 em 单位是字符“m”的宽度。这对于计算字符串的宽度很有用。我已经看到将 em 单位应用于某些属性的跨浏览器问题,尽管如此进行测试。 你忘记了 PASTE 事件我的朋友;)你应该把它改成onInput【参考方案3】:

要计算当前输入的宽度,您必须将其嵌入到一个临时的 span 元素中,将该东西附加到 DOM,使用 scrollWidth 属性获取计算出的宽度(以像素为单位)并删除span 再次。当然,您必须确保在inputspan 元素中使用相同的字体系列、字体大小等。因此我给他们分配了相同的班级。

我将函数附加到keyup 事件,因为在keypress 上,输入字符尚未添加到输入value,因此会导致宽度错误。不幸的是,我不知道如何摆脱输入字段的滚动(在字段末尾添加字符时);它滚动,因为在调用 adjustWidthOfInput() 之前添加并显示了字符。而且,如前所述,我不能反过来这样做,因为这样您将获得输入字段的值在插入按下的字符之前。我稍后会尝试解决这个问题。

顺便说一句,我只在 Firefox (3.6.8) 中对此进行了测试,但我希望你会明白这一点。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Get/set width of &lt;input&gt;</title>
    <style>
      body 
        background: #666;
      

      .input-element 
        border: 0;
        padding: 2px;
        background: #fff;
        font: 12pt sans-serif;
      

      .tmp-element 
        visibility: hidden;
        white-space: pre;
      
    </style>
  </head>
  <body>
    <input id="theInput" type="text" class="input-element" value="1">
    <script>
      var inputEl = document.getElementById("theInput");

      function getWidthOfInput() 
        var tmp = document.createElement("span");
        tmp.className = "input-element tmp-element";
        tmp.innerHTML = inputEl.value.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
        document.body.appendChild(tmp);
        var theWidth = tmp.getBoundingClientRect().width;
        document.body.removeChild(tmp);
        return theWidth;
      

      function adjustWidthOfInput() 
        inputEl.style.width = getWidthOfInput() + "px";
      

      adjustWidthOfInput();
      inputEl.onkeyup = adjustWidthOfInput;
    </script>
  </body>
</html>

【讨论】:

我喜欢你的回答,甚至使用 jQuery/Underscore 实现了它:gist.github.com/3745941。但是,我可以做出某些假设:(1) 任何字符的宽度不超过 14 像素,(2) 让输入元素超出元素值 14 像素是可以接受的。我已将此附加到 keydown 事件,并且效果很好! 你应该以这种方式将white-space: pre;添加到css中:.tmp-element visibility: hidden; white-space: pre;。否则空格会合并,宽度计算会失败。 &lt;input&gt;&lt;span&gt; 在空白处理方面表现不同,&lt;input&gt; 保留空白,&lt;span&gt; 如果未添加 white-space: pre;,则将连续空白合并为一个。 tmp.getBoundingClientRect().widthtmp.scrollWidth 好,因为它有时会返回 0 @lisak 谢谢,我调整了答案,但这里已经有更好的答案了。 更好?我不会这么说的。标记的答案缺乏精确性,其他人(+ here 1 和 here 2)使用 jQuery——我不是因为 React。 Canvas 无法为您提供文字高度 AFAIK。想法:空格问题也可以通过以下方式解决:.replace(/ /g, "&amp;nbsp;")【参考方案4】:

这是一个不需要等宽字体的解决方案,只有一小段javascript代码不需要计算计算样式 ,甚至支持IME支持RTL文本

// copy the text from input to the span
    $(function () 
      $('.input').on('input', function ()  $('.text').text($('.input').val()); );
    );
    * 
      box-sizing: border-box;
    
    
    .container 
      display: inline-block;
      position: relative;
    
    
    .input,
    .text 
      margin: 0;
      padding: 2px 10px;
      font-size: 24px;
      line-height: 32px;
      border: 1px solid #ccc;
      box-radius: 3px;
      height: 36px;
      font: 20px/20px sans-serif;
      /* font: they should use same font; */
    

    .text 
      padding-right: 20px;
      display: inline-block;
      visibility: hidden;
      white-space: pre;
    
    
    .input 
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      width: 100%;
    
    
<script src="https://code.jquery.com/jquery-3.2.0.min.js"></script>

<div class="container">
  <span class="text">
    some text
  </span>
  <input class="input" value="some text" />
</div>

使用span.text 来适应文本的宽度,并通过position: absolute 让输入与容器具有相同的大小。每次更改时将输入值复制到span(您可以轻松地将这段代码更改为vanilla JS,或使用前端框架提供的功能)。所以输入将恰好适合其内容的大小。

【讨论】:

【参考方案5】:

这是对 Lyth 答案的修改,考虑到:

删除 初始化 占位符

它还允许输入任意数量的字段!要查看它的实际效果:http://jsfiddle.net/4Qsa8/

脚本:

$(document).ready(function () 
    var $inputs = $('.resizing-input');

    // Resize based on text if text.length > 0
    // Otherwise resize based on the placeholder
    function resizeForText(text) 
        var $this = $(this);
        if (!text.trim()) 
            text = $this.attr('placeholder').trim();
        
        var $span = $this.parent().find('span');
        $span.text(text);
        var $inputSize = $span.width();
        $this.css("width", $inputSize);
    

    $inputs.find('input').keypress(function (e) 
        if (e.which && e.charCode) 
            var c = String.fromCharCode(e.keyCode | e.charCode);
            var $this = $(this);
            resizeForText.call($this, $this.val() + c);
        
    );

    // Backspace event only fires for keyup
    $inputs.find('input').keyup(function (e)  
        if (e.keyCode === 8 || e.keyCode === 46) 
            resizeForText.call($(this), $(this).val());
        
    );

    $inputs.find('input').each(function () 
        var $this = $(this);
        resizeForText.call($this, $this.val())
    );
);

风格:

.resizing-input input, .resizing-input span 
    font-size: 12px;
    font-family: Sans-serif;
    white-space: pre;
    padding: 5px;

HTML:

<div class="resizing-input">
    <input type="text" placeholder="placeholder"/>
    <span  style="display:none"></span>
</div>

$(document).ready(function() 
  var $inputs = $('.resizing-input');

  // Resize based on text if text.length > 0
  // Otherwise resize based on the placeholder
  function resizeForText(text) 
    var $this = $(this);
    if (!text.trim()) 
      text = $this.attr('placeholder').trim();
    
    var $span = $this.parent().find('span');
    $span.text(text);
    var $inputSize = $span.width();
    $this.css("width", $inputSize);
  

  $inputs.find('input').keypress(function(e) 
    if (e.which && e.charCode) 
      var c = String.fromCharCode(e.keyCode | e.charCode);
      var $this = $(this);
      resizeForText.call($this, $this.val() + c);
    
  );

  // Backspace event only fires for keyup
  $inputs.find('input').keyup(function(e) 
    if (e.keyCode === 8 || e.keyCode === 46) 
      resizeForText.call($(this), $(this).val());
    
  );

  $inputs.find('input').each(function() 
    var $this = $(this);
    resizeForText.call($this, $this.val())
  );
);
.resizing-input input,
.resizing-input span 
  font-size: 12px;
  font-family: Sans-serif;
  white-space: pre;
  padding: 5px;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div class="resizing-input">
  First:
  <input type="text" placeholder="placeholder" />
  <span style="display:none"></span>
</div>
<br>

【讨论】:

嗨@迈克尔。您的代码效果很好,但我有一个问题。我的一个领域是 Google place autocmplete 字段。当我从下拉菜单中选择正确的地址时,输入字段的宽度不会根据所选地址的长度而改变。有没有简单的解决方法? @Maxence 监听 changeinput 事件就足够了 我对 span 的 display:none 样式有疑问,因为它将 span 注册为 0 宽度。最好使用具有可见性的绝对定位:对于跨度隐藏。 嗨@yarwest,感谢您的提示。您是否知道如何使用此设置调整原始脚本? (我对 Js/jquery 的了解非常有限)【参考方案6】:

这是一个特定于 Angular 的答案,但这对我有用,并且在其简单性和易用性方面非常令人满意:

<input [style.width.ch]="value.length" [(ngModel)]="value" />

它通过Jani's answer中的字符单元自动更新。

【讨论】:

这个。是。史诗。 说真的。神奇。 对于那些沉迷于框架以至于忘记原生代码实际上更简单的人来说&lt;input oninput="this.style.width=this.value.length+'ch'"&gt;【参考方案7】:

为了更好的外观和感觉

您应该结合使用 jQuery keypress() 事件和 String.fromCharCode(e.which) 来获取按下的字符。因此,您可以计算出您的宽度将是多少。为什么?因为它看起来会更性感:)

这是一个 jsfiddle,与使用 keyup 事件的解决方案相比,它产生了一个很好的行为:http://jsfiddle.net/G4FKW/3/

下面是一个普通的 JS,它监听 &lt;input&gt; 元素的 input 事件并将 span 兄弟设置为具有相同的文本值以对其进行测量。

document.querySelector('input').addEventListener('input', onInput)

function onInput()
    var spanElm = this.nextElementSibling;
    spanElm.textContent = this.value; // the hidden span takes the value of the input; 
    this.style.width = spanElm.offsetWidth + 'px'; // apply width of the span to the input
;
/* it's important the input and its span have same styling */
input, .measure 
    padding: 5px;
    font-size: 2.3rem;
    font-family: Sans-serif;
    white-space: pre; /* white-spaces will work effectively */


.measure  
  position: absolute;
  left: -9999px;
  top: -9999px;
<input type="text" />
<span class='measure'></span>

【讨论】:

看起来不错,但没有考虑 Backspace 和 Delete。 是的,为此您需要 keydown 事件。您可以通过这样做添加退格和删除的特定处理(e.which === 46 用于删除,e.which === 8 用于退格)。但是您仍然需要 keypress 事件才能访问 e.charCode 其余部分。 如果你不支持 IE8 你可以使用 oninput 事件而不是检查 e.which:developer.mozilla.org/en-US/docs/Web/Events/input 我已经编辑了您的答案以消除 jQuery 并仅使用 vanilla JS。请注意,此解决方案远非最佳,因为您需要一个不涉及手动编码 span 和 css 的通用解决方案。【参考方案8】:

这是使用 DIV 和“contenteditable”属性解决此问题的另一种方法:

HTML:

<div contenteditable = "true" class = "fluidInput" data-placeholder = ""></div>

CSS:(为 DIV 提供一些尺寸并使其更易于查看)

.fluidInput 

    display         : inline-block;
    vertical-align  : top;

    min-width       : 1em;
    height          : 1.5em;

    font-family     : Arial, Helvetica, sans-serif;
    font-size       : 0.8em;
    line-height     : 1.5em;

    padding         : 0px 2px 0px 2px;
    border          : 1px solid #aaa;
    cursor          : text;



.fluidInput * 

    display         : inline;




.fluidInput br  

    display         : none;




.fluidInput:empty:before 

    content         : attr(data-placeholder);
    color           : #ccc;


注意:如果您打算在您计划提交的 FORM 元素中使用它,则需要使用 Javascript / jQuery 来捕获提交事件,以便您可以解析“值”(.innerHTML.html())的DIV。

【讨论】:

这值得更多的支持。它优雅而简单(只要使用 JS 进行表单验证对您来说不是问题)。 但这不是输入!【参考方案9】:

此答案提供了检索浏览器中可用的文本宽度的最准确方法之一,并且比公认的答案更准确。它使用 canvas html5 元素,与其他答案不同,它不会将元素添加到 DOM 中,因此避免了由于向 DOM 中过度添加元素而导致的任何重排问题。

详细了解与文本宽度相关的 Canvas 元素 here。

注意:根据MDN,getPropertyValue() 方法的简写版本(例如字体)可能不可靠。我建议单独获取这些值以提高兼容性。我在这里只是为了速度。

/**
 * returns the width of child text of any DOM node as a float
 */
function getTextWidth(el) 
  // uses a cached canvas if available
  var canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas"));
  var context = canvas.getContext("2d");
  // get the full font style property
  var font = window.getComputedStyle(el, null).getPropertyValue('font');
  var text = el.value;
  // set the font attr for the canvas text
  context.font = font;
  var textMeasurement = context.measureText(text);
  return textMeasurement.width;


var input = document.getElementById('myInput');
// listen for any input on the input field
input.addEventListener('input', function(e) 
  var width = Math.floor(getTextWidth(e.target));
  // add 10 px to pad the input.
  var widthInPx = (width + 10) + "px";
  e.target.style.width = widthInPx;
, false);
#myInput 
  font: normal normal 400 normal 18px / normal Roboto, sans-serif;
  min-width: 40px;
&lt;input id="myInput" /&gt;

【讨论】:

到目前为止的最佳答案。高效且准确。唯一的问题是您可能需要为计算出的宽度添加一个偏移量 喜欢这个答案,绝对是迄今为止最好的!这是一个小提琴,添加一点jQuery来改进它......jsfiddle.net/designosis/ran0vduj【参考方案10】:

只是在其他答案之上添加。

我注意到现在在某些浏览器中,输入字段具有滚动宽度。这意味着:

this.style.width = this.scrollWidth + 'px';

应该很好用。在 chrome、firefox 和 safari 中测试。

对于删除支持,您可以先添加“=0”,然后重新调整。

this.style.width = 0; this.style.width = this.scrollWidth + 'px';

【讨论】:

这很好用,谢谢!我不知道为什么这个答案没有更多的赞成票。这是迄今为止最简单、不那么做作的 (js) 解决方案。 如何将resize命令应用于页面的初始加载?我试过 onload="..." 但这没有用【参考方案11】:

您也可以使用 size 属性设置输入的宽度。输入的大小决定了它的字符宽度。

一个输入可以通过监听关键事件来动态调整它的大小。

例如

$("input[type='text']").bind('keyup', function () 
    $(this).attr("size", $(this).val().length );
);

JsFiddle here

【讨论】:

【参考方案12】:

你可以做类似this

// HTML
<input id="input" type="text" style="width:3px" />
// jQuery
$(function()
  $('#input').keyup(function()
    $('<span id="width">').append( $(this).val() ).appendTo('body');
    $(this).width( $('#width').width() + 2 );
    $('#width').remove();
  );
);

【讨论】:

如果你增加 keyup 的大小,它会导致丑陋的行为。输入需要在角色进入之前增加其大小以获得更多舒适度。【参考方案13】:

你可以设置size属性。 如果您使用的是反应式框架之一,则以下内容就足够了:

<input size=" yourValue.length " [value]="yourValue" />

但如果你使用的是纯 js,你应该设置事件处理程序,比如:

<input oninput="this.setAttribute('size', this.value.length)" />

【讨论】:

【参考方案14】:

值得注意的是,当字体为等宽字体时可以进行漂亮的调整大小,因此我们可以使用ch 单元完美地调整input 元素的大小。

同样在这种方法中,我们可以通过在 input 事件上更新 CSS 变量自定义属性)来更新字段的宽度,我们也应该注意DOMContentLoaded 事件上已经预填充的输入

Codepen demo


标记

<input type="text" value="space mono font" class="selfadapt" />

CSS

:root  --size: 0; 

.selfadapt 
   padding: 5px;
   min-width: 10ch;
   font-family: "space mono";
   font-size: 1.5rem;
   width: calc(var(--size) * 1ch);

作为根变量,我们设置--size: 0:该变量将包含输入的长度,并将在calc() 表达式中乘以1ch。默认情况下,我们还可以设置最小宽度,例如10ch

Javascript部分读取插入值的长度并更新变量--size

JS

let input = document.querySelector('.selfadapt');
let root  = document.documentElement.style;

/* on input event auto resize the field */
input.addEventListener('input', function() 
   root.setProperty('--size', this.value.length );
);

/* resize the field if it is pre-populated */
document.addEventListener("DOMContentLoaded", function() 
   root.setProperty('--size', input.value.length);
);

当然,即使您不使用等宽字体,这仍然有效,但在这种情况下,您需要通过将 --size 变量乘以另一个值来更改 calc() 公式(它严格依赖于 @ 987654336@ 和 font-size) 与 1ch 不同。

【讨论】:

【参考方案15】:

这是我编写的一个普通的 JS 和一个 jQuery 插件,它将使用画布和字体大小/系列来处理调整输入元素的大小,以确定渲染时的实际字符串长度。 (仅适用于 > IE9、chrome、safari、firefox、opera 和大多数其他已实现 canvas 元素的主要浏览器)。

PlainJS:

function autoSize(input, o) 
    o || (o = );
    o.on || (o.on = 'keyup');

    var canvas = document.createElement('canvas');
    canvas.setAttribute('style', 'position: absolute; left: -9999px');
    document.body.appendChild(canvas);

    var ctx = canvas.getContext('2d');

    input.addEventListener(o.on, function () 
        ctx.font = getComputedStyle(this,null).getPropertyValue('font');
        this.style.width = ctx.measureText(this.value + '  ').width + 'px';
    );


//Usage
autoSize(document.getElementById('my-input'));

jQuery 插件:

$.fn.autoSize = function(o) 
  o = $.extend(, 
    on: 'keyup'
  , o);

  var $canvas = $('<canvas/>').css(position: 'absolute', left: -9999);
  $('body').append($canvas);

  var ctx = $canvas[0].getContext('2d');

  return this.on(o.on, function()
    var $this = $(this);
    ctx.font = $this.css('font');
    $this.width(ctx.measureText($this.val()).width + 'px');
  )


//Usage:
$('#my-input').autoSize();

注意:这不会处理文本转换、行间距和字母间距,以及可能的其他一些文本大小更改属性。处理文本转换属性集并调整文本值以匹配该属性。其他人可能相当直截了当。如果这开始获得一些牵引力,我将实施......

【讨论】:

【参考方案16】:

很简单:

oninput='this.style.width = (this.scrollWidth - N) + "px";'

其中 N 是通过实验确定的某个数字(示例中为 2,我正在开发的东西为 17)。

减去 N 可以防止这个奇怪的多余空间在文本到达文本框末尾之前很久就累积。

比较。仔细注意即使在第一个字符之后大小如何变化。

<p>Subtracting N:</p>    
<input type="text" placeholder="enter lots of text here" oninput='this.style.width = (this.scrollWidth-2) + "px";'>

<p>Not Subtracting N:</p>    
<input type="text" placeholder="enter lots of text here" oninput='this.style.width = (this.scrollWidth) + "px";'>

【讨论】:

我没有对此进行广泛的测试,但您可以将oninput='this.style.width = (this.scrollWidth-2) + "px";' 更改为oninput='this.style.width = 0; this.style.width = this.scrollWidth + "px";' 以消除空间累积【参考方案17】:

您可以使用内置的ng-style 指令在 angularjs 中更简单地进行操作。

在您的 html 中:

  <input ng-style="inputStyle(testdata)" ng-model="testdata" />

在您的控制器中:

 $scope.testdata = "whatever";

 $scope.inputStyle = function(str) 
    var charWidth = 7;
    return  "width": (str.length +1) * charWidth + "px" ;
    ;

在你的 CSS 中:

input  font-family:monospace; font-size:12px; 

调整 charWidth 以匹配字体的宽度。它似乎是 7,字体大小为 12px;

【讨论】:

这很酷而且很容易知道,但是将 angularjs 添加到应用程序以动态调整输入元素的大小确实是严重的过度杀伤力,尤其是当 OP 要求“HTML、JavaScript、PHP 或 CSS”解决方案时。有人可能会争辩说 jQuery 在这方面也太过分了,但是 - 与 Angular 不同 - 作为一个 DOM 操作工具包是 jQuery 目的的核心。 我应该如何知道正在输入的字符的宽度?很难假设它是单一大小的字体。 你不能要求等宽字体,也不需要 Angular。 brendan's answer 基本相同。【参考方案18】:

如果你使用 Bootstrap,它可以很容易地完成:

&lt;div contenteditable="true" class="form-control" style="display: inline"&gt;&lt;/div&gt;

您只需要在提交表单之前获取 div 的内容并将其放入隐藏的输入中。

【讨论】:

请注意,此解决方案可能存在复制/粘贴内容的问题,尤其是在粘贴的内容包含 html 时。并且在 IE 中可能无法解析【参考方案19】:

这是我的 2 美分。 创建一个空的不可见 div。用输入内容填充它并将宽度返回到输入字段。匹配每个框之间的文本样式。

$(".answers_number").keyup(function()
    $( "#number_box" ).html( $( this ).val() );
    $( this ).animate(
        width: $( "#number_box" ).width()+20
        , 300, function() 
    );
);
#number_box 
   position: absolute;
   visibility: hidden;
   height: auto;
   width: auto;
   white-space: nowrap;
   padding:0 4px;
   /*Your font styles to match input*/
   font-family:Arial;
   font-size: 30px; 

    
.answers_number 
   font-size: 30px; 
   font-family:Arial;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="number" class="answers_number" />
<div id="number_box">
</div>

【讨论】:

【参考方案20】:

虽然这篇文章已经很老了,但我想添加一个更简单的解决方案,但不知道为什么只提供了如此庞大和/或复杂的解决方案。

这是一个获取所需内容的简单函数:

function resizeInput() 
    const input = document.getElementById('myInput');
    input.style.width = `$input.scrollWidthpx`;
;

【讨论】:

谢谢。但这仅适用于输入文本,不适用于删除文本。【参考方案21】:

最好的解决方案是

【讨论】:

这应该是公认的答案。简单而优雅。谢谢。【参考方案22】:

我认为您误解了min-width CSS property。 min-width 通常用于定义流体布局中的最小 DOM 宽度,例如:

input 
  width: 30%;
  min-width: 200px;

这会将输入元素的最小宽度设置为 200 像素。在这种情况下,“px”代表“像素”。

现在,如果您要检查以确保在用户提交时输入字段至少包含一个字符,您需要使用 JavaScript 和 PHP 进行一些表单验证。如果这确实是你想要做的,我会编辑这个答案并尽我所能帮助你。

【讨论】:

我知道 px 是什么意思,我知道 javascript 有一个最小宽度的功能,但它不适用于输入文本。 @Kerc:“javascript 有一个最小宽度函数”——哪一个?你的意思是? – “它不起作用”从来都不是对问题的良好描述。尝试详细说明预期的行为。 你有没有试过我的例子,而不是你看到它不是 1 像素,你的也不是。无论我用 html、css 编写,这都行不通 也许有一个php函数,有人知道吗? 我确实尝试了您的示例,但我认为 1 pixel 宽的输入字段不是您想要的。如果是,请尝试&lt;input type="text" value="1" style="width:1px;" /&gt;【参考方案23】:

我真的很喜欢Lyth's answer,但也很想这样做:

    处理退格和删除 不需要您手动添加相邻标签。 强制设置最小宽度。 自动应用于具有特定类的元素

我改编了他的 JSFiddle 并提出了this。此小提琴中不存在的一项改进是使用jQuery CSS Parser 之类的东西从 input.textbox-autosize 规则中实际读取初始宽度,并将其用作 minWidth。是的,我只是在 上使用一个属性,这使得演示很紧凑,但并不理想。因为它需要每个输入的额外属性。您可能还只想在 JavaScript 中将 minWidth 设置为 100。

HTML:

<div id='applicationHost'>
<div>Name:   <input class='textbox-autosize' data-min-width='100' type="text" /></div>
<div>Email:  <input class='textbox-autosize' data-min-width='100' type="email" /></div>
<div>Points: <input class='textbox-autosize' data-min-width='100' type="number" /></div>
</div>

CSS:

#applicationHost 
    font-family: courier;
    white-space: pre;


input.textbox-autosize, span.invisible-autosize-helper 
    padding:0;
    font-size:12px;
    font-family:Sans-serif; 
    white-space:pre;

input.textbox-autosize 
    width: 100px; /* Initial width of textboxes */


/*
In order for the measurements to work out, your input and the invisible
span need to have the same styling.
*/

JavaScript:

$('#applicationHost').on('keyup', '.textbox-autosize', function(e) 
    // Add an arbitary buffer of 15 pixels.
    var whitespaceBuffer = 15;
    var je = $(this);
    var minWidth = parseInt(je.attr('data-min-width'));
    var newVal = je.val();
    var sizingSpanClass = 'invisible-autosize-helper';
    var $span = je.siblings('span.' + sizingSpanClass).first();
    // If this element hasn't been created yet, we'll create it now.
    if ($span.length === 0) 
        $span = $('<span/>', 
            'class': sizingSpanClass,
            'style': 'display: none;'
        );
        je.parent().append($span);
    
    $span = je.siblings('span').first();
    $span.text(newVal) ; // the hidden span takes 
    // the value of the input
    $inputSize = $span.width();
    $inputSize += whitespaceBuffer;
    if($inputSize > minWidth)
        je.css("width", $inputSize) ; // apply width of the span to the input
    else
        je.css("width", minWidth) ; // Ensure we're at the min width
);

【讨论】:

【参考方案24】:

更好的是onvalue:

<input id="txt" type="text" onvalue="this.style.width = ((this.value.length + 1) * 8) + 'px';">

还涉及到粘贴、拖拽等操作

【讨论】:

【参考方案25】:

精简版:

<input type="text" style="width: tag.lengthch" bind:value=tag />

【讨论】:

【参考方案26】:

我只是花一些时间弄清楚如何去做。 实际上,我发现的最简单的方法是将输入值移动到输入之前的范围,保持输入 1 符号宽度。虽然我不能确定它是否适合您的初始需求。 也许是一些额外的代码,但在基于 react+flux 的应用程序中,这是非常自然的解决方案。

【讨论】:

【参考方案27】:

根据 Michael 的回答,我使用 jQuery 创建了自己的版本。我认为这是这里大多数答案的更简洁/更短的版本,并且似乎可以完成工作。

我和这里的大多数人都在做同样的事情,通过使用跨度将输入文本写入然后获取宽度。然后我在调用keyupblur 时设置宽度。

这是一个有效的codepen。此 codepen 展示了如何将其与多个输入字段一起使用。

HTML 结构:

<input type="text" class="plain-field" placeholder="Full Name">
<span style="display: none;"></span>

jQuery:

function resizeInputs($text) 
    var text = $text.val().replace(/\s+/g, ' '),
        placeholder = $text.attr('placeholder'),
        span = $text.next('span');
        span.text(placeholder);
    var width = span.width();

    if(text !== '') 
        span.text(text);
    var width = span.width();
    

    $text.css('width', width + 5);
;

上面的函数获取输入值,修剪多余的空格并将文本设置为 span 以获取宽度。如果没有文本,它将获取占位符并将其输入到跨度中。一旦它将文本输入到跨度中,它就会设置输入的宽度。宽度上的+ 5 是因为没有它,Edge 浏览器中的输入会被截断一点。

$('.plain-field').each(function() 
    var $text = $(this);
    resizeInputs($text);
);

$('.plain-field').on('keyup blur', function() 
    var $text = $(this);
    resizeInputs($text);
);

$('.plain-field').on('blur', function() 
    var $text = $(this).val().replace(/\s+/g, ' ');
    $(this).val($text);
);

如果可以改进,请告诉我,因为这是我能想到的最干净的解决方案。

【讨论】:

【参考方案28】:

防弹的通用方法必须:

    考虑到被测量input元素的所有可能的样式 无需修改HTML或即可对任何输入应用测量

Codepen demo

var getInputValueWidth = (function()
  // https://***.com/a/49982135/104380
  function copyNodeStyle(sourceNode, targetNode) 
    var computedStyle = window.getComputedStyle(sourceNode);
    Array.from(computedStyle).forEach(key => targetNode.style.setProperty(key, computedStyle.getPropertyValue(key), computedStyle.getPropertyPriority(key)))
  
  
  function createInputMeassureElm( inputelm )
    // create a dummy input element for measurements
    var meassureElm = document.createElement('span');
    // copy the read input's styles to the dummy input
    copyNodeStyle(inputelm, meassureElm);
    
    // set hard-coded styles needed for propper meassuring 
    meassureElm.style.width = 'auto';
    meassureElm.style.position = 'absolute';
    meassureElm.style.left = '-9999px';
    meassureElm.style.top = '-9999px';
    meassureElm.style.whiteSpace = 'pre';
    
    meassureElm.textContent = inputelm.value || '';
    
    // add the meassure element to the body
    document.body.appendChild(meassureElm);
    
    return meassureElm;
  
  
  return function()
    return createInputMeassureElm(this).offsetWidth;
  
)();


// delegated event binding
document.body.addEventListener('input', onInputDelegate)

function onInputDelegate(e)
  if( e.target.classList.contains('autoSize') )
    e.target.style.width = getInputValueWidth.call(e.target) + 'px';
input 
  font-size:1.3em; 
  padding:5px; 
  margin-bottom: 1em;


input.type2
  font-size: 2.5em;
  letter-spacing: 4px;
  font-style: italic;
<input class='autoSize' value="type something">
<br>
<input class='autoSize type2' value="here too">

【讨论】:

【参考方案29】:

您想随着文本的变化而改变尺寸属性。

# react

const resizeInput = (e) => 
  e.target.setAttribute('size', e.target.value.length || 1);


<input 
  onChange=resizeInput
  size=(propertyInput.current && propertyInput.current.value.length) || 1
  ref=propertyInput 
/>

  

【讨论】:

【参考方案30】:

这是我的 React 解决方案,它适用于任何字体大小,只要确保您有等宽字体(等宽字体的所有字体字符宽度都相同),就像我在我的解决方案中一样,它会完美运行。

JS:

const [value, setValue] = useState(0)

HTML:

<input value=value onChange=(e) => setValue(e.target.value) style=width: `$value.toString().length`ch/>

CSS:

@import url("https://fonts.googleapis.com/css2?family=B612+Mono&display=swap");    
input
    font-family: "B612 Mono", monospace;

【讨论】:

以上是关于将输入字段的宽度调整为其输入的主要内容,如果未能解决你的问题,请参考以下文章

如何将 html 列宽固定为其内容的最大宽度?

Bootstrap 4 - 调整输入字段的宽度

x-editable - 调整输入字段的宽度

ExtJs 4 - 调整窗口大小时未保持 TextField 高度

JCrop 将选择的大小调整为错误的值

如何在键入时使 UITextField 宽度调整为文本?