Автоматическое масштабирование ввода [type = text] до значения ширины?

Есть ли способ масштабировать ширину <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" />

Ответ 1

Вы можете сделать это простым путем, установив атрибут size в длину входного содержимого:

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

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

Смотрите: http://jsfiddle.net/nrabinowitz/NvynC/

Похоже, что добавление некоторых дополнений справа, которые, как я подозреваю, зависит от браузера. Если вы хотите, чтобы он был очень плотным для ввода, вы можете использовать технику, например ту, которую я описываю в этом связанном ответе, используя jQuery для вычисления размера пикселя вашего текст.

Ответ 2

Если по какой-либо причине другие решения не сработают для вас, вы можете использовать contenteditable-span вместо входного элемента.

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

Обратите внимание, что это скорее хак и имеет серьезный недостаток, позволяющий полностью неанитизировать ввод HTML, позволяя пользователям вводить (и вставлять) линии, ссылки и другой HTML.

Итак, , вы, вероятно, не должны использовать это решение, если вы не очень тщательно дезинфицируете вход...

Обновить: вы, вероятно, захотите использовать решение Obsidian ниже.

Ответ 3

ПРОСТОТА, НО ПИКСЕЛЬ СОВЕРШЕННОЕ РЕШЕНИЕ

Я видел несколько способов сделать это, но вычисление ширины шрифтов не всегда на 100% точнее, это просто оценка.

Мне удалось создать идеальный способ пикселя для настройки ширины ввода с помощью скрытого замещающего объекта.


jQuery (рекомендуется)

  $(function() {
. $( '# Скрыть') текст ($ ( '# TXT') Вал().);
. $( '# TXT') Ширина ($ ( '# скрыть') ширина().);
}). on ('input', function() {
. $( '# Скрыть') текст ($ ( '# TXT') Вал().);
. $( '# TXT') Ширина ($ ( '# скрыть') ширина().);
});Код>
  body,
#текст,
#скрывать{
 шрифт: наследование;
 Маржа: 0;
 обивка: 0;
}
#текст{
 границы: нет;
 цвет: # 888;
 мин-ширина: 10px;
}
#скрывать{
 Дисплей: нет;
 бело-пространстве: предварительно;
}Код>
  < script src= "https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery. min.js" > < &/сценарий; GT

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

Ответ 4

Изменить. Теперь плагин работает с завершающими пробельными символами. Спасибо за указание @JavaSpyder

Так как большинство других ответов не соответствовало тому, что мне нужно (или просто не работало вообще) Я изменил Adrian B ответ на правильный плагин jQuery, который приводит к идеальному масштабированию ввода в пикселях без необходимости изменять ваш css или html.

Пример: https://jsfiddle.net/587aapc2/

Использование: $("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});

Ответ 5

У меня есть плагин jQuery на GitHub: https://github.com/MartinF/jQuery.Autosize.Input

Он отражает значение входа, вычисляет ширину и использует его для установки ширины входа.

Здесь вы можете увидеть живой пример: http://jsfiddle.net/mJMpw/2175/

Пример того, как его использовать (поскольку при отправке ссылки 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;    
}

Вы просто используете css для установки min/max-width и используете переход по ширине, если хотите приятный эффект.

Вы можете указать пробел/расстояние до конца как значение в нотации json для атрибута ввода-autosize-input на входном элементе.

Конечно, вы можете просто инициализировать его с помощью jQuery

$("selector").autosizeInput();

Ответ 6

Здесь уже много хороших ответов. Для удовольствия я реализовал это решение ниже, основываясь на других ответах и ​​моих собственных идеях.

<input class="adjust">

Элемент ввода настраивается точным пикселем и может быть определено дополнительное смещение.

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);

Настройка сглаживается с помощью перехода CSS.

.adjust {
    transition: width .15s;
}

Вот скрипка. Надеюсь, это поможет другим, кто ищет чистое решение.

Ответ 7

Вы можете решить эту проблему, как здесь:) http://jsfiddle.net/MqM76/217/

HTML:

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

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');

Ответ 8

К сожалению, атрибут size не будет работать очень хорошо. Иногда будет дополнительное пространство и слишком мало места, в зависимости от настройки шрифта. (посмотрите пример)

Если вы хотите, чтобы это хорошо работало, попробуйте просмотреть изменения на входе и затем измените его размер. Вероятно, вы хотите установить его на вход scrollWidth. Нам также нужно будет учитывать размер окна.

В следующем примере я устанавливаю 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 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>

Ответ 9

Вместо того, чтобы пытаться создать div и измерить его ширину, я думаю, что более надежно измерять ширину напрямую с помощью элемента canvas, который является более точным.

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

Теперь вы можете использовать это для измерения того, какая ширина какого-либо элемента ввода должна быть в любой момент времени, сделав это:

// 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);

Это возвращает число (возможно, с плавающей запятой). Если вы хотите учитывать прописку, вы можете попробовать следующее:

  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";

Ответ 10

Мой плагин jQuery работает для меня:

Использование:

    $('form input[type="text"]').autoFit({

    });

Исходный код jquery.auto-fit.js:

;
(function ($) {
    var methods = {
        init: function (options) {
            var settings = $.extend(true, {}, $.fn.autoFit.defaults, options);
            var $this = $(this);

            $this.keydown(methods.fit);

            methods.fit.call(this, null);

            return $this;
        },

        fit: function (event) {
            var $this = $(this);

            var val = $this.val().replace(' ', '-');
            var fontSize = $this.css('font-size');
            var padding = $this.outerWidth() - $this.width();
            var contentWidth = $('<span style="font-size: ' + fontSize + '; padding: 0 ' + padding / 2 + 'px; display: inline-block; position: absolute; visibility: hidden;">' + val + '</span>').insertAfter($this).outerWidth();

            $this.width((contentWidth + padding) + 'px');

            return $this;
        }
    };

    $.fn.autoFit = function (options) {
        if (typeof options == 'string' && methods[options] && typeof methods[options] === 'function') {
            return methods[options].apply(this, Array.prototype.slice.call(arguments, 1));
        } else if (typeof options === 'object' || !options) {
            // Default to 'init'
            return this.each(function (i, element) {
                methods.init.apply(this, [options]);
            });
        } else {
            $.error('Method ' + options + ' does not exist on jquery.auto-fit.');
            return null;
        }
    };

    $.fn.autoFit.defaults = {};

})(this['jQuery']);

Ответ 11

Элементы ввода ведут себя иначе, чем другие элементы, которые будут делать то, что вам нужно, если вы дадите им float: left (см. http://jsfiddle.net/hEvYj/5/). Я не думаю, что это возможно, не вычисляя его каким-либо образом с помощью JavaScript (т.е. Добавьте 5px к ширине на букву в поле).

Ответ 12

Пользователь решение nrabinowitz работает отлично, но я использую keypress событие вместо keyup. Это уменьшает задержку, если пользователь медленно вводит данные.

Ответ 13

Вот моя модификация решения nrabinowitz. Я не использовал свойство размер, потому что он не идеален с пропорциональными шрифтами, как отметил @Mark. Мое решение помещает элемент после ввода и получает ширину, подсчитанную браузером (используя jQuery).

Хотя я не тестирую его, я полагаю, что он будет работать, только если все свойства CSS, влияющие на шрифт, наследуются.

Ширина входного сигнала изменяется на событие focusout, которое работает лучше для меня. Но вы можете использовать keyup/keypress, чтобы изменить ширину ввода при вводе.

function resizeInput() {

    //Firstly take the content or placeholder if content is missing.
    var content =
        $(this).val().length > 0 ? $(this).val() : $(this).prop("placeholder");

    //Create testing element with same content as input.
    var widthTester = $("<span>"+content+"</span>").hide();

    //Place testing element into DOM after input (so it inherits same formatting as input does).
    widthTester.insertAfter($(this));

    //Set inputs width; you may want to use outerWidth() or innerWidth()
    //depending whether you want to count padding and border or not.
    $(this).css("width",widthTester.width()+"px");

    //Remove the element from the DOM
    widthTester.remove();
 }

 $('.resizing-input').focusout(resizeInput).each(resizeInput);

Ответ 14

Используя холст, мы можем вычислить ширину элементов:

function getTextWidth(text, fontSize, fontName) {
  let canvas = document.createElement('canvas');
  let context = canvas.getContext('2d');
  context.font = fontSize + fontName;
  return context.measureText(text).width;
}

и использовать его для выбранного события:

function onChange(e) {
  let width = getTextWidth(this.value, $(this).css('font-size'), 
  $(this).css('font-family'));
  $(this.input).css('width', width);
}

Ответ 15

try canvas measureText решение

CSS

    input{
        min-width:10px!important;
        max-width:99.99%!important;
        transition: width 0.1s;
        border-width:1px;
    }

JavaScript:

function getWidthOfInput(input){
    var canvas = document.createElement('canvas');
    var ctx = canvas.getContext('2d');
    var text = input.value.length ? input.value : input.placeholder;
    var style = window.getComputedStyle(input);
    ctx.lineWidth = 1;
    ctx.font = style.font;
    var text_width = ctx.measureText(text).width;
    return text_width;
}

function resizable (el, factor) {
    function resize() {
        var width = getWidthOfInput(el);
        el.style.width = width + 'px';
    }
    var e = 'keyup,keypress,focus,blur,change'.split(',');
    for (var i in e){
        el.addEventListener(e[i],resize,false);
    }
    resize();
}

$( "input" ).each( function(i){
    resizable(this);
});