¿Hay alguna manera de escalar el ancho de un <input type="text">
al ancho del valor real?
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" />
Respuestas:
Puede hacer esto de la manera más fácil configurando el
size
atributo a la longitud del contenido de entrada:function resizeInput() { $(this).attr('size', $(this).val().length); } $('input[type="text"]') // event handler .keyup(resizeInput) // resize on page load .each(resizeInput);
Ver: http://jsfiddle.net/nrabinowitz/NvynC/
Esto parece agregar algo de relleno a la derecha que sospecho que depende del navegador. Si desea que esté realmente ajustado a la entrada, puede usar una técnica como la que describo en esta respuesta relacionada , usando jQuery para calcular el tamaño de píxel de su texto.
fuente
Courier New
fuente para el cuadro de texto, porque el ancho de todos los caracteres en esta fuente es igual. ( jsfiddle.net/NabiKAZ/NvynC/745 )UNA SOLUCIÓN SIMPLE PERO PERFECTA DE PÍXELES
He visto varias formas de hacer esto, pero calcular el ancho de las fuentes no siempre es 100% exacto, es solo una estimación.
Me las arreglé para crear una forma perfecta de píxeles de ajustar el ancho de entrada al tener un marcador de posición oculto para medir.
jQuery (recomendado)
$(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>
JavaScript puro
No pude determinar cómo jQuery calcula el ancho de los elementos ocultos, por lo que se requirió un ligero ajuste en css para adaptarse a esta solución.
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>
fuente
hide
debe tener el mismo relleno), laheight: 0;
parte no funcionará correctamente. Una solución para este problema sería usarposition: fixed; top: -100vh;
, también puede agregaropacity: 0;
solo para estar seguro.Si por alguna razón las otras soluciones no funcionan para usted, puede usar un intervalo contenteditable en lugar de un elemento de entrada.
<span contenteditable="true">dummy text</span>
Tenga en cuenta que esto es más un truco y tiene el grave inconveniente de permitir una entrada HTML totalmente no higienizada, como permitir que los usuarios ingresen (y peguen) saltos de línea, enlaces y otro HTML.
Por lo tanto , probablemente no debería usar esta solución a menos que esté desinfectando cuidadosamente la entrada ...
Actualización : probablemente desee utilizar la solución de DreamTeK a continuación .
fuente
contenteditable
es para configurar un editor de texto WYSIWYG de texto enriquecido. No para cambiar el tamaño de las entradas.Editar : el complemento ahora funciona con caracteres de espacio en blanco finales. Gracias por señalarlo @JavaSpyder
Dado que la mayoría de las otras respuestas no coincidían con lo que necesitaba (o simplemente no funcionó en absoluto), modifiqué la respuesta de Adrian B en un complemento de jQuery adecuado que da como resultado una escala de entrada perfecta de píxeles sin necesidad de que cambie su css o html.
Ejemplo: https://jsfiddle.net/587aapc2/
Uso:
$("input").autoresize({padding: 20, minWidth: 20, maxWidth: 300});
Enchufar:
//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});
fuente
font
es una forma abreviada de CSS (extrañamente, FF no puede manejarlo ). Puede solucionar este problema mediante la definición de la primera función:var _this_font = [this.css('font-style'), this.css('font-variant'), this.css('font-weight'), 'normal', this.css('font-size') + ' / ' + this.css('line-height'), this.css('font-family')].join(' ');
. Entonces cambiathis.css('font')
a ser_this_font
.Tengo un complemento jQuery en GitHub: https://github.com/MartinF/jQuery.Autosize.Input
Refleja el valor de la entrada, calcula el ancho y lo usa para configurar el ancho de la entrada.
Puedes ver un ejemplo en vivo aquí: http://jsfiddle.net/mJMpw/2175/
Ejemplo de cómo usarlo (porque se necesita algo de código al publicar un enlace 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; }
Simplemente use css para establecer el ancho mínimo / máximo y use una transición en el ancho si desea un efecto agradable.
Puede especificar el espacio / distancia hasta el final como el valor en notación json para el atributo data-autosize-input en el elemento de entrada.
Por supuesto, también puede inicializarlo usando jQuery
$("selector").autosizeInput();
fuente
Ya hay muchas buenas respuestas aquí. Por diversión, implementé esta solución a continuación, basándome en las otras respuestas y en mis propias ideas.
<input class="adjust">
El elemento de entrada se ajusta con precisión de píxeles y se puede definir un desplazamiento adicional.
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, ' ')); // 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);
El ajuste se suaviza con una transición CSS.
.adjust { transition: width .15s; }
Aquí está el violín . Espero que esto pueda ayudar a otros que buscan una solución limpia.
fuente
En lugar de intentar crear un div y medir su ancho, creo que es más confiable medir el ancho directamente usando un elemento de lienzo que es más preciso.
function measureTextWidth(txt, font) { var element = document.createElement('canvas'); var context = element.getContext("2d"); context.font = font; return context.measureText(txt).width; }
Ahora puede usar esto para medir cuál debería ser el ancho de algún elemento de entrada en cualquier momento haciendo esto:
// 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);
Esto devuelve un número (posiblemente punto flotante). Si desea tener en cuenta el relleno, puede intentar esto:
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";
fuente
Puede resolver este problema como aquí :) 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');
fuente
Desafortunadamente, el
size
atributo no funcionará muy bien. Habrá espacio adicional y muy poco espacio a veces, dependiendo de cómo esté configurada la fuente. (mira el ejemplo)Si desea que esto funcione bien, intente observar los cambios en la entrada y luego cambie su tamaño. Probablemente desee configurarlo en la entrada
scrollWidth
. También deberíamos tener en cuenta el tamaño de la caja.En el siguiente ejemplo, establezco el valor
size
de la entrada en 1 para evitar que tenga unscrollWidth
ancho mayor que nuestro ancho inicial (establecido manualmente con 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>
Creo que esto debería funcionar incluso en IE6, pero no confíe en mi palabra.
Dependiendo de su caso de uso, es posible que deba vincular la función de ajuste a otros eventos. Por ejemplo, cambiar el valor de una entrada mediante programación, o cambiar la
display
propiedad de estilo del elemento denone
(dóndescrollWidth === 0
) ablock
oinline-block
, etc.fuente
Encontré otra solución para este problema que no involucra a JS. En HTML acabo de poner algo como:
<div> <input class="input" value={someValue} /> <div class="ghost-input">someValue</div> </div>
Todo lo que se necesita es configurar la visibilidad: oculta en la entrada fantasma y el ancho: 100% en la entrada misma. Funciona porque la entrada se escala al 100% de su contenedor, cuyo ancho es calculado por el propio navegador (basado en el mismo texto).
Si agrega algo de relleno y borde al campo de entrada, debe ajustar su clase de entrada fantasma en consecuencia (o usar calc () en la clase de entrada).
fuente
Mi complemento jQuery funciona para mí:
Uso:
$('form input[type="text"]').autoFit({ });
Código fuente de
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']);
fuente
Los elementos de entrada se comportan de manera diferente a otros elementos, que harían casi lo que usted desea si se los da
float: left
(consulte http://jsfiddle.net/hEvYj/5/ ). No creo que sea posible sin calcularlo de alguna manera con JavaScript (es decir, agregue 5px al ancho por letra en el cuadro).fuente
La solución del usuario nrabinowitz funciona muy bien, pero uso el
keypress
evento en lugar dekeyup
. Eso reduce la latencia si el usuario escribe lentamente.fuente
oninput
(oonpropertychange
para IE heredado) es el evento correcto, ya que responden a cosas como pegar con un clic derecho o seleccionar "Archivo -> pegar" en la barra de menú del navegadorAquí está mi modificación de la solución de nrabinowitz . No usé la propiedad de tamaño , porque no es perfecta con fuentes proporcionales como señaló @Mark. Mi solución coloca un elemento después de su entrada y obtiene el ancho contado por el navegador (usando jQuery).
Aunque no lo pruebo, supongo que funcionará solo si se heredan todas las propiedades CSS que afectan a la fuente.
El ancho de entrada cambia en el evento focusout , que funciona mejor para mí. Pero también puede usar tecla arriba / pulsación de tecla para cambiar el ancho de entrada al escribir.
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);
fuente
Usando canvas podríamos calcular el ancho de los elementos:
function getTextWidth(text, fontSize, fontName) { let canvas = document.createElement('canvas'); let context = canvas.getContext('2d'); context.font = fontSize + fontName; return context.measureText(text).width; }
y utilícelo en el evento elegido:
function onChange(e) { let width = getTextWidth(this.value, $(this).css('font-size'), $(this).css('font-family')); $(this.input).css('width', width); }
fuente
Prueba la solución 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); });
fuente
Resolví el ancho creando un lienzo y calculando su tamaño. Es importante que el valor de entrada y el lienzo compartan las mismas características de fuente (familia, tamaño, peso ...)
import calculateTextWidth from "calculate-text-width"; /* requires two props "value" and "font" - defaultFont: normal 500 14px sans-serif */ const defaultText = 'calculate my width' const textFont = 'normal 500 14px sans-serif' const calculatedWidth = calculateTextWidth(defaultText, textFont) console.log(calculatedWidth) // 114.37890625
GitHub: https://github.com/ozluy/calculate-text-width CodeSandbox: https://codesandbox.io/s/calculate-text-width-okr46
fuente