jQuery 将输入 [type=text] 自动缩放到值的宽度?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8100770/
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-27 10:01:11  来源:igfitidea点击:

Auto-scaling input[type=text] to width of value?

jqueryhtmlcss

提问by Walker

Is there a way to scale the width of an <input type="text">to the width of the actual value?

有没有办法将 an<input type="text">的宽度缩放到实际值的宽度?

input {
  display: block;
  margin: 20px;
  width: auto;
}
<input type="text" value="I've had enough of these damn snakes, on this damn plane!" />

<input type="text" value="me too" />

回答by nrabinowitz

You can do this the easy way by setting the sizeattribute to the length of the input contents:

您可以通过将size属性设置为输入内容的长度来轻松完成此操作:

function resizeInput() {
    $(this).attr('size', $(this).val().length);
}

$('input[type="text"]')
    // event handler
    .keyup(resizeInput)
    // resize on page load
    .each(resizeInput);

See: http://jsfiddle.net/nrabinowitz/NvynC/

见:http: //jsfiddle.net/nrabinowitz/NvynC/

This seems to add some padding on the right that I suspect is browser dependent. If you wanted it to be really tight to the input, you could use a technique like the one I describe in this related answer, using jQuery to calculate the pixel size of your text.

这似乎在右侧添加了一些我怀疑与浏览器相关的填充。如果您希望它对输入非常严格,您可以使用我在此相关答案中描述的技术,使用 jQuery 计算文本的像素大小。

回答by DreamTeK

A SIMPLE BUT PIXEL PERFECT SOLUTION

一个简单但像素完美的解决方案

I have seen several ways to do this but calculating the width of fonts isn't always 100% accurate, it's just an estimate.

我已经看到了几种方法来做到这一点,但计算字体的宽度并不总是 100% 准确,这只是一个估计。

I managed to create a pixel perfect way of adjusting the input width by having a hidden placeholder to measure from.

我设法通过使用隐藏的占位符进行测量来创建一种像素完美的方式来调整输入宽度。



jQuery(Recommended)

jQuery (推荐)

$(function(){
  $('#hide').text($('#txt').val());
  $('#txt').width($('#hide').width());
}).on('input', function () {
  $('#hide').text($('#txt').val());
  $('#txt').width($('#hide').width());
});
body,
#txt,
#hide{
  font:inherit;
  margin:0;
  padding:0;
}
#txt{
  border:none;
  color:#888;
  min-width:10px;
}
#hide{
  display:none;
  white-space:pre;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<p>Lorem ipsum 
  <span id="hide"></span><input id="txt" type="text" value="type here ...">
  egestas arcu.
</p>



Pure JavaScript

纯 JavaScript

I was unable to determine how jQuery calculates the width of hidden elements so a slight tweak to css was required to accomodate this solution.

我无法确定 jQuery 如何计算隐藏元素的宽度,因此需要对 css 稍作调整以适应此解决方案。

var hide = document.getElementById('hide');
var txt = document.getElementById('txt');
resize();
txt.addEventListener("input", resize);

function resize() {
  hide.textContent = txt.value;
  txt.style.width = hide.offsetWidth + "px";
}
body,
#txt,
#hide {
  font: inherit;
  margin: 0;
  padding: 0;
}

#txt {
  border: none;
  color: #888;
  min-width: 10px;
}

#hide {
  position: absolute;
  height: 0;
  overflow: hidden;
  white-space: pre;
}
<p>Lorem ipsum
  <span id="hide"></span><input id="txt" type="text" value="type here ..."> egestas arcu.
</p>

回答by mb21

If for some reason the other solutions don't work for you, you could use a contenteditable-span instead of an input element.

如果由于某种原因其他解决方案对您不起作用,您可以使用 contenteditable-span 而不是 input 元素。

<span contenteditable="true">dummy text</span>

Note that this is more of a hack and has the severe drawback of allowing totally unsanitized HTML input like letting users enter (and paste) linebreaks, links and other HTML.

请注意,这更像是一种黑客行为,并且具有允许完全未经处理的 HTML 输入的严重缺点,例如让用户输入(和粘贴)换行符、链接和其他 HTML。

So you probably shouldn't use this solutionunless you're very carefully sanitising the input...

所以你可能不应该使用这个解决方案,除非你非常仔细地清理输入......

Update: you probably want to use DreamTeK's solution below.

更新:您可能想使用下面的DreamTeK解决方案

回答by Marc Guiselin

Edit: The plugin now works with trailing whitespace characters. Thanks for pointing it out @JavaSpyder

编辑:该插件现在适用于尾随空格字符。感谢您指出@JavaSpyder

Since most other answers didn't match what I needed(or simply didn't work at all) I modified Adrian B's answer into a proper jQuery plugin that results in pixel perfect scaling of input without requiring you to change your css or html.

由于大多数其他答案与我需要的不匹配(或者根本不起作用),我将 Adrian B 的答案修改为一个合适的 jQuery 插件,该插件可以对输入进行像素完美缩放,而无需您更改 css 或 html。

Example:https://jsfiddle.net/587aapc2/

示例:https: //jsfiddle.net/587aapc2/

Usage:$("input").autoresize({padding: 20, minWidth: 20, maxWidth: 300});

用法:$("input").autoresize({padding: 20, minWidth: 20, maxWidth: 300});

Plugin:

插入:

//JQuery plugin:
$.fn.textWidth = function(_text, _font){//get width of text with font.  usage: $("div").textWidth();
        var fakeEl = $('<span>').hide().appendTo(document.body).text(_text || this.val() || this.text()).css({font: _font || this.css('font'), whiteSpace: "pre"}),
            width = fakeEl.width();
        fakeEl.remove();
        return width;
    };

$.fn.autoresize = function(options){//resizes elements based on content size.  usage: $('input').autoresize({padding:10,minWidth:0,maxWidth:100});
  options = $.extend({padding:10,minWidth:0,maxWidth:10000}, options||{});
  $(this).on('input', function() {
    $(this).css('width', Math.min(options.maxWidth,Math.max(options.minWidth,$(this).textWidth() + options.padding)));
  }).trigger('input');
  return this;
}



//have <input> resize automatically
$("input").autoresize({padding:20,minWidth:40,maxWidth:300});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input value="i magically resize">
<br/><br/>
called with:
$("input").autoresize({padding: 20, minWidth: 40, maxWidth: 300});

回答by MartinF

I have a jQuery plugin on GitHub: https://github.com/MartinF/jQuery.Autosize.Input

我在 GitHub 上有一个 jQuery 插件:https: //github.com/MartinF/jQuery.Autosize.Input

It mirrors the value of the input, calculates the width and uses it for setting the width of the input.

它镜像输入的值,计算宽度并使用它来设置输入的宽度。

You can see an live example here: http://jsfiddle.net/mJMpw/2175/

你可以在这里看到一个活生生的例子:http: //jsfiddle.net/mJMpw/2175/

Example of how to use it (because some code is needed when posting a jsfiddle link):

如何使用它的示例(因为发布 jsfiddle 链接时需要一些代码):

<input type="text" value="" placeholder="Autosize" data-autosize-input='{ "space": 40 }' />

input[type="data-autosize-input"] {
  width: 90px;
  min-width: 90px;
  max-width: 300px;
  transition: width 0.25s;    
}

You just use css to set min/max-width and use a transition on the width if you want a nice effect.

如果你想要一个好的效果,你只需使用 css 来设置最小/最大宽度并在宽度上使用过渡。

You can specify the space / distance to the end as the value in json notation for the data-autosize-input attribute on the input element.

您可以为 input 元素上的 data-autosize-input 属性指定到末尾的空间/距离作为 json 表示法中的值。

Of course you can also just initialize it using jQuery

当然你也可以使用jQuery初始化它

$("selector").autosizeInput();

回答by danijar

There are already a lot of good answers here. For fun, I implemented this solution below, based on the other answers and my own ideas.

这里已经有很多很好的答案了。为了好玩,我根据其他答案和我自己的想法在下面实现了这个解决方案。

<input class="adjust">

The input element is adjusted pixel accurate and an additional offset can be defined.

输入元素经过像素精确调整,并且可以定义额外的偏移量。

function adjust(elements, offset, min, max) {

    // Initialize parameters
    offset = offset || 0;
    min    = min    || 0;
    max    = max    || Infinity;
    elements.each(function() {
        var element = $(this);

        // Add element to measure pixel length of text
        var id = btoa(Math.floor(Math.random() * Math.pow(2, 64)));
        var tag = $('<span id="' + id + '">' + element.val() + '</span>').css({
            'display': 'none',
            'font-family': element.css('font-family'),
            'font-size': element.css('font-size'),
        }).appendTo('body');

        // Adjust element width on keydown
        function update() {

            // Give browser time to add current letter
            setTimeout(function() {

                // Prevent whitespace from being collapsed
                tag.html(element.val().replace(/ /g, '&nbsp'));

                // Clamp length and prevent text from scrolling
                var size = Math.max(min, Math.min(max, tag.width() + offset));
                if (size < max)
                    element.scrollLeft(0);

                // Apply width to element
                element.width(size);
            }, 0);
        };
        update();
        element.keydown(update);
    });
}

// Apply to our element
adjust($('.adjust'), 10, 100, 500);

The adjustment gets smoothed with a CSS transition.

调整通过 CSS 过渡变得平滑。

.adjust {
    transition: width .15s;
}

Here is the fiddle. I hope this can help others looking for a clean solution.

这是小提琴。我希望这可以帮助其他人寻找一个干净的解决方案。

回答by ハセン

Instead of trying to create a div and measure its width, I think it's more reliable to measure the width directly using a canvas element which is more accurate.

与其尝试创建 div 并测量其宽度,我认为直接使用更准确的 canvas 元素测量宽度更可靠。

function measureTextWidth(txt, font) {
    var element = document.createElement('canvas');
    var context = element.getContext("2d");
    context.font = font;
    return context.measureText(txt).width;
}

Now you can use this to measure what the width of some input element should be at any point in time by doing this:

现在,您可以通过执行以下操作来使用它来测量某个输入元素在任何时间点的宽度应该是多少:

// assuming inputElement is a reference to an input element (DOM, not jQuery)
var style = window.getComputedStyle(inputElement, null);
var text = inputElement.value || inputElement.placeholder;
var width = measureTextWidth(text, style.font);

This returns a number (possibly floating point). If you want to account for padding you can try this:

这将返回一个数字(可能是浮点数)。如果你想考虑填充,你可以试试这个:

  var desiredWidth = (parseInt(style.borderLeftWidth) +
      parseInt(style.paddingLeft) +
      Math.ceil(width) +
      1 + // extra space for cursor
      parseInt(style.paddingRight) +
      parseInt(style.borderRightWidth))
  inputElement.style.width = desiredWidth + "px";

回答by Joseph Nields

Unfortunately the sizeattribute will not work very well. There will be extra space and too little space sometimes, depending on how the font is set up. (check out the example)

不幸的是,该size属性不能很好地工作。有时会有额外的空间和太小的空间,这取决于字体的设置方式。(查看示例)

If you want this to work well, try watching for changes on the input, and resize it then. You probably want to set it to the input's scrollWidth. We would need to account for box sizing, too.

如果您希望它正常工作,请尝试观察输入的更改,然后调整其大小。您可能希望将其设置为输入的scrollWidth. 我们也需要考虑盒子的尺寸。

In the following example, I'm setting the sizeof the input to 1 to prevent it from having a scrollWidththat is greater than our initial width (set manually with CSS).

在下面的示例中,我size将输入的设置为 1 以防止它的scrollWidth宽度大于我们的初始宽度(使用 CSS 手动设置)。

// (no-jquery document.ready)
function onReady(f) {
    "complete" === document.readyState
        ? f() : setTimeout(onReady, 10, f);
}

onReady(function() {
    [].forEach.call(
        document.querySelectorAll("input[type='text'].autoresize"),
        registerInput
    );
});
function registerInput(el) {
    el.size = 1;
    var style = el.currentStyle || window.getComputedStyle(el),
        borderBox = style.boxSizing === "border-box",
        boxSizing = borderBox
            ? parseInt(style.borderRightWidth, 10) +
                parseInt(style.borderLeftWidth, 10)
            : 0;
    if ("onpropertychange" in el) {
         // IE
         el.onpropertychange = adjust;
    } else if ("oninput" in el) {
         el.oninput = adjust;
    }
    adjust();

    function adjust() {

        // reset to smaller size (for if text deleted) 
        el.style.width = "";

        // getting the scrollWidth should trigger a reflow
        // and give you what the width would be in px if 
        // original style, less any box-sizing
        var newWidth = el.scrollWidth + boxSizing;

        // so let's set this to the new width!
        el.style.width = newWidth + "px";
    }
}
* {
  font-family: sans-serif;
}
input.autoresize {
  width: 125px;
  min-width: 125px;
  max-width: 400px;
}
input[type='text'] {
  box-sizing: border-box;
  padding: 4px 8px;
  border-radius: 4px;
  border: 1px solid #ccc;
  margin-bottom: 10px;
}
<label> 
  Resizes:
  <input class="autoresize" placeholder="this will resize" type='text'>
</label>
<br/>
<label>
  Doesn't resize:
<input placeholder="this will not" type='text'>
</label>
<br/>
<label>
  Has extra space to right:
  <input value="123456789" size="9" type="text"/>
</label>

I think this should work in even IE6, but don't take my word for it.

我认为这甚至应该在 IE6 中工作,但不要相信我的话。

Depending on your use case, you may need to bind the adjust function to other events. E.g. changing an input's value programmatically, or changing the element's style's displayproperty from none(where scrollWidth === 0) to blockor inline-block, etc.

根据您的用例,您可能需要将调整函数绑定到其他事件。例如,以编程方式更改输入的值,或将元素的样式display属性从none(where scrollWidth === 0) 更改为blockorinline-block等。

回答by Adrian B

You can solve this problem as here :) http://jsfiddle.net/MqM76/217/

你可以在这里解决这个问题:) http://jsfiddle.net/MqM76/217/

HTML:

HTML:

<input id="inpt" type="text" />
<div id="inpt-width"></div>

JS:

JS:

$.fn.textWidth = function(text, font) {
    if (!$.fn.textWidth.fakeEl) $.fn.textWidth.fakeEl =      $('<span>').hide().appendTo(document.body);
    $.fn.textWidth.fakeEl.text(text || this.val() || this.text()).css('font', font || this.css('font'));
    return $.fn.textWidth.fakeEl.width(); 
};

$('#inpt').on('input', function() {
    var padding = 10; //Works as a minimum width
    var valWidth = ($(this).textWidth() + padding) + 'px';
    $('#'+this.id+'-width').html(valWidth);
    $('#inpt').css('width', valWidth);
}).trigger('input');

回答by Piotr Siatkowski

I've found another solution for this problem not involving JS. In HTML I just put something like:

我为这个问题找到了另一个不涉及 JS 的解决方案。在 HTML 中,我只是放了一些类似的东西:

<div>
  <input class="input" value={someValue} />
  <div class="ghost-input">someValue</div>
</div>

All is needed is to set visibility: hidden on ghost-input and width: 100% on the input itself. It works because input scales to the 100% of its container which width is calculated by the browser itself (based on the same text).

所需要的只是设置可见性:隐藏在幽灵输入上和宽度:100% 在输入本身上。它起作用是因为输入缩放到其容器的 100%,其宽度由浏览器本身计算(基于相同的文本)。

If you add some padding and border to the input field you have to adjust your ghost-input class accordingly (or use calc() in input class).

如果您向输入字段添加一些填充和边框,则必须相应地调整您的 ghost-input 类(或在输入类中使用 calc() )。