Ajustar a largura do campo de entrada à sua entrada

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

Este é o meu código e não está funcionando. Existe alguma outra maneira em HTML, JavaScript, PHP ou CSS para definir a largura mínima?

Eu quero um campo de entrada de texto com uma largura que muda dinamicamente, para que o campo de entrada flua em torno de seu conteúdo. Toda entrada possui um preenchimento interno 2em, esse é o problema e o segundo problema é que min-widthnão está trabalhando na entrada.

Se eu definir a largura mais do que o necessário, todo o programa será confuso, precisarei da largura de 1 px, mais apenas se for necessário.

Kerc
fonte

Respostas:

96

Parece que sua expectativa é que o estilo seja aplicado dinamicamente à largura da caixa de texto com base no conteúdo da caixa de texto. Nesse caso, você precisará de alguns js para executar a alteração do conteúdo da caixa de texto, algo como isto :

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

Nota: esta solução funciona apenas quando cada caractere é exatamente 8pxlargo.

Tahbaza
fonte
41
@Kerc & Tahbaza: sim, mas isso só funcionará se a largura de cada caractere for exatamente 8 pixels.
Marcel Korpel
6
Concordo, Marcel (e o código publicado não é algo que eu possa ver realmente útil), mas exibe o comportamento desejado. Você sabe como calcular a largura real do texto renderizado, levando em consideração fonte, tamanho, peso, kerning etc.? Em caso afirmativo, compartilhe, pois eu consideraria útil esse código ocasionalmente.
Tahbaza
1
- Eu já pensei que era apenas um exemplo. Não é tão difícil calcular a largura da entrada, no entanto. Dê uma olhada na minha resposta.
Marcel Korpel 03/08/19
unidades em são a largura do caractere "m". Isso seria útil para calcular a largura de uma string. Já vi problemas entre navegadores com as unidades em aplicadas a alguns atributos, portanto, teste-o.
precisa saber é o seguinte
7
você esqueceu o evento PASTE meu amigo;) você deve alterá-lo paraonInput
vsync
114

Nas versões modernas do navegador, a unidade CSS chtambém está disponível. No meu entender, é uma unidade independente de fonte, onde 1ché igual à largura do caractere 0(zero) em qualquer fonte.

Assim, algo tão simples como o seguinte pode ser usado como função de redimensionamento:

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>

Esse exemplo redimensionaria "elem" para o comprimento do valor + 2 caracteres extras.

Jani Jalkala
fonte
13
Estou surpreso que este comentário não tenha sido votado mais alto, porque é uma ótima solução e cerca de 95% ( 1 ) dos navegadores suportam isso.
Husky
8
Esta não é uma boa resposta em tudo, desde a medição não é precisa e não leva em conta os estilos que possam ocorrer no inputelemento, tais como font-style, letter-spacinge assim por diante. Editei a resposta com uma demonstração ao vivo.
vsync 16/05
5
Funciona muito bem se você usar uma fonte monoespaçada. Com outras fontes, sua milhagem pode variar, pois aparentemente usa a largura do caractere 0.
Jilles van Gurp
2
Isso é realmente ótimo. Embora observe que às vezes ocorre um erro / não funciona como eu esperava quando um .é encontrado.
Rishav 14/08/19
1
Isso funciona perfeitamente se você definir o tamanho da caixa na entrada como 'caixa de conteúdo'. Dessa forma, ele ignora o preenchimento quando você define o tamanho.
Hypersapien
65

Para calcular a largura da entrada atual, você precisará incorporá-la em um arquivo temporário. span elemento , anexar essa coisa ao DOM, obter a largura calculada (em pixels) usando a scrollWidthpropriedade e remover spannovamente. Obviamente, você precisará garantir que a mesma família de fontes, tamanho de fonte etc. seja usada inputtanto no spanelemento quanto no elemento. Portanto, eu atribuí a mesma classe a eles.

Anexei a função ao keyupevento, como emkeypress o caractere de entrada ainda não foi adicionado à entrada value, o que resultará na largura incorreta. Infelizmente, não sei como me livrar da rolagem do campo de entrada (ao adicionar caracteres ao final do campo); rola, porque o caractere é adicionado e mostrado antes adjustWidthOfInput()é chamado. E, como dito, não posso fazer isso de outra maneira, porque você terá o valor do campo de entrada antes que o caractere pressionado seja inserido. Tentarei resolver esse problema mais tarde.

BTW, eu só testei isso no Firefox (3.6.8), mas você entenderá, espero.

<!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
fonte
Gostei da sua resposta e até a implementei usando o jQuery / Underscore: gist.github.com/3745941 . No entanto, eu poderia fazer certas suposições: (1) a largura de qualquer caractere não ultrapassa 14 px, (2) é aceitável que o elemento de entrada estenda 14 px além do valor do elemento. Eu tenho isso anexado a um evento keydown e está funcionando muito bem!
Nathan
11
Você deve adicionar white-space: pre;em css desta forma: .tmp-element{ visibility: hidden; white-space: pre;}. Caso contrário, os espaços em branco são combinados e o cálculo da largura falha. <input>e <span>se comporta de maneira diferente em relação à manipulação <input>de espaços em branco , retém espaços em branco e <span>combina espaços em branco seqüenciais em um, se white-space: pre;não for adicionado.
Timo Kähkönen
2
tmp.getBoundingClientRect().widthé melhor que tmp.scrollWidth, porque isso às vezes retorna 0
lisak 6/15
@lisak Obrigado, eu ajustei minha resposta, mas já existem respostas melhores aqui.
Marcel Korpel
Melhor? Eu não diria isso. A resposta marcada não tem precisão, outras (+ aqui 1 e aqui 2 ) usam jQuery - não uso por causa do React. A tela não pode fornecer a altura do texto AFAIK. Idéia: o problema com espaços também pode ser resolvido com:.replace(/ /g, "&nbsp;")
Milan Jaros
30

Aqui está uma modificação da resposta de Lyth que leva em consideração:

  • Eliminação
  • Inicialização
  • Espaços reservados

Também permite qualquer número de campos de entrada! Para vê-lo em ação: http://jsfiddle.net/4Qsa8/

Roteiro:

$(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>

Michael
fonte
Olá Michael. Seu código funciona muito bem, mas eu tenho um problema. Um dos meus campos é um campo de preenchimento automático do Google Place. E quando eu escolho o endereço certo em um menu suspenso, a largura do campo de entrada não é alterada de acordo com o tamanho do endereço escolhido. Existe uma solução simples para isso?
Maxence
2
@Maxence ouvindo o changeou inputevento seria suficiente
yarwest
Eu tive problemas com a tela do span: nenhum estilo, pois ele registrou o span como tendo 0 de largura. Melhor usar posicionamento absoluto com visibilidade: oculto durante o período.
Jayt 21/08/19
Olá @yarwest, obrigado pela dica. Por acaso, você saberia como ajustar o script original com essa configuração? (meu conhecimento em JS / jQuery é muito limitada)
Maxence
21

Aqui está uma solução sem a fonte monoespaçada necessária, com apenas um código de peça muito pequeno de javascript , não precisa calcular estilos computados e, mesmo suportando , suporta 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 o span.text para ajustar a largura do texto e deixe a entrada ter o mesmo tamanho com ela position: absoluteno contêiner. Copie o valor da entrada para spantoda vez que ela for alterada (você pode alterar esse trecho de código para vanilla js facilmente). Portanto, a entrada apenas "encaixa" no tamanho do seu conteúdo.

tsh
fonte
18

PARA UM OLHAR E SENTIR MAIS AGRADÁVEIS

Você deve usar o evento jQuery keypress () em combinação com String.fromCharCode (e.which) para obter o caractere pressionado. Portanto, você pode calcular qual será sua largura . Por quê? Porque ficará muito mais sexy :)

Aqui está um jsfiddle que resulta em um bom comportamento em comparação com soluções usando o evento keyup: http://jsfiddle.net/G4FKW/3/

Abaixo está uma JS baunilha que escuta o inputevento de um <input>elemento e define um spanirmão para ter o mesmo valor de texto para medi-lo.

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
fonte
1
Parece bom, mas não leva em consideração Backspace e Delete.
Marcel Korpel #
Sim, para isso, você precisa do evento de pressionamento de tecla. Você pode adicionar manipulação específica para backspace e excluir ao fazê-lo (e.which === 46 para exclusão e e.which === 8 para backspace). Mas você ainda precisa do evento de pressionamento de tecla para ter acesso ao e.charCode para o restante.
Lyth
Se você não está apoiando IE8 você pode usar o oninput evento em vez de e.which verificação: developer.mozilla.org/en-US/docs/Web/Events/input
Frinsh
1
Eu editei sua resposta para eliminar o jQuery e use apenas o vanilla JS. lembre-se de que esta solução está longe de ser ideal porque você deseja uma solução genérica que não envolva a codificação manual de a spane css para ela.
vsync 16/05
17

Esta é uma resposta específica da Angular, mas funcionou para mim e tem sido muito satisfatória em termos de simplicidade e facilidade de uso:

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

Ele é atualizado automaticamente através das unidades de caracteres na resposta de Jani .

Chris Vandevelde
fonte
3
Este. É. Épico.
Daniel Flippance
Seriamente. Mágico.
DongBin Kim
13

Aqui está uma maneira alternativa de resolver isso usando uma DIV e a propriedade 'contenteditable':

HTML:

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

CSS: (para dar algumas dimensões ao DIV e facilitar a visualização)

.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: Se você planeja usá-lo dentro de um elemento FORM que planeja enviar, precisará usar Javascript / jQuery para capturar o evento de envio, para poder analisar o 'valor' ( .innerHTMLou .html()respectivamente) do DIV.

logic8
fonte
1
Isso merece mais votos. É elegante e simples (desde que o uso do JS para validações de formulários não seja um problema para você).
precisa
3
Mas não é uma entrada!
Toni Michel Caubet
8

Você pode definir a largura de uma entrada usando o atributo size também. O tamanho de uma entrada determina sua largura em caracteres.

Uma entrada pode ajustar dinamicamente seu tamanho, ouvindo os principais eventos.

Por exemplo

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

JsFiddle aqui

brendan
fonte
7

Você poderia fazer algo como isso

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

O que outras pessoas estão dizendo

O que outras pessoas estão dizendo

Laços
fonte
Se você aumentar o tamanho do keyup, isso resultará em um comportamento feio. A entrada precisa aumentar seu tamanho antes que o personagem entre nela para obter mais conforto.
Lyth
5

Apenas adicionando outras respostas.

Notei que hoje em alguns navegadores o campo de entrada tem uma scrollWidth. Que significa:

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

deve funcionar bem. testado em cromo, firefox e safari.

Para suporte à exclusão, você pode adicionar '= 0' primeiro e depois reajustar.

this.style.width = 0; this.style.width = this.scrollWidth + 'px';
guy mograbi
fonte
3
Adicione também o código relevante aqui - o link pode estar morto no futuro e, em seguida, este post é inútil.
Uooo
3
Isso funciona muito bem, obrigado! Não sei por que essa resposta não tem mais votos positivos. É de longe a solução mais simples e menos artificial (js).
Formulário
4

Aqui está um JS simples e um plugin jQuery que escrevi que manipularão o redimensionamento de um elemento de entrada usando uma tela e o tamanho / família da fonte para determinar o tamanho real da string quando renderizada. (funciona apenas em> IE9, chrome, safari, firefox, opera e na maioria dos outros principais navegadores que implementaram o 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'));

Plugin 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: isso não trata de transformações de texto, espaçamento entre linhas e espaçamento entre letras e provavelmente outras propriedades de alteração de tamanho de texto. Para manipular o conjunto de propriedades de transformação de texto e ajustar o valor do texto para corresponder a essa propriedade. Os outros são provavelmente bastante diretos. Vou implementar se isso começar a ganhar alguma tração ...

newms87
fonte
4

Vale a pena notar que um redimensionamento bonito pode ser feito quando a fonte é monoespaçada, para que possamos redimensionar perfeitamente o inputelemento usando a chunidade.

Também nesta abordagem, podemos atualizar a largura do campo apenas atualizando uma variável CSS ( propriedade personalizada ) no inputevento e também devemos cuidar da entrada já preenchida no DOMContentLoadedevento

Codepen demo


Marcação

<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 variável raiz, definimos --size: 0: essa variável conterá o comprimento da entrada e será multiplicada por 1chdentro da calc()expressão. Por padrão, também podemos definir uma largura mínima, por exemplo10ch

A parte Javascript lê o comprimento do valor inserido e atualiza a variável --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);
});

é claro que isso ainda funciona mesmo se você não usar fonte monoespaçada, mas, nesse caso, você terá que mudar a calc()fórmula multiplicando a --sizevariável por um outro valor (que é estritamente dependente da font-familye font-size) diferente 1ch.

Fabrizio Calderan
fonte
3

Esta resposta fornece um dos métodos mais precisos para recuperar a largura do texto disponível no navegador e é mais precisa que a resposta aceita. Ele usa o elemento canvas html5 e, diferentemente de outras respostas, não adiciona o elemento ao DOM e, assim, evita problemas de refluxo causados ​​pela adição excessiva de elementos ao DOM.

Leia mais sobre o elemento Canvas aqui em relação à largura do texto.

NOTA: De acordo com o MDN, as versões abreviadas do getPropertyValue()método, como fonte, podem não ser confiáveis. Eu recomendo obter os valores individualmente para melhorar a compatibilidade. Eu só usei aqui para velocidade.

/**
 * 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
fonte
2

Você pode fazer isso de maneira ainda mais simples em angularjs usando a diretiva de estilo ng incorporada .

No seu html:

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

No seu controlador:

 $scope.testdata = "whatever";

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

Em seu css:

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

Ajuste o charWidth para corresponder à largura da sua fonte. Parece ser 7 em um tamanho de fonte de 12px;

michieljoris
fonte
3
Isso é interessante e útil, mas adicionar angularjs a um aplicativo para redimensionar dinamicamente um elemento de entrada é um sério exagero, especialmente quando o OP solicita soluções "HTML, JavaScript, PHP ou CSS". Alguém poderia argumentar que o jQuery é um exagero para isso também, mas - ao contrário do Angular - ser um kit de ferramentas de manipulação de DOM é essencial para o objetivo do jQuery.
precisa saber é o seguinte
Como devo saber a largura do caractere sendo digitado? Não é fácil supor que é uma fonte de tamanho mono.
Ethan
1
Você não pode exigir uma fonte monoespaçada e não há necessidade de Angular. a resposta de brendan faz basicamente o mesmo.
Dan Dascalescu
2

Se você usa o Bootstrap, isso pode ser feito com muita facilidade:

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

Você só precisará buscar o conteúdo de div e colocá-lo em uma entrada oculta antes de enviar o formulário.

Alexey Kosov
fonte
1

Eu acho que você está interpretando mal a propriedade CSS de largura mínima . largura mínima é geralmente usada para definir uma largura DOM mínima em um layout de fluido, como:

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

Isso definiria o elemento de entrada com uma largura mínima de 200 pixels. Nesse contexto, "px" significa "pixels".

Agora, se você estiver tentando verificar se o campo de entrada contém pelo menos um caractere quando um usuário o envia, será necessário validar o formulário com JavaScript e PHP. Se é isso que você está tentando fazer, editarei esta resposta e farei o possível para ajudá-lo.

peterjmag
fonte
Eu sei o que significa px e eu sei que o javascript tem uma função para largura mínima, mas não está funcionando para entrada de texto.
Kerc
1
@ Kerc: “javascript tem uma função para largura mínima” - qual? O que você quer dizer? - "não está funcionando" nunca é uma boa descrição de um problema. Tente elaborar o comportamento pretendido.
Marcel Korpel
Você tentou o meu exemplo? Você vê que ele não tem 1 px e o seu também não. Isso não vai funcionar, não importa se eu escrevê-lo em html, css
Kerc
Talvez exista uma função php para isso, alguém sabe?
Kerc
Tentei o seu exemplo, mas presumi que um campo de entrada com 1 pixel de largura não era o que você estava procurando. Se estiver, tente<input type="text" value="1" style="width:1px;" />
peterjmag
1

Gostei muito da resposta de Lyth , mas também queria:

  1. Manipular backspace e excluir
  2. Não é necessário adicionar manualmente uma tag adjacente.
  3. Aplique uma largura mínima.
  4. Ser aplicado automaticamente a elementos com uma classe específica

Eu adaptei o JSFiddle dele e criei isso . Uma melhoria não presente neste violino seria usar algo como o Analisador CSS do jQuery para realmente ler a largura inicial da regra CC0box-autosize e usá-la como minWidth. Certo, estou simplesmente usando um atributo no, o que contribui para uma demonstração compacta, mas não é o ideal. pois requer um atributo extra em cada entrada. Você também pode colocar apenas a minWidth como 100 no 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
fonte
1

Melhor é onvalue:

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

Também envolve colar, arrastar e soltar, etc.

Łukasz Polowczyk
fonte
1

Aqui estão os meus 2 centavos. Crie uma div invisível vazia. Preencha-o com o conteúdo de entrada e retorne a largura ao campo de entrada. Corresponda os estilos de texto entre cada caixa.

$(".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
fonte
1

Bem simples:

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

Onde N é algum número (2 no exemplo, 17 em algo que estou desenvolvendo) que é determinado experimentalmente.

Subtrair N impede que esse espaço estranho e acumulado se acumule muito antes do texto chegar ao fim da caixa de texto.

Comparar. Preste muita atenção em como o tamanho muda após apenas o primeiro caractere.

<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
fonte
Eu não testei extensivamente com isso, mas você poderia apenas mudar oninput='this.style.width = (this.scrollWidth-2) + "px";'por oninput='this.style.width = 0; this.style.width = this.scrollWidth + "px";'se livrar do espaço acumulando
MaxCloutier
0

Eu passo algum tempo tentando descobrir como fazê-lo.
Na verdade, a maneira mais simples que encontrei é mover o valor de entrada para abranger pouco antes da entrada, mantendo a largura do símbolo da entrada 1. Embora eu não tenha certeza de que se encaixa na sua necessidade inicial.
Talvez seja algum código extra, mas na aplicação baseada em react + flux é uma solução bastante natural.

freele
fonte
0

Baseado na resposta de Michael, criei minha própria versão usando o jQuery. Eu acho que é uma versão mais limpa / mais curta da maioria das respostas aqui e parece fazer o trabalho.

Estou fazendo a mesma coisa que a maioria das pessoas aqui, usando um intervalo para escrever o texto de entrada e obtendo a largura. Então, eu estou definindo a largura quando as ações keyupeblur são chamadas.

Aqui está um código de trabalho . Este código mostra como isso pode ser usado com vários campos de entrada.

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

A função acima obtém o valor das entradas, apara os espaços extras e define o texto no intervalo para obter a largura. Se não houver texto, ele obtém o espaço reservado e o insere no intervalo. Depois de inserir o texto no intervalo, ele define a largura da entrada. A + 5largura é porque, sem isso, a entrada é cortada um pouquinho no Navegador de Borda.

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

Se isso puder ser melhorado, informe-me, pois esta é a solução mais limpa que eu poderia encontrar.

Mateus
fonte
0

Por que não usar apenas 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;
}

esse código foi introduzido por @Iain Todd e achei que deveria compartilhá-lo

Milad
fonte
Não é apenas CSS. É apenas outro método js. Interessante.
vatavale
0

Uma maneira genérica e à prova de balas deve:

  1. Leve em consideração todos os estilos possíveis do inputelemento medido
  2. Poder aplicar a medida em qualquer entrada sem modificar o HTML ou

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
fonte
0

Você pode apenas definir o sizeatributo. Se você estiver usando uma das estruturas reativas, o seguinte será suficiente:

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

mas se você estiver usando js puros, defina manipuladores de eventos, como:

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