Passen Sie die Breite des Eingabefelds an seine Eingabe an

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

Dies ist mein Code und es funktioniert nicht. Gibt es eine andere Möglichkeit in HTML, JavaScript, PHP oder CSS, die Mindestbreite festzulegen?

Ich möchte ein Texteingabefeld mit einer sich dynamisch ändernden Breite, damit das Eingabefeld um seinen Inhalt herum fließt. Jeder Eingang hat eine eingebaute Auffüllung von 2em, das ist das Problem und das zweite Problem ist, dass überhaupt min-widthnicht an Eingaben gearbeitet wird.

Wenn ich die Breite mehr einstelle, als benötigt wird, als das gesamte Programm unordentlich ist, brauche ich die Breite von 1 Pixel, mehr nur, wenn es benötigt wird.

Kerc
quelle

Antworten:

96

Es hört sich so an, als ob Sie erwarten, dass der Stil basierend auf dem Inhalt des Textfelds dynamisch auf die Breite des Textfelds angewendet wird. Wenn ja einige js benötigen auf Textbox Inhalt zu verändern, so etwas wie laufen diese :

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

Hinweis: Diese Lösung funktioniert nur, wenn jedes Zeichen genau 8pxbreit ist.

Tahbaza
quelle
41
@Kerc & Tahbaza: Ja, aber das funktioniert nur, wenn die Breite jedes Zeichens genau 8 Pixel beträgt.
Marcel Korpel
6
Ich stimme zu, Marcel (und der veröffentlichte Code ist nichts, wofür ich wirklich eine Verwendung sehen kann), aber er zeigt das gewünschte Verhalten. Wissen Sie, wie Sie die tatsächliche Breite des gerenderten Texts unter Berücksichtigung von Schriftart, Größe, Gewicht, Kerning usw. berechnen können? Wenn ja, teilen Sie uns dies bitte mit, da ich diesen Code gelegentlich nützlich finden würde.
Tahbaza
1
- Ich dachte schon, dass es nur ein Beispiel ist. Es ist jedoch nicht so schwierig, die Breite der Eingabe zu berechnen. Schau dir meine Antwort an.
Marcel Korpel
em Einheiten sind die Breite des Zeichens "m". Dies wäre nützlich, um die Breite einer Zeichenfolge zu berechnen. Ich habe browserübergreifende Probleme mit em-Einheiten gesehen, die auf einige Attribute angewendet wurden. Testen Sie es also.
Archonic
7
du hast das PASTE- Ereignis vergessen , mein Freund;) du solltest es ändern inonInput
vsync
114

In modernen Browserversionen chist auch die CSS-Einheit verfügbar. Nach meinem Verständnis handelt es sich um eine schriftunabhängige Einheit, bei 1chder die Zeichenbreite entspricht0 (Null) in einer bestimmten Schriftart entspricht.

So könnte etwas so Einfaches wie das Folgende als Größenänderungsfunktion verwendet werden:

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>

In diesem Beispiel würde die Größe von "elem" auf die Länge des Werts + 2 zusätzliche Zeichen geändert.

Jani Jalkala
quelle
13
Ich bin überrascht, dass dieser Kommentar nicht höher bewertet wird, da er eine großartige Lösung darstellt und etwa 95% ( 1 ) der Browser dies unterstützen.
Husky
8
Dies ist überhaupt keine gute Antwort, da die Messung nicht genau ist und Stile nicht berücksichtigt, die auf der Website auftreten können input , Element, wie font-style, letter-spacingund so weiter. Ich habe die Antwort mit einer Live-Demo bearbeitet.
vsync
5
Funktioniert hervorragend, wenn Sie eine monospaced Schriftart verwenden. Bei anderen Schriftarten kann Ihr Kilometerstand variieren, da anscheinend die Zeichenbreite des 0-Zeichens verwendet wird.
Jilles van Gurp
2
Das ist wirklich toll. Beachten Sie jedoch, dass es manchmal Fehler gibt / nicht wie erwartet funktioniert, wenn a .auftritt.
Rishav
1
Dies funktioniert perfekt, wenn Sie die Boxgröße für die Eingabe auf 'content-box' setzen. Auf diese Weise wird die Polsterung beim Einstellen der Größe ignoriert.
Hypersapien
65

Um die Breite der aktuellen Eingabe zu berechnen, müssen Sie sie in ein temporäres spanElement einbetten , das scrollWidthObjekt an das DOM anhängen, die berechnete Breite (in Pixel) mithilfe der Eigenschaft abrufen und erneut entfernen span. Natürlich müssen Sie sicherstellen, dass sowohl in inputals auch in der Schrift die gleiche Schriftfamilie, Schriftgröße usw. verwendet wirdspan Element Element . Deshalb habe ich ihnen die gleiche Klasse zugewiesen.

Ich habe die Funktion an das keyupEreignis angehängt , da keypressdas Eingabezeichen noch nicht zur Eingabe hinzugefügt wurde value, so dass sich die falsche Breite ergibt. Leider weiß ich nicht, wie ich das Scrollen des Eingabefelds loswerden soll (wenn ich Zeichen am Ende des Feldes hinzufüge). es wird gescrollt, weil das Zeichen hinzugefügt und angezeigt wird, bevor adjustWidthOfInput()es aufgerufen wird. Und wie gesagt, ich kann das nicht umgekehrt machen, weil Sie dann den Wert des Eingabefelds haben, bevor das gedrückte Zeichen eingefügt wird. Ich werde später versuchen, dieses Problem zu lösen.

Übrigens habe ich dies nur in Firefox (3.6.8) getestet, aber Sie werden es verstehen, hoffe ich.

<!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
quelle
Ich mochte Ihre Antwort und implementierte sie sogar mit jQuery / Underscore: gist.github.com/3745941 . Ich könnte jedoch bestimmte Annahmen treffen: (1) Die Breite eines Zeichens beträgt nicht mehr als 14 Pixel. (2) Es ist akzeptabel, dass das Eingabeelement 14 Pixel über den Wert des Elements hinausragt. Ich habe dies mit einem Keydown-Event verbunden und es funktioniert großartig!
Nathan
11
Sie sollten white-space: pre;CSS folgendermaßen hinzufügen : .tmp-element{ visibility: hidden; white-space: pre;}. Andernfalls werden Leerzeichen kombiniert und die Breitenberechnung schlägt fehl. <input>und <span>verhält sich in Bezug auf die Behandlung von <input>Leerzeichen anders, behält Leerzeichen bei und <span>kombiniert aufeinanderfolgende Leerzeichen zu einem, wenn white-space: pre;es nicht hinzugefügt wird.
Timo Kähkönen
2
tmp.getBoundingClientRect().widthist besser als tmp.scrollWidth, weil das manchmal 0 zurückgibt
lisak
@lisak Danke, ich habe meine Antwort angepasst, aber hier gibt es bereits bessere Antworten.
Marcel Korpel
Besser? Das würde ich nicht sagen. Markierte Antworten sind nicht präzise genug, andere (+ hier 1 und hier 2 ) verwenden jQuery - ich nicht wegen React. Canvas kann Ihnen keine Texthöhe AFAIK geben. Idee: Problem mit Leerzeichen könnte auch gelöst werden mit:.replace(/ /g, "&nbsp;")
Milan Jaros
30

Hier ist eine Modifikation von Lyths Antwort, die Folgendes berücksichtigt:

  • Streichung
  • Initialisierung
  • Platzhalter

Es erlaubt auch eine beliebige Anzahl von Eingabefeldern! Um es in Aktion zu sehen: http://jsfiddle.net/4Qsa8/

Skript:

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

Stil:

.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
quelle
Hallo Michael. Ihr Code funktioniert gut, aber ich habe ein Problem. Eines meiner Felder ist ein Google Place-Feld zum automatischen Vervollständigen. Und wenn ich die richtige Adresse aus einem Dropdown-Menü auswähle, ändert sich die Breite des Eingabefelds nicht entsprechend der Länge der ausgewählten Adresse. Gibt es eine einfache Lösung dafür?
Maxence
2
@ Maxence das changeoder inputEreignis zu hören würde ausreichen
yarwest
Ich hatte Probleme mit der Anzeige des Bereichs: Kein Styling, da der Bereich mit einer Breite von 0 registriert wurde. Verwenden Sie besser die absolute Positionierung mit Sichtbarkeit: versteckt für die Spanne.
Jayt
Hallo @yarwest, danke für den Tipp. Würdest du vielleicht wissen, wie man das ursprüngliche Skript mit diesem Setup optimiert? (Mein Wissen in Js / JQuery ist sehr, sehr begrenzt)
Maxence
21

Hier ist eine Lösung ohne proportionale Schrift benötigt, mit nur sehr kleinen Stück Code von Javascript , braucht nicht berechnet Arten zu berechnen und sogar unterstützen ime , Unterstützung rtl Texte .

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

Verwenden Sie die span.text, um die Textbreite anzupassen, und lassen Sie die Eingabe position: absolutefür den Container dieselbe Größe haben . Kopieren Sie den Wert der Eingabe bei spanjeder Änderung in den Wert (Sie können diesen Code leicht in vanilla js ändern). Die Eingabe "passt" also einfach zur Größe ihres Inhalts.

tsh
quelle
18

FÜR EIN NICER LOOK & FEEL

Sie sollten das Ereignis jQuery keypress () in Kombination mit String.fromCharCode (e.which) verwenden, um das gedrückte Zeichen abzurufen. Daher können Sie berechnen, wie breit Sie sein werden . Warum? Weil es viel sexy aussehen wird :)

Hier ist eine jsfiddle, die im Vergleich zu Lösungen mit dem keyup-Ereignis zu einem netten Verhalten führt: http://jsfiddle.net/G4FKW/3/

Unten sehen Sie eine Vanille-JS, die das inputEreignis eines <input>Elements abhört und ein spanGeschwister so einstellt , dass es denselben Textwert hat, um es zu messen.

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
quelle
1
Sieht gut aus, berücksichtigt jedoch nicht Rücktaste und Löschen.
Marcel Korpel
Ja, dafür benötigen Sie ein Keydown-Ereignis. Sie können eine bestimmte Behandlung für die Rücktaste hinzufügen und löschen, indem Sie dies tun (e.which === 46 für delete, e.which === 8 für backspace). Sie benötigen jedoch noch ein Tastendruckereignis, um für den Rest auf e.charCode zugreifen zu können.
Lyth
Wenn Sie IE8 nicht unterstützen, können Sie das Ereignis oninput verwenden, anstatt e.which zu überprüfen: developer.mozilla.org/en-US/docs/Web/Events/input
Frinsh
1
Ich habe Ihre Antwort bearbeitet, um jQuery zu entfernen und nur Vanilla JS zu verwenden. Beachten Sie, dass diese Lösung alles andere als optimal ist, da Sie eine generische Lösung wünschen, bei der a spanund css nicht manuell codiert werden müssen .
vsync
17

Dies ist eine winkelspezifische Antwort, die jedoch für mich funktioniert hat und hinsichtlich ihrer Einfachheit und Benutzerfreundlichkeit sehr zufriedenstellend war:

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

Es wird automatisch über die Zeicheneinheiten in Janis Antwort aktualisiert .

Chris Vandevelde
quelle
3
Dies. Ist. Epos.
Daniel Flippance
Ernsthaft. Magisch.
DongBin Kim
12

Hier ist eine alternative Möglichkeit, dies mithilfe eines DIV und der Eigenschaft 'contenteditable' zu lösen:

HTML:

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

CSS: (um dem DIV einige Dimensionen zu geben und das Sehen zu erleichtern)

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

}

Hinweis: Wenn Sie dies in einem FORM-Element verwenden möchten, das Sie senden möchten, müssen Sie Javascript / jQuery verwenden, um das Übermittlungsereignis abzufangen, damit Sie den 'Wert' ( .innerHTMLbzw. .html()) des DIV analysieren können .

Logik8
quelle
1
Dies verdient mehr Gegenstimmen. Es ist elegant und einfach (solange die Verwendung von JS für Formularüberprüfungen für Sie kein Problem darstellt).
Daniel Bonnell
2
Aber es ist keine Eingabe!
Toni Michel Caubet
8

Sie können die Breite einer Eingabe anhand der Größe festlegen und Attribute. Die Größe einer Eingabe bestimmt die Breite in Zeichen.

Ein Eingang kann seine Größe dynamisch anpassen, indem er auf wichtige Ereignisse wartet.

Beispielsweise

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

JsFiddle hier

brendan
quelle
7

Man könnte so etwas wie tun dies

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

.

.

Krawatten
quelle
Wenn Sie die Größe beim Keyup erhöhen, führt dies zu einem hässlichen Verhalten. Die Eingabe muss für mehr Komfort vergrößert werden, bevor der Charakter sie betritt.
Lyth
5

Fügen Sie einfach zusätzlich zu anderen Antworten hinzu.

Mir ist aufgefallen, dass heutzutage in einigen Browsern das Eingabefeld eine scrollWidth hat. Was bedeutet:

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

sollte gut funktionieren. getestet in Chrom, Firefox und Safari.

Zur Unterstützung des Löschens können Sie zuerst '= 0' hinzufügen und dann neu einstellen.

this.style.width = 0; this.style.width = this.scrollWidth + 'px';
Kerl Mograbi
quelle
3
Bitte fügen Sie auch hier den relevanten Code hinzu - der Link könnte in Zukunft tot sein und dann ist dieser Beitrag nutzlos.
Uooo
3
Das funktioniert super, danke! Ich weiß nicht, warum diese Antwort nicht mehr positive Stimmen hat. Es ist bei weitem die einfachste, weniger erfundene (js) Lösung.
Form
4

Hier ist ein einfaches JS- und ein jQuery-Plugin, das ich geschrieben habe und das die Größe eines Eingabeelements mithilfe einer Zeichenfläche und der Schriftgröße / -familie ändert, um die tatsächliche Zeichenfolgenlänge beim Rendern zu bestimmen. (funktioniert nur in> IE9, Chrome, Safari, Firefox, Opera und den meisten anderen großen Browsern, die das Canvas-Element implementiert haben).

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

jQuery Plugin:

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

Hinweis: Dies behandelt keine Texttransformationen, Zeilenabstände und Buchstabenabstände sowie wahrscheinlich einige andere Eigenschaften zur Änderung der Textgröße. Um die Eigenschaft der Texttransformation zu verarbeiten, passen Sie den Textwert an diese Eigenschaft an. Die anderen sind wahrscheinlich ziemlich einfach. Ich werde implementieren, wenn dies etwas an Zugkraft gewinnt ...

newms87
quelle
4

Es ist erwähnenswert, dass eine gut aussehende Größenänderung durchgeführt werden kann, wenn die Schrift monospaced ist, so dass wir die Größe des inputElements mithilfe des chGeräts perfekt ändern können .

Auch bei diesem Ansatz können wir die Breite des Feldes aktualisieren, indem wir nur eine CSS-Variable ( benutzerdefinierte Eigenschaft ) für ein inputEreignis aktualisieren. Außerdem sollten wir uns um bereits vorab ausgefüllte Eingaben für ein DOMContentLoadedEreignis kümmern

Codepen-Demo


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

Als Root-Variable setzen wir --size: 0: Diese Variable enthält die Länge der Eingabe und wird 1chinnerhalb des calc()Ausdrucks mit multipliziert . Standardmäßig können wir auch eine Mindestbreite festlegen, z10ch

Der Javascript-Teil liest die Länge des eingefügten Werts und aktualisiert die 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);
});

Dies funktioniert natürlich auch dann, wenn Sie keine monospaced Schriftart verwenden. In diesem Fall müssen Sie jedoch die calc()Formel ändern, indem Sie die --sizeVariable mit einem anderen Wert multiplizieren (der streng vom font-familyund abhängt font-size) 1ch.

Fabrizio Calderan
quelle
3

Diese Antwort bietet eine der genauesten Methoden zum Abrufen der im Browser verfügbaren Textbreite und ist genauer als die akzeptierte Antwort. Es verwendet das Canvas-Element html5 und fügt das Element im Gegensatz zu anderen Antworten nicht zum DOM hinzu. Dadurch werden Reflow-Probleme vermieden, die durch übermäßiges Hinzufügen von Elementen zum DOM verursacht werden.

Lesen Sie mehr über das Canvas - Element hier in Bezug auf Textbreite.

HINWEIS: Laut MDN können die Kurzversionen der getPropertyValue()Methode, z. B. die Schriftart, unzuverlässig sein. Ich würde empfehlen, die Werte einzeln zu erhalten, um die Kompatibilität zu verbessern. Ich habe es hier nur aus Geschwindigkeitsgründen benutzt.

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

Mit der integrierten ng- Direktive können Sie dies in Angularjs noch einfacher tun .

In Ihrem HTML:

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

In Ihrem Controller:

 $scope.testdata = "whatever";

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

In Ihrem CSS:

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

Passen Sie die Zeichenbreite an die Breite Ihrer Schrift an. Es scheint 7 bei einer Schriftgröße von 12px zu sein;

michieljoris
quelle
3
Dies ist cool und praktisch zu wissen, aber das Hinzufügen von AngularJs zu einer App, um die Größe eines Eingabeelements dynamisch zu ändern, ist ein schwerwiegender Overkill, insbesondere wenn OP nach "HTML-, JavaScript-, PHP- oder CSS" -Lösungen gefragt wird. Man könnte argumentieren, dass jQuery auch dafür übertrieben ist, aber - anders als Angular - ein DOM-Manipulations-Toolkit zu sein, ist der Kern von jQuerys Zweck.
Vlasits
Woher soll ich die Breite des eingegebenen Zeichens wissen? Es ist nicht leicht anzunehmen, dass es sich um eine monogroße Schrift handelt.
Ethan
1
Sie können keine monospaced Schriftart benötigen, und Angular ist nicht erforderlich. brendans antwort macht im Grunde das gleiche.
Dan Dascalescu
2

Wenn Sie Bootstrap verwenden, ist dies sehr einfach möglich:

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

Sie müssen nur den Inhalt von div abrufen und in eine versteckte Eingabe einfügen, bevor Sie das Formular senden.

Alexey Kosov
quelle
1

Ich denke, Sie interpretieren die CSS-Eigenschaft mit minimaler Breite falsch . Die Mindestbreite wird im Allgemeinen verwendet, um eine Mindest-DOM-Breite in einem Fluid-Layout zu definieren, z.

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

Dies würde das Eingabeelement auf eine Mindestbreite von 200 Pixel einstellen. In diesem Zusammenhang steht "px" für "Pixel".

Wenn Sie nun überprüfen möchten, ob das Eingabefeld mindestens ein Zeichen enthält, wenn ein Benutzer es einreicht, müssen Sie eine Formularüberprüfung mit JavaScript und PHP durchführen. Wenn Sie dies tatsächlich versuchen, werde ich diese Antwort bearbeiten und mein Bestes geben, um Ihnen zu helfen.

peterjmag
quelle
Ich weiß, was px bedeutet und ich weiß, dass Javascript eine Funktion für die Mindestbreite hat, aber es funktioniert nicht für Eingabetext.
Kerc
1
@Kerc: "Javascript hat eine Funktion für die Mindestbreite" - welche? Was meinst du? - "es funktioniert nicht" ist niemals eine gute Beschreibung eines Problems. Versuchen Sie, das beabsichtigte Verhalten zu erläutern.
Marcel Korpel
Haben Sie sogar mein Beispiel ausprobiert, als Sie sehen, dass es nicht 1 px ist und Ihr Beispiel auch nicht. Dies wird nicht funktionieren, egal ob ich es in HTML, CSS
Kerc
Vielleicht gibt es dafür eine PHP-Funktion, weiß jemand?
Kerc
Ich habe Ihr Beispiel ausprobiert, aber ich habe angenommen, dass ein 1 Pixel breites Eingabefeld nicht das ist, wonach Sie gesucht haben. Wenn <input type="text" value="1" style="width:1px;" />
ja
1

Ich mochte Lyths Antwort sehr , wollte es aber auch:

  1. Rücktaste behandeln und löschen
  2. Sie müssen kein benachbartes Tag manuell hinzufügen.
  3. Erzwingen Sie eine minimale Breite.
  4. Wird automatisch auf Elemente mit einer bestimmten Klasse angewendet

Ich passte seine JSFiddle und kam mit bis diese . Eine Verbesserung, die in dieser Geige nicht vorhanden ist, wäre die Verwendung von jQuery CSS Parser zu verwenden, um die anfängliche Breite aus der Regel input.textbox-autosize tatsächlich zu lesen und diese als minWidth zu verwenden. Richtig, ich verwende einfach ein Attribut auf dem, was für eine kompakte Demo sorgt, aber nicht ideal ist. da für jede Eingabe ein zusätzliches Attribut erforderlich ist. Möglicherweise möchten Sie auch nur die minWidth als 100 direkt in das JavaScript einfügen.

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
quelle
1

Besser ist onvalue:

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

Dazu gehört auch das Einfügen, Ziehen und Ablegen usw.

Łukasz Polowczyk
quelle
1

Hier sind meine 2 Cent. Erstellen Sie ein leeres unsichtbares Div. Füllen Sie es mit dem Eingabeinhalt und geben Sie die Breite in das Eingabefeld zurück. Ordnen Sie die Textstile den einzelnen Feldern zu.

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

Ziemlich einfach:

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

Wobei N eine Zahl ist (2 im Beispiel, 17 für etwas, das ich entwickle), die experimentell bestimmt wird.

Das Subtrahieren von N verhindert, dass sich dieser seltsame, überflüssige Raum ansammelt, lange bevor der Text das Ende des Textfelds erreicht.

Vergleichen Sie. Achten Sie genau darauf, wie sich die Größe bereits nach dem ersten Zeichen ändert .

<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.
quelle
Ich habe nicht viel mit diesem getestet, aber man konnte nur ändern , oninput='this.style.width = (this.scrollWidth-2) + "px";'indem oninput='this.style.width = 0; this.style.width = this.scrollWidth + "px";'der Raum , um loszuwerden Akkumulieren
MaxCloutier
0

Ich verbringe nur einige Zeit damit, herauszufinden, wie es geht.
Der einfachste Weg, den ich gefunden habe, besteht darin, den Eingabewert so zu verschieben, dass er kurz vor der Eingabe liegt, wobei die Symbolbreite von Eingabe 1 beibehalten wird. Obwohl ich nicht sicher sein kann, ob es für Ihren anfänglichen Bedarf geeignet ist.
Vielleicht ist es ein zusätzlicher Code, aber in einer auf React + Flux basierenden Anwendung ist es eine ganz natürliche Lösung.

freele
quelle
0

Basierend auf Michaels Antwort habe ich mit jQuery eine eigene Version davon erstellt. Ich denke, es ist eine sauberere / kürzere Version der meisten Antworten hier und es scheint die Arbeit zu erledigen.

Ich mache das Gleiche wie die meisten Leute hier, indem ich eine Spanne benutze, um den Eingabetext zu schreiben und dann die Breite zu erhalten. Dann stelle ich die Breite ein, wenn die Aktionen keyupundblur aufgerufen werden.

Hier ist ein funktionierender Codepen . Dieser Codepen zeigt, wie dies mit mehreren Eingabefeldern verwendet werden kann.

HTML-Struktur:

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

Die obige Funktion ruft den Eingabewert ab, schneidet die zusätzlichen Leerzeichen ab und setzt den Text in den Bereich, um die Breite zu erhalten. Wenn kein Text vorhanden ist, wird stattdessen der Platzhalter abgerufen und in den Bereich eingegeben. Sobald der Text in den Bereich eingegeben wurde, wird die Breite der Eingabe festgelegt. Die + 5auf die Breite ist, weil ohne das die Eingabe im Edge-Browser ein kleines Stück abgeschnitten wird.

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

Wenn dies verbessert werden könnte, lassen Sie es mich bitte wissen, da dies die sauberste Lösung ist, die ich finden könnte.

Matthew
quelle
0

Warum nicht einfach CSS verwenden?

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

Dieser Code wurde von @Iain Todd eingeführt und ich dachte, ich sollte ihn teilen

Milad
quelle
Es ist nicht nur CSS. Es ist nur eine andere js-Methode. Interessant.
Vatavale
0

Ein kugelsicherer, generischer Weg muss:

  1. Berücksichtigen Sie alle möglichen Stile des gemessenen inputElements
  2. Sie können die Messung auf jede Eingabe anwenden, ohne den HTML-Code oder zu ändern

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

Sie können einfach ein sizeAttribut festlegen . Wenn Sie eines der reaktiven Frameworks verwenden, reicht Folgendes aus:

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

Wenn Sie jedoch reines js verwenden, sollten Sie Ereignishandler festlegen, wie z.

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