hacer que el campo de entrada de texto html crezca a medida que escribo?

81

Puedo establecer el tamaño de entrada de texto inicial en css, así:

width: 50px;

Pero me gustaría que creciera cuando escribo hasta que alcance, por ejemplo, 200px. ¿Se puede hacer esto en css, html, preferiblemente sin javascript?

Por supuesto, también publique sus soluciones js / jquery, pero si esto es posible sin ellas, será genial.

mi intento aquí:

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

Stann
fuente
Creo que esta pregunta SO te ayudará: stackoverflow.com/questions/1288297/…
Curt
Para que conste, no fui yo. Parece una pregunta válida, aunque similar a la que he vinculado.
Curt
Andre: Trate de mantener los comentarios constructivos por favor.
Set
1
Podría utilizar un párrafo con contenteditable. Eso se expandirá a medida que escriba por sí solo.
Costa

Respuestas:

107

A continuación, se muestra un ejemplo con solo CSS y contenido editable :

Ejemplo de jsFiddle

CSS

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

HTML

<div>
    <span contenteditable="true">sdfsd</span>
</div>
Joe
fuente
4
HURRA. Lo acabo de probar en IE6-9, los últimos Opera, Firefox y Chrome, y Dios mío, ¡funcionó en todas partes!
Stann
4
Para mí, en Chrome, esto extiende el elemento una fila hacia abajo cuando alcanza el ancho máximo. Tampoco funcionará si la entrada está destinada a ser parte de un formulario.
Paul
5
Para un campo de entrada de varias líneas (saltos de línea personalizados), reemplace spanpor div. Tenga en cuenta que word-wrap: break-wordserán necesarias o palabras más largas que max-widthdesbordarán el cuadro div: jsfiddle.net/YZPmC/157
CodeManX
6
Asegúrese de buscar html no deseado que pueda entrar en el espacio satisfactorio a través de copiar y pegar.
Brian Peacock
3
¿Esto se envía con formulario?
Tomáš Zato - Reincorpora a Monica
38

Acabo de escribir esto para ti, espero que te guste :) No hay garantías de que sea entre navegadores, pero creo que sí :)

(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

Pablo
fuente
Gracias por este. Sin embargo, decidí hacerlo con un atributo contenteditable que no requiere js.
Stann
34
"Acabo de escribir esto para ti". +1 por el esfuerzo :)
Kevin Martin Jose
¿Cómo puedo permitir que esto apunte a más de 1 (4) entrada conid='adjinput'
teachtyler
muy creativo me encanta
Deryck
2
Esto supone que los cambios de contenido ocurren solo mediante el uso de un teclado.
hasta el
7

Si configura el intervalo para mostrar: bloque en línea, el cambio de tamaño horizontal y vertical automático funciona muy bien:

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

lastmjs
fuente
6

¿Qué tal modificar programáticamente el atributo de tamaño en la entrada?

Semánticamente (imo), esta solución es mejor que la solución aceptada porque todavía usa campos de entrada para la entrada del usuario, pero introduce un poco de jQuery. Soundcloud hace algo similar a esto para su etiquetado.

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

manguitos
fuente
2
Esto no funciona si resalta el texto y presiona la tecla de retroceso, ya que solo cuenta como tamaño-1, no como tamaño- $ ('input'). Val ().
Length
3
Supongo que contar value.lengthsería más fácil y más confiable.
Tomáš Zato - Reincorpora a Monica
1
Eliminar clave hace que esto crezca
Ricca
3

Un par de cosas vienen a la mente:

Utilice un onkeydowncontrolador en su campo de texto, mida el texto * y aumente el tamaño del cuadro de texto en consecuencia.

Adjunte una :focusclase css a su cuadro de texto con un ancho mayor. Entonces su caja será más grande cuando esté enfocada. Eso no es exactamente lo que estás pidiendo, pero es similar.

* No es sencillo medir texto en javascript. Consulte esta pregunta para obtener algunas ideas.

Seth
fuente
la mejor respuesta hasta ahora. :focus { width: 100% }
oldboy
3

De: ¿Existe un complemento de crecimiento automático de jQuery para campos de texto?


Vea una demostración aquí: http://jsbin.com/ahaxe

El complemento:

(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);
cmpolis
fuente
2

Aquí puedes probar algo como esto

EDITAR: EJEMPLO REVISADO (agregada una nueva solución) http://jsfiddle.net/jszjz/10/

Explicación del código

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

y el CSS también es bastante sencillo

#adjinput{
    max-width:200px !important;
    width:40px;
    min-width:40px;
    font-size:11px;
}

EDITAR: Otra solución es hacer que el usuario escriba lo que quiere y, en el desenfoque (enfoque), agarre la cadena (en el mismo tamaño de fuente), colóquela en un div, cuente el ancho del div, y luego con una animación agradable con un Efecto suavizante actualiza el ancho de los campos de entrada. El único inconveniente es que el campo de entrada seguirá siendo "pequeño" mientras el usuario escribe. O puede agregar un tiempo de espera :) ¡También puede verificar este tipo de solución en el violín de arriba!

Pantelis
fuente
font-sizeno es una solución perfecta. No está mal y ciertamente no vale la pena un voto negativo, pero intente escribir la letra ivarias veces y verá resultados muy sesgados en el tamaño. Vea mi respuesta para una solución para esto.
Paul
vea el segundo ejemplo en mi violín que no usa el tamaño de fuente y opta por la suavidad. El primero se agregó solo por velocidad y velocidad, manteniendo lo que quería el solicitante. Tener que crear un div adjuntarle texto, calcular su ancho, etc., etc. cada vez me parece "pesado", por algo así de simple.
Pantelis
No estoy seguro de por qué, pero su segundo ejemplo no cambia de tamaño en absoluto para mí. También tenga en cuenta que mi solución (que crea un div temporal y demás) puede ejecutarse aproximadamente 800 veces por segundo en un navegador moderno en una computadora promedio actualizada y probablemente no sea mucho más lenta que 100 veces por segundo en 99.5 % de computadoras que todavía están en uso hoy)
Paul
2

Sé que esta es una publicación muy antigua, pero mi respuesta podría ser útil para otros de todos modos, así que aquí va. Descubrí que si mi definición de estilo CSS para el div contenteditable tiene una altura mínima de 200 en lugar de una altura de 200, entonces el div se escala automáticamente.

b0rgBart3
fuente
1

Si solo está interesado en crecer, puede actualizar el widtha scrollWidthsiempre inputque cambie el contenido del elemento.

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

Pero esto no encogerá el elemento.

ceving
fuente
1

El enfoque que utilice, por supuesto, depende de cuál sea su objetivo final. Si desea enviar los resultados con un formulario, usar elementos de formulario nativos significa que no tiene que usar secuencias de comandos para enviar. Además, si la secuencia de comandos está desactivada, la reserva seguirá funcionando sin los elegantes efectos de reducción de tamaño. Si desea obtener el texto sin formato de un elemento satisfactorio , siempre puede usar secuencias de comandos como node.textContent para eliminar el html que los navegadores insertan en la entrada del usuario.

Esta versión utiliza elementos de formulario nativo con ligeras mejoras en algunas de las publicaciones anteriores.

También permite que el contenido se reduzca.

Use esto en combinación con CSS para un mejor control.

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

Puedes usar algo similar con los elementos <textarea>

document.querySelectorAll('textarea').forEach(function(node) {
  var minHeight = parseInt(getComputedStyle(node).minHeight) || node.clientHeight;
  node.style.overflowY = 'auto'; // 'hidden'
  node.onchange = node.oninput = function() {
    node.style.height = minHeight + 'px';
    node.style.height = node.scrollHeight + 'px';
  };
});

Esto no parpadea en Chrome, los resultados pueden variar en otros navegadores, así que prueba.

Kevin Douglas
fuente
0

Aquí hay un método que funcionó para mí. Cuando escribe en el campo, coloca ese texto en el intervalo oculto, luego obtiene su nuevo ancho y lo aplica al campo de entrada. Crece y se encoge con su entrada, con una protección contra la entrada que prácticamente desaparece cuando borra toda la entrada. Probado en Chrome. (EDITAR: funciona en Safari, Firefox y Edge en el momento de esta edición)

function travel_keyup(e)
{
    if (e.target.value.length == 0) return;
    var oSpan=document.querySelector('#menu-enter-travel span');
    oSpan.textContent=e.target.value;
    match_span(e.target, oSpan);
}
function travel_keydown(e)
{
    if (e.key.length == 1)
    {
        if (e.target.maxLength == e.target.value.length) return;
        var oSpan=document.querySelector('#menu-enter-travel span');
        oSpan.textContent=e.target.value + '' + e.key;
        match_span(e.target, oSpan);
    }
}
function match_span(oInput, oSpan)
{
    oInput.style.width=oSpan.getBoundingClientRect().width + 'px';
}

window.addEventListener('load', function()
{
    var oInput=document.querySelector('#menu-enter-travel input');
    oInput.addEventListener('keyup', travel_keyup);
    oInput.addEventListener('keydown', travel_keydown);

    match_span(oInput, document.querySelector('#menu-enter-travel span'));
});
#menu-enter-travel input
{
	width: 8px;
}
#menu-enter-travel span
{
	visibility: hidden;
    position: absolute;
    top: 0px;
    left: 0px;
}
<div id="menu-enter-travel">
<input type="text" pattern="^[0-9]{1,4}$" maxlength="4">KM
<span>9</span>
</div>

Aaron Mason
fuente
0

Si se le permite usar la medida ch (monoespaciada), resolvió por completo lo que estaba tratando de hacer.

onChange(e => {
    e.target.style.width = `${e.target.length}ch`;
})

Esto era exactamente lo que necesitaba, pero no estoy seguro de si funciona para familias de fuentes de ancho dinámico.

jscul
fuente
0

Para aquellos que buscan estrictamente una solución que funcione para entrada o área de texto, esta es la solución más simple que he encontrado. Solo unas pocas líneas de CSS y una línea de JS.

JavaScript establece un atributo data- * en el elemento igual al valor de la entrada. La entrada se establece dentro de una cuadrícula CSS, donde esa cuadrícula es un pseudo-elemento que usa ese atributo data- * como su contenido. Ese contenido es lo que extiende la cuadrícula al tamaño apropiado según el valor de entrada.

Chen W
fuente
0

Todo lo que necesita hacer es obtener el elemento del campo de entrada que desea crecer a medida que escribe y en CSS, establecer el ancho de la entrada en automático y establecer un ancho mínimo para decir 50px.

Anthony Rosario
fuente
Bienvenido a Stack Overflow. Lea Cómo responder. stackoverflow.com/questions/how-to-answer
Ran Marciano