Сделать поле ввода текста HTML расти по мере ввода?

Я могу установить начальный размер ввода текста в CSS, например, так:

width: 50px;

Но я бы хотел, чтобы он рос, когда я набираю текст, например, до 200px. Может ли это быть сделано в прямой CSS, HTML, желательно без JavaScript?

Размещайте свои решения js/jquery, конечно, но если это возможно без них - это будет здорово.

моя попытка здесь:

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

16 ответов

Решение

Вот пример только с CSS и Content Editable:

Пример jsFiddle

CSS

span 
{
    border: solid 1px black;
}
div 
{
    max-width: 200px;   
}

HTML

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

Я только что написал это для вас, я надеюсь, вам понравится:) Нет гарантий, что это кросс-браузер, но я думаю, что это так:)

(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

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

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

Как насчет программного изменения атрибута размера на входе?

Семантически (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/

Если вы просто заинтересованы в росте, вы можете обновить width в scrollWidthвсякий раз, когда содержание input изменения элемента.

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

Но это не уменьшит элемент.

From: Есть ли плагин jQuery autogrow для текстовых полей?


Посмотреть демо здесь: 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);

Несколько вещей приходят на ум:

Используйте onkeydown обработчик в вашем текстовом поле, измерьте текст * и соответственно увеличьте размер текстового поля.

Прикрепить :focus Класс CSS для вашего текстового поля с большей шириной. Тогда ваша коробка будет больше, когда сфокусирована. Это не совсем то, что вы просите, но похоже.

* Это не просто измерить текст в JavaScript. Проверьте этот вопрос для некоторых идей.

Здесь вы можете попробовать что-то вроде этого

РЕДАКТИРОВАТЬ: ПЕРЕСМОТРЕННЫЙ ПРИМЕР (добавлено одно новое решение) 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 - и затем с хорошей анимацией с крутым Эффект ослабления обновляет ширину полей ввода. Единственным недостатком является то, что поле ввода останется "маленьким", пока пользователь вводит. Или вы можете добавить тайм-аут:) вы также можете проверить такое решение на скрипке выше!

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

Вы можете сделать это с помощью:

Идея состоит в том, чтобы создать фиктивный элемент, содержащий то же содержимое, что и у, а затем установить ширину, соответствующую ширине фиктивного элемента. Выше мы используем JavaScript для синхронизации текста, а display: inline-grid трюк, чтобы установить input ширина, чтобы соответствовать.

(Этот подход взят из этой статьи ; я сократил его до самого необходимого.)

Конечно, какой подход вы используете, зависит от вашей конечной цели. Если вы хотите отправить результаты с помощью формы, то использование собственных элементов формы означает, что вам не нужно использовать сценарии для отправки. Кроме того, если сценарии отключены, то запасной вариант все еще работает без причудливых эффектов увеличения и уменьшения. Если вы хотите получить простой текст из 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';
  };
});

Вы можете использовать что-то подобное с элементами