Regola la larghezza del campo di input al suo input


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

Questo è il mio codice e non funziona. Esiste un altro modo in HTML, JavaScript, PHP o CSS per impostare la larghezza minima?

Voglio un campo di input di testo con una larghezza che cambia dinamicamente, in modo che il campo di input fluisca attorno al suo contenuto. Ogni input ha un padding integrato di 2em, questo è il problema e il secondo problema è che min-widthnon funziona affatto sull'input.

Se imposto la larghezza più di quanto sia necessario rispetto all'intero programma è disordinato, ho bisogno della larghezza di 1px, più solo se è necessario.


Risposte:


96

Sembra che la tua aspettativa sia che lo stile venga applicato dinamicamente alla larghezza della casella di testo in base al contenuto della casella di testo. Se è così avrete bisogno di alcune js per funzionare sui contenuti della casella di testo che cambiano, qualcosa di simile a questo :

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

Nota: questa soluzione funziona solo quando ogni personaggio è esattamente 8pxlargo.


41
@Kerc & Tahbaza: sì, ma funzionerà solo se la larghezza di ogni personaggio è esattamente 8 pixel.
Marcel Korpel,

6
Sono d'accordo, Marcel (e il codice pubblicato non è qualcosa per cui posso davvero vedere un uso) ma mostra il comportamento desiderato. Sai come calcolare la larghezza effettiva del testo renderizzato tenendo conto di font, dimensioni, peso, crenatura, ecc.? In tal caso, ti preghiamo di condividere come troverei utile quel pezzo di codice a volte.
Tahbaza,

1
- Ho già pensato che fosse solo un esempio. Tuttavia, non è così difficile calcolare la larghezza dell'input. Dai un'occhiata alla mia risposta.
Marcel Korpel,

Le unità em sono la larghezza del carattere "m". Ciò sarebbe utile per calcolare la larghezza di una stringa. Ho visto problemi cross-browser con unità em applicate ad alcuni attributi, quindi provalo.
Archonic

7
hai dimenticato l' evento PASTE amico mio;) dovresti cambiarlo inonInput
vsync,

114

Nelle moderne versioni del browser, chè disponibile anche l' unità CSS . Per quanto ne so, è un'unità indipendente dal carattere, dove 1chequivale alla larghezza del carattere 0(zero) in un dato carattere.

Pertanto, una funzione semplice come la seguente potrebbe essere utilizzata come funzione di ridimensionamento:

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>

Quell'esempio ridimensionerebbe "elem" alla lunghezza del valore + 2 caratteri in più.


13
Sono sorpreso che questo commento non sia votato più in alto, perché è un'ottima soluzione e circa il 95% ( 1 ) dei browser lo supporta.
Husky,

8
Questa non è affatto una buona risposta, poiché la misurazione non è accurata e non tiene conto degli stili che potrebbero verificarsi inputsull'elemento, come font-style, letter-spacinge così via. Ho modificato la risposta con una demo dal vivo.
vsync,

5
Funziona alla grande se si utilizza un carattere a spaziatura fissa. Con altri tipi di carattere il tuo chilometraggio può variare in quanto utilizza apparentemente la larghezza del carattere del carattere 0.
Jilles van Gurp,

2
Questo è davvero fantastico. Anche se a volte nota che a volte non funziona / non funziona come mi aspettavo quando .si incontra un.
Rishav,

1
Funziona perfettamente se imposti il ​​ridimensionamento della casella sull'input su 'content-box'. In questo modo ignora l'imbottitura quando si imposta la dimensione.
Hypersapien

65

Per calcolare la larghezza dell'input corrente, dovrai incorporarlo in un spanelemento temporaneo , collegare quella cosa al DOM, ottenere la larghezza calcolata (in pixel) usando la scrollWidthproprietà e rimuovere di spannuovo. Ovviamente dovrai assicurarti che la stessa famiglia di caratteri, la dimensione del carattere, ecc., Sia usata inputsia spannell'elemento. Pertanto ho assegnato loro la stessa classe.

Ho collegato la funzione keyupall'evento, poiché keypressil carattere di input non è stato ancora aggiunto all'input value, in modo che risulti in una larghezza errata. Sfortunatamente, non so come sbarazzarmi dello scorrimento del campo di input (quando si aggiungono caratteri alla fine del campo); scorre, perché il personaggio viene aggiunto e mostrato prima adjustWidthOfInput()viene chiamato. E, come detto, non posso farlo al contrario perché poi avrai il valore del campo di input prima che venga inserito il carattere premuto. Proverò a risolvere questo problema in seguito.

A proposito, l'ho provato solo su Firefox (3.6.8), ma spero che tu capisca il 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>

Mi è piaciuta la tua risposta e l'ho persino implementata usando jQuery / Underscore: gist.github.com/3745941 . Tuttavia, potrei fare alcune ipotesi: (1) la larghezza di qualsiasi carattere non è superiore a 14px, (2) è accettabile che l'elemento di input si estenda di 14px oltre il valore dell'elemento. Ho collegato questo a un evento keydown e funziona alla grande!
Nathan,

11
Si dovrebbe aggiungere white-space: pre;in css in questo modo: .tmp-element{ visibility: hidden; white-space: pre;}. Altrimenti gli spazi bianchi vengono combinati e il calcolo della larghezza fallisce. <input>e si <span>comporta in modo diverso rispetto alla gestione <input>degli spazi bianchi , conserva gli spazi bianchi e <span>combina gli spazi bianchi sequenziali in uno se white-space: pre;non viene aggiunto.
Timo Kähkönen,

2
tmp.getBoundingClientRect().widthè meglio di tmp.scrollWidth, perché a volte restituisce 0
lisak

@lisak Grazie, ho modificato la mia risposta, ma ci sono già risposte migliori qui.
Marcel Korpel,

Meglio? Non lo direi. La risposta contrassegnata manca di precisione, altri (+ qui 1 e qui 2 ) usano jQuery - non a causa di React. La tela non può darti l'altezza del testo AFAIK. Idea: il problema con gli spazi potrebbe essere risolto anche con:.replace(/ /g, "&nbsp;")
Milan Jaros,

30

Ecco una modifica della risposta di Lyth che tiene conto:

  • cancellazione
  • Inizializzazione
  • segnaposto

Inoltre consente un numero qualsiasi di campi di input! Per vederlo in azione: http://jsfiddle.net/4Qsa8/

script:

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

Stile:

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


Ciao @Michael. Il tuo codice funziona alla grande ma ho un problema. Uno dei miei campi è un campo di completamento automatico di Google Place. E quando scelgo l'indirizzo giusto da un menu a discesa, la larghezza del campo di input non viene modificata in base alla lunghezza dell'indirizzo scelto. C'è una soluzione semplice per questo?
Maxence,

2
@Maxence ascoltare l' evento changeo inputsarebbe sufficiente
yarwest

Ho avuto problemi con il display dello span: nessuno stile poiché ha registrato lo span come 0 larghezza. Meglio usare il posizionamento assoluto con visibilità: nascosto per l'arco.
Jay

Ciao @yarwest, grazie per il suggerimento. Per caso sapresti come modificare lo script originale con questa configurazione? (la mia conoscenza di Js / jquery è molto limitata)
Maxence

21

Ecco una soluzione senza il carattere a spaziatura fissa necessaria, con solo un codice minuscolo di javascript , non è necessario calcolare gli stili calcolati e, persino supportare ime , supportare i testi 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>

Utilizzare span.textper adattare la larghezza del testo e lasciare che l'input abbia le stesse dimensioni con esso position: absolutenel contenitore. Copia il valore dell'input spanogni volta che cambia (puoi cambiare facilmente questo pezzo di codice in vanilla js). Quindi l'input "si adatterà" alla dimensione del suo contenuto.


18

PER UNO SGUARDO E SENTIRE NICER

È necessario utilizzare l'evento jQuery keypress () in combinazione con String.fromCharCode (e.which) per ottenere il carattere premuto. Quindi puoi calcolare quale sarà la tua larghezza . Perché? Perché sembrerà molto più sexy :)

Ecco un jsfiddle che si traduce in un buon comportamento rispetto alle soluzioni che usano l'evento keyup: http://jsfiddle.net/G4FKW/3/

Di seguito è riportato un JS vaniglia che ascolta l' inputevento di un <input>elemento e imposta un spanfratello con lo stesso valore di testo per misurarlo.

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>


1
Sembra carino, ma non tiene conto di Backspace ed Elimina.
Marcel Korpel

Sì, per questo è necessario un evento di keydown. È possibile aggiungere una gestione specifica per il backspace ed eliminare in questo modo (e.which === 46 per l'eliminazione, e.which === 8 per il backspace). Ma hai ancora bisogno dell'evento keypress per accedere a e.charCode per il resto.
Lyth

Se non stai supportando IE8, puoi utilizzare l'evento oninput invece di controllare e.which: developer.mozilla.org/en-US/docs/Web/Events/input
Frinsh,

1
Ho modificato la tua risposta per eliminare jQuery e utilizzare solo JS vaniglia. tenere presente che questa soluzione è tutt'altro che ottimale perché si desidera una soluzione generica che non prevede la codifica manuale di a spane css per essa.
vsync,

17

Questa è una risposta angolare specifica, ma ha funzionato per me ed è stata molto soddisfacente in termini di semplicità e facilità d'uso:

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

Si aggiorna automaticamente tramite le unità personaggio nella risposta di Jani .


3
Questo. È. Epico.
Daniel Flippance,

Sul serio. Magico.
DongBin Kim,

13

Ecco un modo alternativo per risolverlo usando un DIV e la proprietà 'contenteditable':

HTML:

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

CSS: (per dare al DIV alcune dimensioni e renderlo più facile da vedere)

.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 stai pianificando di utilizzarlo all'interno di un elemento FORM che prevedi di inviare, dovrai utilizzare Javascript / jQuery per catturare l'evento di invio in modo da poter analizzare il "valore" ( .innerHTMLo .html()rispettivamente) del DIV.


1
Questo merita più voti. È elegante e semplice (purché l'utilizzo di JS per le validazioni dei moduli non sia un problema per te).
Daniel Bonnell,

3
Ma non è un input!
Toni Michel Caubet,

8

Puoi impostare la larghezza di un input usando anche l' attributo size . La dimensione di un input determina la sua larghezza in caratteri.

Un input potrebbe regolare dinamicamente le sue dimensioni ascoltando eventi chiave.

Per esempio

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

JsFiddle qui


7

Si potrebbe fare qualcosa di simile a questo

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


Se si aumenta la dimensione al keyup, si comporterà un brutto comportamento. L'input deve aumentare le sue dimensioni appena prima che il personaggio vi entri per maggiore comfort.
Lyth,

5

Basta aggiungere altre risposte.

Ho notato che oggigiorno in alcuni browser il campo di input ha scrollWidth. Che significa:

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

dovrebbe funzionare bene. testato su Chrome, Firefox e Safari.

Per il supporto per l'eliminazione, è possibile aggiungere prima '= 0' e quindi regolare nuovamente.

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

3
Aggiungi qui anche il codice pertinente: il link potrebbe essere morto in futuro e quindi questo post è inutile.
Uooo,

3
Funziona benissimo, grazie! Non so perché questa risposta non abbia più voti. È di gran lunga la soluzione più semplice, meno ingegnosa (js).
Modulo

4

Ecco un semplice JS e un plugin jQuery che ho scritto che gestiranno il ridimensionamento di un elemento di input usando un canvas e la dimensione / famiglia del font per determinare la lunghezza effettiva della stringa quando viene renderizzato. (funziona solo con> IE9, Chrome, Safari, Firefox, Opera e la maggior parte dei principali browser che hanno implementato l'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: questo non gestirà trasformazioni di testo, interlinea e spaziatura tra lettere e probabilmente altre proprietà di modifica delle dimensioni del testo. Per gestire il set di proprietà di trasformazione del testo e regolare il valore del testo in modo che corrisponda a tale proprietà. Gli altri sono probabilmente abbastanza semplici. Lo implementerò se questo inizia a guadagnare un po 'di trazione ...


4

Vale la pena notare che un ridimensionamento gradevole può essere fatto quando il font è a spaziatura fissa, quindi possiamo ridimensionare perfettamente l' inputelemento usando ilch unità.

Anche in questo approccio possiamo aggiornare la larghezza del campo semplicemente aggiornando una variabile CSS ( proprietà personalizzata ) inputsull'evento e dovremmo anche occuparci dell'input già compilato DOMContentLoadedsull'evento

Demo Codepen


markup

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

Come variabile radice che impostiamo --size: 0: questa variabile conterrà la lunghezza dell'input e verrà moltiplicata per 1chall'interno calc()dell'espressione. Di default potremmo anche impostare una larghezza minima, ad es10ch

La parte Javascript legge la lunghezza del valore inserito e aggiorna la variabile --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);
});

ovviamente questo funziona ancora anche se non si utilizza il carattere a spaziatura fissa, ma in tal caso sarà necessario modificare la calc()formula moltiplicando la --sizevariabile per un altro valore (che è strettamente dipendente dal font-familye font-size) diverso da 1ch.


3

Questa risposta fornisce uno dei metodi più accurati per recuperare la larghezza del testo disponibile nel browser ed è più accurata della risposta accettata. Utilizza l'elemento canvas html5 e, diversamente dalle altre risposte, non aggiunge l'elemento al DOM e quindi evita eventuali problemi di riflusso causati dall'eccessiva aggiunta di elementi al DOM.

Maggiori informazioni sull'elemento Canvas qui in relazione alla larghezza del testo.

NOTA: secondo MDN le versioni abbreviate del getPropertyValue()metodo come font possono essere inaffidabili. Consiglierei di ottenere i valori singolarmente per migliorare la compatibilità. L'ho usato qui solo per la velocità.

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


2

Puoi farlo ancora più semplice in angularjs usando la direttiva integrata in stile ng .

Nel tuo html:

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

Nel tuo controller:

 $scope.testdata = "whatever";

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

Nel tuo css:

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

Regola charWidth in modo che corrisponda alla larghezza del carattere. Sembra essere 7 con una dimensione del carattere di 12 px;


3
È interessante e pratico da sapere, ma l'aggiunta di angularjs a un'app per ridimensionare dinamicamente un elemento di input è davvero grave, soprattutto quando OP ha chiesto soluzioni "HTML, JavaScript, PHP o CSS". Si potrebbe sostenere che anche jQuery sia eccessivo per questo, ma - a differenza di Angular - essere un toolkit di manipolazione DOM è fondamentale per lo scopo di jQuery.
vlasits

Come posso sapere la larghezza del personaggio che si sta digitando? Non è facile supporre che si tratti di un carattere mono.
Ethan,

1
Non è possibile richiedere un carattere a spaziatura fissa e non è necessario Angular. la risposta di Brendan fa sostanzialmente la stessa cosa.
Dan Dascalescu,

2

Se usi Bootstrap, potrebbe essere fatto molto facilmente:

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

Dovrai solo recuperare il contenuto del div e inserirlo in un input nascosto prima di inviare il modulo.


1

Penso che tu stia fraintendendo la proprietà CSS di larghezza minima . la larghezza minima viene generalmente utilizzata per definire una larghezza DOM minima in un layout fluido, come:

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

Ciò imposterebbe l'elemento di input su una larghezza minima di 200 pixel. In questo contesto, "px" sta per "pixel".

Ora, se stai cercando di verificare che il campo di input contenga almeno un carattere quando un utente lo invia, dovrai eseguire una convalida del modulo con JavaScript e PHP. Se questo è davvero ciò che stai tentando di fare, modificherò questa risposta e farò del mio meglio per aiutarti.


so cosa significa px e so che JavaScript ha una funzione per la larghezza minima ma non funziona per il testo di input.
Kerc

1
@Kerc: "javascript ha una funzione per la larghezza minima" - quale? Cosa intendi? - "non funziona" non è mai una buona descrizione di un problema. Cerca di elaborare il comportamento previsto.
Marcel Korpel,

Hai mai provato il mio esempio, di quello che vedi che non è 1 px e il tuo non lo è anche. Non funzionerà, non importa se lo scrivo in html, css
Kerc

Forse c'è una funzione php per questo, qualcuno lo sa?
Kerc,

Ho provato il tuo esempio, ma ho pensato che un campo di input largo 1 pixel non fosse quello che stavi cercando. Se lo è, prova<input type="text" value="1" style="width:1px;" />
peterjmag

1

Mi è piaciuta molto la risposta di Lyth , ma volevo anche che:

  1. Gestisci backspace ed elimina
  2. Non è necessario aggiungere manualmente un tag adiacente.
  3. Applicare una larghezza minima.
  4. Si applica automaticamente agli elementi con una classe specifica

Ho adattato il suo JSFiddle e ho pensato a questo . Un miglioramento non presente in questo violino sarebbe l'uso di qualcosa come il parser CSS jQuery per leggere effettivamente la larghezza iniziale dalla regola input.textbox-autosize, e usarla come minWidth. Bene, sto semplicemente usando un attributo su, che rende una demo compatta ma non è l'ideale. in quanto richiede un attributo aggiuntivo su ciascun input. Potresti anche voler inserire minWidth come 100 proprio nel 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
});

1

Meglio è onvalue:

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

Implica anche incollare, trascinare e rilasciare, ecc.


1

Ecco i miei 2 centesimi. Crea un div invisibile vuoto. Riempilo con il contenuto di input e riporta la larghezza nel campo di input. Abbina gli stili di testo tra ciascuna casella.

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


1

Abbastanza semplice:

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

Dove N è un numero (2 nell'esempio, 17 su qualcosa che sto sviluppando) che viene determinato sperimentalmente.

Sottraendo N si evita che questo strano spazio estraneo si accumuli molto prima che il testo raggiunga la fine della casella di testo.

Confrontare. Presta attenzione a come le dimensioni cambiano anche dopo solo il primo carattere.

<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";'>


Non ho ancora testato a lungo con questo, ma si può solo cambiare oninput='this.style.width = (this.scrollWidth-2) + "px";'per oninput='this.style.width = 0; this.style.width = this.scrollWidth + "px";'sbarazzarsi dello spazio accumulare
MaxCloutier

0

Passo solo un po 'di tempo a capire come farlo.
In realtà il modo più semplice che ho trovato è spostare il valore di input sull'intervallo appena prima dell'input, mantenendo la larghezza del simbolo di input 1. Anche se non posso essere sicuro che si adatti alle tue necessità iniziali.
Forse è un po 'di codice extra, ma nell'applicazione basata su reatt + flusso è una soluzione abbastanza naturale.


0

Sulla base della risposta di Michael, ho creato la mia versione di questo usando jQuery. Penso che sia una versione più pulita / più breve della maggior parte delle risposte qui e sembra riuscire a fare il lavoro.

Sto facendo la stessa cosa della maggior parte delle persone qui usando un intervallo per scrivere il testo di input e poi ottenere la larghezza. Quindi sto impostando la larghezza quando le azioni keyupeblur sono chiamati.

Ecco un codice funzionante . Questo codice mostra come può essere usato con più campi di input.

Struttura 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 funzione sopra ottiene il valore di input, taglia gli spazi extra e imposta il testo nell'intervallo per ottenere la larghezza. Se non c'è testo, ottiene invece il segnaposto e lo inserisce invece nell'intervallo. Una volta inserito il testo nell'intervallo, imposta la larghezza dell'input. La + 5larghezza è perché senza che l'input viene tagliato un po 'nel browser 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);
});

Se questo potrebbe essere migliorato, per favore fatemi sapere in quanto questa è la soluzione più pulita che potrei trovare.


0

Perché non usare 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;
}

questo codice è stato introdotto da @Iain Todd e ho pensato di condividerlo


Non è solo CSS. È solo un altro metodo js. Uno interessante.
vatavale,

0

Un modo generico a prova di proiettile deve:

  1. Prendi in considerazione tutti i possibili stili inputdell'elemento misurato
  2. Essere in grado di applicare la misurazione su qualsiasi input senza modificare il codice HTML o

Demo Codepen

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


0

Puoi semplicemente impostare l' sizeattributo. Se si utilizza uno dei framework reattivi, sarà sufficiente quanto segue:

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

ma se stai usando js puro, dovresti impostare i gestori di eventi, come:

<input oninput="this.setAttribute('size', this.value.length)" />
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.