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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3392493/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 04:26:17  来源:igfitidea点击:

Adjust width of input field to its input

javascripthtmlcss

提问by Kerc

<html>
  <head>
  </head>
  <body>
    <input type="text" value="1" style="min-width:1px;" />
  </body>
</html>

This is my code and it is not working. Is there any other way in HTML, JavaScript, PHP or CSS to set minimum width?

这是我的代码,它不起作用。在 HTML、JavaScript、PHP 或 CSS 中还有其他方法可以设置最小宽度吗?

I want a text input field with a dynamically changing width, so that the input field fluids around its contents. Every input has a built-in padding of 2em, that is the problem and second problem is that min-widthain't working on input at all.

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

If I set width more than it is needed than the whole program is messy, I need the width of 1px, more only if it's needed.

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

采纳答案by Tahbaza

It sounds like your expectation is that the style be applied dynamically to the width of the textbox based on the contents of the textbox. If so you will need some js to run on textbox contents changing, something like this:

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

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

Note: this solution only works when every character is exactly 8pxwide.

注意:此解决方案仅适用于每个字符都正好为8px宽的情况。

回答by Jani Jalkala

In modern browser versions, CSS unit chis also available. To my understanding, it is font-independent unit, where 1chequals to width of character 0(zero) in any given font.

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

Thus, something as simple as following could be used as resize function:

因此,可以使用如下简单的东西作为调整大小函数:

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; }
<input>

That example would resize "elem" to length of the value + 2 characters extra.

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

回答by Marcel Korpel

To calculate the width of the current input, you'll have to embed it in a temporary spanelement, attach that thing to the DOM, get the computed width (in pixels) using the scrollWidthproperty and remove the spanagain. Of course you'll have to ensure that the same font family, font size, etc., is used in the inputas well as in the spanelement. Therefore I assigned the same class to them.

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

I attached the function to the keyupevent, as on keypressthe input character is not yet added to the input value, so that will result in the wrong width. Unfortunately, I don't know how to get rid of the scrolling of the input field (when adding characters to the end of the field); it scrolls, because the character is added and shown before adjustWidthOfInput()is called. And, as said, I can't do this the other way round because then you'll have the value of the input field beforethe pressed character is inserted. I'll try to solve this issue later.

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

BTW, I only tested this in Firefox (3.6.8), but you'll get the point, I hope.

顺便说一句,我只在 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>

回答by Michael

Here's a modification of Lyth's answer that takes into account:

这是对 Lyth 回答的修改,其中考虑到了:

  • Deletion
  • Initialisation
  • Placeholders
  • 删除
  • 初始化
  • 占位符

It also allows for any number of input fields! To see it in action: http://jsfiddle.net/4Qsa8/

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

Script:

脚本:

$(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())
    });
});

Style:

风格:

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

HTML:

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>

回答by tsh

Here is a solution without monospaced fontneeded, with only very small piece code of javascript, do not need calculate computed styles, and, even support ime, support rtl texts.

这里是一个解决方案,而不等宽字体需要,用JavaScript只有很小的一块代码不需要计算计算样式,并且,即使是支持输入法支持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>

Use the span.textto fit width of text, and let the input have same size with it by position: absoluteto the container. Copy value of input to the spanevery time it changed (you may change this piece of code to vanilla js easily). So the input will just "fit" the size of its content.

使用span.text以适应文本的宽度,并让输入与position: absolute容器具有相同的大小。span每次更改时将input 的值复制到它(您可以轻松地将这段代码更改为 vanilla js)。所以输入只会“适合”其内容的大小。

回答by Lyth

FOR A NICER LOOK&FEEL

为了更好的外观和感觉

You should use jQuery keypress() event in combination with String.fromCharCode(e.which) to get the pressed character. Hence you can calculate what your width will be. Why? Because it will look a lot more sexy :)

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

Here is a jsfiddle that results in a nice behaviour compared to solutions using the keyup event : http://jsfiddle.net/G4FKW/3/

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

Below is a vanilla JS which listens to the inputevent of an <input>element and sets a spansibling to have the same text value in order to measure it.

下面是一个 vanilla JS,它侦听元素的input事件<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>

回答by Chris Vandevelde

This is an Angular-specific answer, but this worked for me and has been very satisfying in terms of its simplicity and ease-of-use:

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

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

It automatically updates via the character units in Jani's answer.

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

回答by logic8

Here is an alternative way to solve this using a DIV and the 'contenteditable' property:

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

HTML:

HTML:

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

CSS: (to give the DIV some dimensions and make it easier to see)

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;

}

Note: If you are planning on using this inside of a FORM element that you plan to submit, you will need to use Javascript / jQuery to catch the submit event so that you can parse the 'value' ( .innerHTMLor .html()respectively) of the DIV.

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

回答by brendan

You can set an input's width using the sizeattribute as well. The size of an input determines it's width in characters.

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

An input could dynamically adjust it's size by listening for key events.

输入可以通过侦听关键事件来动态调整其大小。

For example

例如

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

JsFiddle here

JsFiddle在这里

回答by Ties

You could do something like 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();
  });
});

?

?

?

?