Ajuste el ancho del campo de entrada a su entrada

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

Este es mi código y no funciona. ¿Hay alguna otra forma en HTML, JavaScript, PHP o CSS para establecer el ancho mínimo?

Quiero un campo de entrada de texto con un ancho que cambie dinámicamente, para que el campo de entrada fluya alrededor de su contenido. Cada entrada tiene un relleno incorporado 2em, ese es el problema y el segundo problema es que min-widthno funciona en absoluto en la entrada.

Si configuro el ancho más de lo necesario de lo que todo el programa es desordenado, necesito el ancho de 1px, más solo si es necesario.

Kerc
fuente
¿Responde esto a tu pregunta? Crear un área de texto con cambio de tamaño automático
DreamTeK

Respuestas:

96

Parece que su expectativa es que el estilo se aplique dinámicamente al ancho del cuadro de texto en función del contenido del cuadro de texto. Si es así, necesitará algunos js para ejecutar el cambio de contenido del cuadro de texto, algo como esto :

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

Nota: esta solución solo funciona cuando cada carácter es exactamente 8pxancho.

Tahbaza
fuente
41
@Kerc & Tahbaza: sí, pero esto solo funcionará si el ancho de cada carácter es exactamente de 8 píxeles.
Marcel Korpel
66
Estoy de acuerdo, Marcel (y el código publicado no es algo para lo que realmente pueda usar) pero exhibe el comportamiento deseado. ¿Sabes cómo calcular el ancho real del texto representado teniendo en cuenta la fuente, el tamaño, el peso, el interletraje, etc.? Si es así, por favor comparta, ya que en ocasiones me parecería útil ese código.
Tahbaza
1
- Ya pensé que era solo un ejemplo. Sin embargo, no es tan difícil calcular el ancho de la entrada. Mira mi respuesta.
Marcel Korpel
Las unidades em son el ancho del carácter "m". Esto sería útil para calcular el ancho de una cadena. Sin embargo, he visto problemas entre navegadores con unidades em aplicadas a algunos atributos, así que pruébelo.
Archonic
77
ha olvidado la PASTA caso de que mi amigo;) se debe cambiar aonInput
VSYNC
114

En las versiones modernas del navegador, la unidad CSS chtambién está disponible. A mi entender, es una unidad independiente de la fuente, donde 1ches igual al ancho del carácter 0(cero) en cualquier fuente dada.

Por lo tanto, algo tan simple como lo siguiente podría usarse como función de cambio de tamaño:

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>

Ese ejemplo redimensionaría "elem" a la longitud del valor + 2 caracteres extra.

Jani Jalkala
fuente
13
Me sorprende que este comentario no sea votado más alto, porque es una gran solución y aproximadamente el 95% ( 1 ) de los navegadores lo admiten.
Husky
8
Esta no es una buena respuesta, ya que la medición no es precisa y no tiene en cuenta los estilos que pueden ocurrir en el inputelemento, como font-style, letter-spacingetc. He editado la respuesta con una demostración en vivo.
vsync
55
Funciona muy bien si usa una fuente monoespaciada. Con otras fuentes, su kilometraje puede variar ya que aparentemente usa el ancho de caracteres del carácter 0.
Jilles van Gurp
2
Esto es realmente genial Aunque tenga en cuenta que a veces falla / no funciona como esperaba cuando .se encuentra un.
Rishav
1
Esto funciona perfectamente si configura el tamaño del cuadro en la entrada a 'content-box'. De esta forma, ignora el relleno cuando establece el tamaño.
Hypersapien
65

Para calcular el ancho de la entrada actual, deberá incrustarlo en un spanelemento temporal , adjuntarlo al DOM, obtener el ancho calculado (en píxeles) utilizando la scrollWidthpropiedad y eliminarlo spannuevamente. Por supuesto, deberá asegurarse de utilizar la misma familia de fuentes, tamaño de fuente, etc., inputtanto en el spanelemento como en el elemento. Por lo tanto, les asigné la misma clase.

Adjunté la función al keyupevento, ya que keypressel carácter de entrada aún no se agrega a la entrada value, por lo que el ancho será incorrecto. Desafortunadamente, no sé cómo deshacerme del desplazamiento del campo de entrada (al agregar caracteres al final del campo); se desplaza, porque el carácter se agrega y se muestra antes de que adjustWidthOfInput()se llame. Y, como se dijo, no puedo hacer esto al revés porque entonces tendrás el valor del campo de entrada antes de insertar el carácter presionado. Intentaré resolver este problema más tarde.

Por cierto, solo probé esto en Firefox (3.6.8), pero espero que entiendas el punto.

<!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>
Marcel Korpel
fuente
Me gustó su respuesta e incluso la implementé usando jQuery / Underscore: gist.github.com/3745941 . Sin embargo, podría hacer ciertas suposiciones: (1) el ancho de cualquier carácter no es mayor a 14px, (2) es aceptable que el elemento de entrada se extienda 14px más allá del valor del elemento. ¡Tengo esto adjunto a un evento keydown y está funcionando muy bien!
Nathan
11
Usted debe agregar white-space: pre;en css de esta manera: .tmp-element{ visibility: hidden; white-space: pre;}. De lo contrario, los espacios en blanco se combinan y el cálculo del ancho falla. <input>y se <span>comporta de manera diferente con respecto al manejo <input>de espacios en blanco , retiene espacios en blanco y <span>combina espacios en blanco secuenciales en uno si white-space: pre;no se agrega.
Timo Kähkönen
2
tmp.getBoundingClientRect().widthes mejor que tmp.scrollWidth, porque eso a veces devuelve 0
lisak
@lisak Gracias, ajusté mi respuesta, pero ya hay mejores respuestas aquí.
Marcel Korpel
¿Mejor? Yo no diría eso. La respuesta marcada carece de precisión, otros (+ aquí 1 y aquí 2 ) usan jQuery, no por React. El lienzo no puede darle la altura del texto AFAIK. Idea: el problema con los espacios también podría resolverse con:.replace(/ /g, "&nbsp;")
Milan Jaros
30

Aquí hay una modificación de la respuesta de Lyth que tiene en cuenta:

  • Supresión
  • Inicialización
  • Marcadores de posición

¡También permite cualquier cantidad de campos de entrada! Para verlo en acción: http://jsfiddle.net/4Qsa8/

Guión:

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

Estilo:

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

HTML:

<div class="resizing-input">
    <input type="text" placeholder="placeholder"/>
    <span  style="display:none"></span>
</div>

Miguel
fuente
Hola Michael. Su código funciona muy bien pero tengo un problema. Uno de mi campo es un campo de autocmplete de Google place. Y cuando elijo la dirección correcta de un menú desplegable, el ancho del campo de entrada no cambia según la longitud de la dirección elegida. ¿Hay una solución simple para ello?
Maxence
2
@Maxence escuchando el evento changeo inputsería suficiente
yarwest
Tuve problemas con la pantalla del span: ninguno de estilo, ya que registró el span como 0 ancho. Mejor usar posicionamiento absoluto con visibilidad: oculto para el tramo.
jayt
Hola @yarwest, gracias por el consejo. ¿Por casualidad sabrías cómo modificar el script original con esta configuración? (mi conocimiento en Js / jquery es muy muy limitado)
Maxence
21

Aquí hay una solución que no necesita fuente monoespaciada , con un código de pieza muy pequeño de javascript , no necesita calcular estilos calculados e, incluso admite ime , admite textos 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 span.textpara ajustar el ancho del texto y deje que la entrada tenga el mismo tamaño con position: absoluteel contenedor. Copie el valor de la entrada spancada vez que cambie (puede cambiar este código a vainilla js fácilmente). Por lo tanto, la entrada simplemente "se ajustará" al tamaño de su contenido.

tsh
fuente
18

PARA UNA MIRADA Y SENTIR NICER

Debe usar el evento jQuery keypress () en combinación con String.fromCharCode (e.which) para obtener el carácter presionado. Por lo tanto, puede calcular cuál será su ancho . ¿Por qué? Porque se verá mucho más sexy :)

Aquí hay un jsfiddle que resulta en un comportamiento agradable en comparación con las soluciones que usan el evento keyup: http://jsfiddle.net/G4FKW/3/

A continuación se muestra un JS de vainilla que escucha el inputevento de un <input>elemento y establece que un spanhermano tenga el mismo valor de texto para medirlo.

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>

Lyth
fuente
1
Se ve bien, pero no tiene Retroceso y Eliminar en cuenta.
Marcel Korpel
Sí, para esto necesitas un evento keydown. Puede agregar un manejo específico para retroceso y eliminar al hacerlo (por ejemplo, === 46 para eliminar, e.que === 8 para retroceso). Pero aún necesita el evento de pulsación de tecla para tener acceso a e.charCode para el resto.
Lyth
Si no es compatible con IE8, puede usar el evento oninput en lugar de verificar e.which: developer.mozilla.org/en-US/docs/Web/Events/input
Frinsh
1
He editado tu respuesta para eliminar jQuery y usar solo vanilla JS. Tenga en cuenta que esta solución está lejos de ser óptima porque desea una solución genérica que no implique la codificación manual de ay spancss.
vsync
17

Esta es una respuesta específica de Angular, pero funcionó para mí y ha sido muy satisfactoria en términos de simplicidad y facilidad de uso:

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

Se actualiza automáticamente a través de las unidades de personajes en la respuesta de Jani .

Chris Vandevelde
fuente
3
Esta. Es. Épico.
Daniel Flippance
Seriamente. Mágico.
DongBin Kim
13

Aquí hay una forma alternativa de resolver esto usando un DIV y la propiedad 'contenteditable':

HTML:

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

CSS: (para darle al DIV algunas dimensiones y facilitar su visualización)

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

}

Nota: Si planea usar esto dentro de un elemento FORM que planea enviar, necesitará usar Javascript / jQuery para capturar el evento de envío para poder analizar el 'valor' ( .innerHTMLo .html()respectivamente) del DIV.

lógica8
fuente
1
Esto merece más votos a favor. Es elegante y simple (siempre y cuando usar JS para validaciones de formularios no sea un problema para usted).
Daniel Bonnell
3
¡Pero no es una entrada!
Toni Michel Caubet
8

También puede establecer el ancho de una entrada utilizando el atributo de tamaño . El tamaño de una entrada determina su ancho en caracteres.

Una entrada podría ajustar dinámicamente su tamaño al escuchar eventos clave.

Por ejemplo

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

JsFiddle aquí

Brendan
fuente
7

Podrías hacer algo como esto

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

Corbatas
fuente
Si aumenta el tamaño en el teclado, dará como resultado un comportamiento feo. La entrada debe aumentar su tamaño justo antes de que el personaje entre en él para mayor comodidad.
Lyth
5

Solo agregando sobre otras respuestas.

Noté que hoy en día en algunos navegadores el campo de entrada tiene un desplazamiento de ancho. Lo que significa:

this.style.width = this.scrollWidth + 'px';

Debería funcionar bien. Probado en Chrome, Firefox y Safari.

Para el soporte de eliminación, puede agregar '= 0' primero y luego reajustar.

this.style.width = 0; this.style.width = this.scrollWidth + 'px';
chico mograbi
fuente
3
Agregue también el código relevante aquí: el enlace puede estar muerto en el futuro y luego esta publicación no sirve para nada.
Uooo
3
Esto funciona muy bien, gracias! No sé por qué esta respuesta no tiene más votos a favor. Es, con mucho, la solución más simple y menos artificial (js).
Formulario
4

Aquí hay un JS simple y un complemento jQuery que escribí que manejará el cambio de tamaño de un elemento de entrada usando un lienzo y el tamaño de fuente / familia para determinar la longitud real de la cadena cuando se procesa. (solo funciona en> IE9, Chrome, Safari, Firefox, Opera y la mayoría de los otros navegadores principales que han implementado el elemento Canvas).

PlainJS:

function autoSize(input, o) {
    o || (o = {});
    o.on || (o.on = 'keyup');

    var canvas = document.createElement('canvas');
    canvas.setAttribute('style', 'position: absolute; left: -9999px');
    document.body.appendChild(canvas);

    var ctx = canvas.getContext('2d');

    input.addEventListener(o.on, function () {
        ctx.font = getComputedStyle(this,null).getPropertyValue('font');
        this.style.width = ctx.measureText(this.value + '  ').width + 'px';
    });
}

//Usage
autoSize(document.getElementById('my-input'));

Complemento jQuery:

$.fn.autoSize = function(o) {
  o = $.extend({}, {
    on: 'keyup'
  }, o);

  var $canvas = $('<canvas/>').css({position: 'absolute', left: -9999});
  $('body').append($canvas);

  var ctx = $canvas[0].getContext('2d');

  return this.on(o.on, function(){
    var $this = $(this);
    ctx.font = $this.css('font');
    $this.width(ctx.measureText($this.val()).width + 'px');
  })
}

//Usage:
$('#my-input').autoSize();

Nota: esto no manejará las transformaciones de texto, el espaciado entre líneas y el espaciado entre letras, y probablemente algunas otras propiedades de cambio de tamaño de texto. Para manejar el conjunto de propiedades de transformación de texto y ajustar el valor del texto para que coincida con esa propiedad. Los otros son probablemente bastante sencillos. Implementaré si esto comienza a ganar algo de tracción ...

newms87
fuente
4

Vale la pena señalar que se puede hacer un cambio de tamaño agradable cuando la fuente es monoespaciada, por lo que podemos cambiar el tamaño del inputelemento perfectamente usando la chunidad.

También en este enfoque podemos actualizar el ancho del campo simplemente actualizando una variable CSS ( propiedad personalizada ) en el inputevento y también debemos ocuparnos de la entrada ya rellenada previamente en el DOMContentLoadedevento

Codepen demo


Margen

<input type="text" value="space mono font" class="selfadapt" />

CSS

:root { --size: 0; }

.selfadapt {
   padding: 5px;
   min-width: 10ch;
   font-family: "space mono";
   font-size: 1.5rem;
   width: calc(var(--size) * 1ch);
}

Como variable raíz establecemos --size: 0: esta variable contendrá la longitud de la entrada y se multiplicará por 1chdentro de la calc()expresión. Por defecto, también podríamos establecer un ancho mínimo, por ejemplo10ch

La parte Javascript lee la longitud del valor insertado y actualiza la variable --size:

JS

let input = document.querySelector('.selfadapt');
let root  = document.documentElement.style;

/* on input event auto resize the field */
input.addEventListener('input', function() {
   root.setProperty('--size', this.value.length );
});

/* resize the field if it is pre-populated */
document.addEventListener("DOMContentLoaded", function() {
   root.setProperty('--size', input.value.length);
});

por supuesto, esto aún funciona incluso si no usa una fuente monoespaciada, pero en ese caso deberá cambiar la calc()fórmula multiplicando la --sizevariable por otro valor (que depende estrictamente de font-familyy font-size) diferente de 1ch.

Fabrizio Calderan
fuente
3

Esta respuesta proporciona uno de los métodos más precisos para recuperar el ancho de texto disponible en el navegador y es más precisa que la respuesta aceptada. Utiliza el elemento lienzo html5 y, a diferencia de otras respuestas, no agrega el elemento al DOM y, por lo tanto, evita cualquier problema de reflujo causado por la adición excesiva de elementos al DOM.

Lea más sobre el elemento Canvas aquí en relación con el ancho del texto.

NOTA: Según MDN, las versiones abreviadas del getPropertyValue()método, como la fuente, pueden no ser confiables. Recomiendo obtener los valores de forma singular para mejorar la compatibilidad. Solo lo usé aquí por velocidad.

/**
 * returns the width of child text of any DOM node as a float
 */
function getTextWidth(el) {
  // uses a cached canvas if available
  var canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas"));
  var context = canvas.getContext("2d");
  // get the full font style property
  var font = window.getComputedStyle(el, null).getPropertyValue('font');
  var text = el.value;
  // set the font attr for the canvas text
  context.font = font;
  var textMeasurement = context.measureText(text);
  return textMeasurement.width;
}

var input = document.getElementById('myInput');
// listen for any input on the input field
input.addEventListener('input', function(e) {
  var width = Math.floor(getTextWidth(e.target));
  // add 10 px to pad the input.
  var widthInPx = (width + 10) + "px";
  e.target.style.width = widthInPx;
}, false);
#myInput {
  font: normal normal 400 normal 18px / normal Roboto, sans-serif;
  min-width: 40px;
}
<input id="myInput" />

Matthew Brent
fuente
2

Puede hacerlo aún más simple en angularjs utilizando la directiva incorporada ng-style .

En tu html:

  <input ng-style="inputStyle(testdata)" ng-model="testdata" />

En tu controlador:

 $scope.testdata = "whatever";

 $scope.inputStyle = function(str) {
    var charWidth = 7;
    return  {"width": (str.length +1) * charWidth + "px" };
    };

En tu css:

input { font-family:monospace; font-size:12px; }

Ajuste el ancho de char para que coincida con el ancho de su fuente. Parece ser 7 con un tamaño de letra de 12px;

michieljoris
fuente
3
Es genial y práctico saberlo, pero agregar angularjs a una aplicación para cambiar el tamaño dinámicamente de un elemento de entrada es una exageración realmente seria, especialmente cuando OP solicitó soluciones "HTML, JavaScript, PHP o CSS". Se podría argumentar que jQuery también es excesivo para esto, pero, a diferencia de Angular, ser un kit de herramientas de manipulación DOM es esencial para el propósito de jQuery.
Vlasits
¿Cómo se supone que debo saber el ancho del carácter que se está escribiendo? No es fácil asumir que es una fuente de tamaño mono.
Ethan
1
No puede requerir una fuente monoespaciada, y no hay necesidad de Angular. La respuesta de Brendan hace básicamente lo mismo.
Dan Dascalescu
2

Si usa Bootstrap, se podría hacer muy fácilmente:

<div contenteditable="true" class="form-control" style="display: inline"></div>

Solo tendrá que buscar el contenido de div y ponerlo en una entrada oculta antes de enviar el formulario.

Alexey Kosov
fuente
1

Creo que estás malinterpretando la propiedad CSS de ancho mínimo . min-width se usa generalmente para definir un ancho DOM mínimo en un diseño fluido, como:

input {
  width: 30%;
  min-width: 200px;
}

Eso establecería el elemento de entrada en un ancho mínimo de 200 píxeles. En este contexto, "px" significa "píxeles".

Ahora, si está tratando de verificar para asegurarse de que el campo de entrada contiene al menos un carácter cuando un usuario lo envía, deberá validar un formulario con JavaScript y PHP. Si eso es lo que estás intentando hacer, editaré esta respuesta y haré todo lo posible para ayudarte.

Peterjmag
fuente
Sé lo que significa px y sé que JavaScript tiene una función para ancho mínimo, pero no funciona para el texto de entrada.
Kerc
1
@Kerc: “javascript tiene una función para ancho mínimo”, ¿cuál? ¿Qué quieres decir? - "no funciona" nunca es una buena descripción de un problema. Intenta elaborar sobre el comportamiento previsto.
Marcel Korpel
¿Incluso probaste mi ejemplo, de lo que ves que no es 1 px y el tuyo tampoco? Esto no va a funcionar, no importa si lo escribo en html, css
Kerc
Quizás hay una función php para esto, ¿alguien lo sabe?
Kerc
Intenté su ejemplo, pero supuse que un campo de entrada de 1 píxel de ancho no era lo que estaba buscando. Si es así, intente<input type="text" value="1" style="width:1px;" />
peterjmag
1

Realmente me gustó la respuesta de Lyth , pero también quería:

  1. Manejar retroceso y eliminar
  2. No requiere que agregue manualmente una etiqueta adyacente.
  3. Hacer cumplir un ancho mínimo.
  4. Se aplica automáticamente a elementos con una clase específica

Adapte su JSFiddle y se me ocurrió esto . Una mejora que no está presente en este violín sería usar algo como jQuery CSS Parser para leer realmente el ancho inicial de la regla input.textbox-autosize y usarlo como minWidth. Bien, simplemente estoy usando un atributo en el, lo que lo convierte en una demostración compacta pero no es ideal. ya que requiere un atributo adicional en cada entrada. También es posible que solo desee colocar el minWidth como 100 directamente en JavaScript.

HTML:

<div id='applicationHost'>
<div>Name:   <input class='textbox-autosize' data-min-width='100' type="text" /></div>
<div>Email:  <input class='textbox-autosize' data-min-width='100' type="email" /></div>
<div>Points: <input class='textbox-autosize' data-min-width='100' type="number" /></div>
</div>

CSS:

#applicationHost {
    font-family: courier;
    white-space: pre;
}

input.textbox-autosize, span.invisible-autosize-helper {
    padding:0;
    font-size:12px;
    font-family:Sans-serif; 
    white-space:pre;
}
input.textbox-autosize {
    width: 100px; /* Initial width of textboxes */
}

/*
In order for the measurements to work out, your input and the invisible
span need to have the same styling.
*/

JavaScript:

$('#applicationHost').on('keyup', '.textbox-autosize', function(e) {
    // Add an arbitary buffer of 15 pixels.
    var whitespaceBuffer = 15;
    var je = $(this);
    var minWidth = parseInt(je.attr('data-min-width'));
    var newVal = je.val();
    var sizingSpanClass = 'invisible-autosize-helper';
    var $span = je.siblings('span.' + sizingSpanClass).first();
    // If this element hasn't been created yet, we'll create it now.
    if ($span.length === 0) {
        $span = $('<span/>', {
            'class': sizingSpanClass,
            'style': 'display: none;'
        });
        je.parent().append($span);
    }
    $span = je.siblings('span').first();
    $span.text(newVal) ; // the hidden span takes 
    // the value of the input
    $inputSize = $span.width();
    $inputSize += whitespaceBuffer;
    if($inputSize > minWidth)
        je.css("width", $inputSize) ; // apply width of the span to the input
    else
        je.css("width", minWidth) ; // Ensure we're at the min width
});
Josh
fuente
1

Mejor es onvalue:

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

También implica pegar, arrastrar y soltar, etc.

Łukasz Polowczyk
fuente
1

Aquí están mis 2 centavos. Crea un div invisible vacío. Rellenar con el contenido de entrada y devolver el ancho al campo de entrada. Haga coincidir los estilos de texto entre cada cuadro.

$(".answers_number").keyup(function(){
    $( "#number_box" ).html( $( this ).val() );
    $( this ).animate({
        width: $( "#number_box" ).width()+20
        }, 300, function() {
    });
});
#number_box {
   position: absolute;
   visibility: hidden;
   height: auto;
   width: auto;
   white-space: nowrap;
   padding:0 4px;
   /*Your font styles to match input*/
   font-family:Arial;
   font-size: 30px; 
}
    
.answers_number {
   font-size: 30px; 
   font-family:Arial;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="number" class="answers_number" />
<div id="number_box">
</div>

Thomas Byy
fuente
1

Bastante sencillo:

oninput='this.style.width = (this.scrollWidth - N) + "px";'

Donde N es algún número (2 en el ejemplo, 17 en algo que estoy desarrollando) que se determina experimentalmente.

Restar N evita que este extraño y extenso espacio se acumule mucho antes de que el texto llegue al final del cuadro de texto.

Comparar. Presta mucha atención a cómo cambia el tamaño incluso después del primer personaje.

<p>Subtracting N:</p>    
<input type="text" placeholder="enter lots of text here" oninput='this.style.width = (this.scrollWidth-2) + "px";'>

<p>Not Subtracting N:</p>    
<input type="text" placeholder="enter lots of text here" oninput='this.style.width = (this.scrollWidth) + "px";'>

Dan T
fuente
No he probado extensamente con esto, pero sólo podía cambiar oninput='this.style.width = (this.scrollWidth-2) + "px";'por oninput='this.style.width = 0; this.style.width = this.scrollWidth + "px";'deshacerse del espacio de acumulación
MaxCloutier
0

Solo paso algún tiempo descubriendo cómo hacerlo.
En realidad, la forma más simple que encontré es mover el valor de entrada para abarcar justo antes de la entrada, manteniendo el ancho del símbolo de entrada 1. Aunque no puedo estar seguro de que se ajuste a tu necesidad inicial.
Tal vez sea un código extra, pero en la aplicación basada en react + flux es una solución bastante natural.

freele
fuente
0

Basado en la respuesta de Michael, he creado mi propia versión de esto usando jQuery. Creo que es una versión más limpia / corta de la mayoría de las respuestas aquí y parece hacer el trabajo.

Estoy haciendo lo mismo que la mayoría de las personas aquí usando un espacio para escribir el texto de entrada y luego obtener el ancho. Luego estoy configurando el ancho cuando se llaman las acciones keyupy blur.

Aquí hay un codepen que funciona . Este codepen muestra cómo se puede usar con múltiples campos de entrada.

Estructura HTML:

<input type="text" class="plain-field" placeholder="Full Name">
<span style="display: none;"></span>

jQuery:

function resizeInputs($text) {
    var text = $text.val().replace(/\s+/g, ' '),
        placeholder = $text.attr('placeholder'),
        span = $text.next('span');
        span.text(placeholder);
    var width = span.width();

    if(text !== '') {
        span.text(text);
    var width = span.width();
    }

    $text.css('width', width + 5);
};

La función anterior obtiene el valor de las entradas, recorta los espacios adicionales y establece el texto en el intervalo para obtener el ancho. Si no hay texto, obtiene el marcador de posición y lo ingresa en el intervalo. Una vez que ingresa el texto en el intervalo, establece el ancho de la entrada. El + 5ancho es porque sin eso la entrada se corta un poco en el navegador Edge.

$('.plain-field').each(function() {
    var $text = $(this);
    resizeInputs($text);
});

$('.plain-field').on('keyup blur', function() {
    var $text = $(this);
    resizeInputs($text);
});

$('.plain-field').on('blur', function() {
    var $text = $(this).val().replace(/\s+/g, ' ');
    $(this).val($text);
});

Si esto pudiera mejorarse, avíseme, ya que esta es la solución más limpia que se me ocurrió.

Mateo
fuente
0

¿Por qué no usar solo css?

<div id="wrapper">
  <input onkeyup="keyup(event)">
  <div id="ghost"></div>
</div>

function keyup(e) {
	document.getElementById('ghost').innerText = e.target.value;
}
#wrapper {
  position: relative;
  min-width: 30px;
  display: inline-block;
}

input {
  position: absolute;
  left:0;
  right:0;
  border:1px solid blue;
  width: 100%;
}

#ghost {
  color: transparent;
}
<div id="wrapper">
  <input onkeyup="keyup(event)">
  <div id="ghost"></div>
</div>

wrapper {
  position: relative;
  min-width: 30px;
  border: 1px solid red;
  display: inline-block;
}

input {
  position: absolute;
  left:0;
  right:0;
  width: 100%;
}

#ghost {
  color: transparent;
}

@Iain Todd introdujo este código y pensé que debería compartirlo

Milad
fuente
No es solo CSS. Es solo otro método js. Interesante
vatavale
0

Una forma genérica a prueba de balas tiene que:

  1. Tener en cuenta todos los estilos posibles del inputelemento medido.
  2. Poder aplicar la medida en cualquier entrada sin modificar el HTML o

Codepen demo

var getInputValueWidth = (function(){
  // https://stackoverflow.com/a/49982135/104380
  function copyNodeStyle(sourceNode, targetNode) {
    var computedStyle = window.getComputedStyle(sourceNode);
    Array.from(computedStyle).forEach(key => targetNode.style.setProperty(key, computedStyle.getPropertyValue(key), computedStyle.getPropertyPriority(key)))
  }
  
  function createInputMeassureElm( inputelm ){
    // create a dummy input element for measurements
    var meassureElm = document.createElement('span');
    // copy the read input's styles to the dummy input
    copyNodeStyle(inputelm, meassureElm);
    
    // set hard-coded styles needed for propper meassuring 
    meassureElm.style.width = 'auto';
    meassureElm.style.position = 'absolute';
    meassureElm.style.left = '-9999px';
    meassureElm.style.top = '-9999px';
    meassureElm.style.whiteSpace = 'pre';
    
    meassureElm.textContent = inputelm.value || '';
    
    // add the meassure element to the body
    document.body.appendChild(meassureElm);
    
    return meassureElm;
  }
  
  return function(){
    return createInputMeassureElm(this).offsetWidth;
  }
})();


// delegated event binding
document.body.addEventListener('input', onInputDelegate)

function onInputDelegate(e){
  if( e.target.classList.contains('autoSize') )
    e.target.style.width = getInputValueWidth.call(e.target) + 'px';
}
input{ 
  font-size:1.3em; 
  padding:5px; 
  margin-bottom: 1em;
}

input.type2{
  font-size: 2.5em;
  letter-spacing: 4px;
  font-style: italic;
}
<input class='autoSize' value="type something">
<br>
<input class='autoSize type2' value="here too">

vsync
fuente
0

Solo puede establecer el sizeatributo. Si está utilizando uno de los marcos reactivos, lo siguiente será suficiente:

<input size="{{ yourValue.length }}" [value]="yourValue" />

pero si está utilizando js puro, debe establecer controladores de eventos, como:

<input oninput="this.setAttribute('size', this.value.length)" />
akim lyubchenko
fuente