it-swarm.com.de

Auto-Skalierungseingabe [Typ = Text] auf Wertbreite?

Gibt es eine Möglichkeit, die Breite eines <input type="text"> auf die Breite des tatsächlichen Werts zu skalieren?

input {
  display: block;
  margin: 20px;
  width: auto;
}
<input type="text" value="I've had enough of these damn snakes, on this damn plane!" />

<input type="text" value="me too" />

72
Walker

Sie können dies auf einfache Weise tun, indem Sie das size-Attribut auf die Länge des Eingabeinhalts setzen:

function resizeInput() {
    $(this).attr('size', $(this).val().length);
}

$('input[type="text"]')
    // event handler
    .keyup(resizeInput)
    // resize on page load
    .each(resizeInput);

Siehe: http://jsfiddle.net/nrabinowitz/NvynC/

Dies scheint etwas Füllung auf der rechten Seite hinzuzufügen, von der ich vermute, dass sie vom Browser abhängt. Wenn Sie möchten, dass die Eingabe sehr eng ist, können Sie eine Methode wie die von mir in dieser verwandten Antwort beschriebene verwenden. Verwenden Sie jQuery, um die Pixelgröße Ihres Textes zu berechnen.

74
nrabinowitz

Wenn die anderen Lösungen aus irgendeinem Grund nicht für Sie funktionieren, können Sie anstelle eines Eingabeelements einen inhaltbaren Bereich verwenden.

<span contenteditable="true">dummy text</span>

Beachten Sie, dass dies eher ein Hack ist und den gravierenden Nachteil hat, dass völlig unbelebte HTML-Eingaben zugelassen werden, z.

Sie sollten diese Lösung wahrscheinlich nicht verwenden, wenn Sie die Eingabe nicht sehr sorgfältig bereinigen ...

Update: Wahrscheinlich möchten Sie die Lösung von Obsidian unter verwenden.

33
mb21

EINE EINFACHE ABER PIXEL-PERFEKTE LÖSUNG

Ich habe mehrere Möglichkeiten dafür gesehen, aber die Breite der Schriftarten zu berechnen, ist nicht immer zu 100% genau, es handelt sich lediglich um eine Schätzung.

Es gelang mir, eine pixelgenaue Methode zur Anpassung der Eingabebreite zu erstellen, indem ein ausgeblendeter Platzhalter zum Messen verwendet wurde.


jQuery (Empfohlen)

$(function(){
  $('#hide').text($('#txt').val());
  $('#txt').width($('#hide').width());
}).on('input', function () {
  $('#hide').text($('#txt').val());
  $('#txt').width($('#hide').width());
});
body,
#txt,
#hide{
  font:inherit;
  margin:0;
  padding:0;
}
#txt{
  border:none;
  color:#888;
  min-width:10px;
}
#hide{
  display:none;
  white-space:pre;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<p>Lorem ipsum 
  <span id="hide"></span><input id="txt" type="text" value="type here ...">
  egestas arcu.
</p>


Reines JavaScript

Ich konnte nicht feststellen, wie jQuery die Breite der ausgeblendeten Elemente berechnet, sodass für diese Lösung eine leichte Anpassung an css erforderlich war.

var hide = document.getElementById('hide');
var txt = document.getElementById('txt');
resize();
txt.addEventListener("input", resize);

function resize() {
  hide.textContent = txt.value;
  txt.style.width = hide.offsetWidth + "px";
}
body,
#txt,
#hide {
  font: inherit;
  margin: 0;
  padding: 0;
}

#txt {
  border: none;
  color: #888;
  min-width: 10px;
}

#hide {
  position: absolute;
  height: 0;
  overflow: hidden;
  white-space: pre;
}
<p>Lorem ipsum
  <span id="hide"></span><input id="txt" type="text" value="type here ..."> egestas arcu.
</p>

16
DreamTeK

Bearbeiten : Das Plugin funktioniert jetzt mit nachgestellten Leerzeichen. Vielen Dank für den Hinweis auf @JavaSpyder

Da die meisten anderen Antworten nicht den Anforderungen entsprachen (oder überhaupt nicht funktionierten), habe ich die Antwort von Adrian B in ein richtiges jQuery-Plugin geändert, das eine pixelgenaue Skalierung der Eingabe ermöglicht, ohne dass Sie Ihre CSS- oder HTML-Daten ändern müssen.

Beispiel: https://jsfiddle.net/587aapc2/

Verwendung: $("input").autoresize({padding: 20, minWidth: 20, maxWidth: 300});

Plugin:

//JQuery plugin:
$.fn.textWidth = function(_text, _font){//get width of text with font.  usage: $("div").textWidth();
        var fakeEl = $('<span>').hide().appendTo(document.body).text(_text || this.val() || this.text()).css({font: _font || this.css('font'), whiteSpace: "pre"}),
            width = fakeEl.width();
        fakeEl.remove();
        return width;
    };

$.fn.autoresize = function(options){//resizes elements based on content size.  usage: $('input').autoresize({padding:10,minWidth:0,maxWidth:100});
  options = $.extend({padding:10,minWidth:0,maxWidth:10000}, options||{});
  $(this).on('input', function() {
    $(this).css('width', Math.min(options.maxWidth,Math.max(options.minWidth,$(this).textWidth() + options.padding)));
  }).trigger('input');
  return this;
}



//have <input> resize automatically
$("input").autoresize({padding:20,minWidth:40,maxWidth:300});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input value="i magically resize">
<br/><br/>
called with:
$("input").autoresize({padding: 20, minWidth: 40, maxWidth: 300});
9
Marc Guiselin

Ich habe ein jQuery-Plugin auf GitHub: https://github.com/MartinF/jQuery.Autosize.Input

Es spiegelt den Wert der Eingabe wider, berechnet die Breite und verwendet sie zur Einstellung der Breite der Eingabe.

Ein Live-Beispiel finden Sie hier: http://jsfiddle.net/mJMpw/2175/

Beispiel für die Verwendung (weil beim Posten eines jsfiddle-Links Code benötigt wird):

<input type="text" value="" placeholder="Autosize" data-autosize-input='{ "space": 40 }' />

input[type="data-autosize-input"] {
  width: 90px;
  min-width: 90px;
  max-width: 300px;
  transition: width 0.25s;    
}

Verwenden Sie einfach css, um die Min-/Max-Breite festzulegen, und verwenden Sie einen Übergang für die Breite, wenn Sie einen Nice-Effekt wünschen.

Sie können den Abstand zum Ende als Wert in json-Notation für das data-autosize-input-Attribut des Eingabeelements angeben.

Natürlich können Sie es auch einfach mit jQuery initialisieren

$("selector").autosizeInput();
7
MartinF

Hier gibt es schon viele gute Antworten. Zum Spaß habe ich diese Lösung unten implementiert, basierend auf den anderen Antworten und meinen eigenen Ideen.

<input class="adjust">

Das Eingabeelement ist pixelgenau eingestellt und es kann ein zusätzlicher Versatz definiert werden.

function adjust(elements, offset, min, max) {

    // Initialize parameters
    offset = offset || 0;
    min    = min    || 0;
    max    = max    || Infinity;
    elements.each(function() {
        var element = $(this);

        // Add element to measure pixel length of text
        var id = btoa(Math.floor(Math.random() * Math.pow(2, 64)));
        var tag = $('<span id="' + id + '">' + element.val() + '</span>').css({
            'display': 'none',
            'font-family': element.css('font-family'),
            'font-size': element.css('font-size'),
        }).appendTo('body');

        // Adjust element width on keydown
        function update() {

            // Give browser time to add current letter
            setTimeout(function() {

                // Prevent whitespace from being collapsed
                tag.html(element.val().replace(/ /g, '&nbsp'));

                // Clamp length and prevent text from scrolling
                var size = Math.max(min, Math.min(max, tag.width() + offset));
                if (size < max)
                    element.scrollLeft(0);

                // Apply width to element
                element.width(size);
            }, 0);
        };
        update();
        element.keydown(update);
    });
}

// Apply to our element
adjust($('.adjust'), 10, 100, 500);

Die Anpassung wird durch einen CSS-Übergang geglättet.

.adjust {
    transition: width .15s;
}

Hier ist die Geige . Ich hoffe, dass dies anderen helfen kann, nach einer sauberen Lösung zu suchen.

5
danijar

Leider funktioniert das size-Attribut nicht sehr gut. Je nach Einstellung der Schrift ist manchmal mehr Platz und zu wenig Platz vorhanden. (Schauen Sie sich das Beispiel an)

Wenn Sie möchten, dass dies gut funktioniert, versuchen Sie, nach Änderungen an der Eingabe zu suchen, und ändern Sie dann die Größe. Sie möchten wahrscheinlich die Variable scrollWidth der Eingabe festlegen. Wir müssen auch die Größe der Box berücksichtigen.

Im folgenden Beispiel setze ich die Variable size auf 1, um zu verhindern, dass scrollWidth größer ist als unsere ursprüngliche Breite (manuell mit CSS festgelegt).

// (no-jquery document.ready)
function onReady(f) {
    "complete" === document.readyState
        ? f() : setTimeout(onReady, 10, f);
}

onReady(function() {
    [].forEach.call(
        document.querySelectorAll("input[type='text'].autoresize"),
        registerInput
    );
});
function registerInput(el) {
    el.size = 1;
    var style = el.currentStyle || window.getComputedStyle(el),
        borderBox = style.boxSizing === "border-box",
        boxSizing = borderBox
            ? parseInt(style.borderRightWidth, 10) +
                parseInt(style.borderLeftWidth, 10)
            : 0;
    if ("onpropertychange" in el) {
         // IE
         el.onpropertychange = adjust;
    } else if ("oninput" in el) {
         el.oninput = adjust;
    }
    adjust();

    function adjust() {

        // reset to smaller size (for if text deleted) 
        el.style.width = "";

        // getting the scrollWidth should trigger a reflow
        // and give you what the width would be in px if 
        // original style, less any box-sizing
        var newWidth = el.scrollWidth + boxSizing;

        // so let's set this to the new width!
        el.style.width = newWidth + "px";
    }
}
* {
  font-family: sans-serif;
}
input.autoresize {
  width: 125px;
  min-width: 125px;
  max-width: 400px;
}
input[type='text'] {
  box-sizing: border-box;
  padding: 4px 8px;
  border-radius: 4px;
  border: 1px solid #ccc;
  margin-bottom: 10px;
}
<label> 
  Resizes:
  <input class="autoresize" placeholder="this will resize" type='text'>
</label>
<br/>
<label>
  Doesn't resize:
<input placeholder="this will not" type='text'>
</label>
<br/>
<label>
  Has extra space to right:
  <input value="123456789" size="9" type="text"/>
</label>

Ich denke, das sollte sogar in IE6 funktionieren, aber mein Wort darf nicht dafür.

Je nach Anwendungsfall müssen Sie die Anpassungsfunktion möglicherweise an andere Ereignisse binden. Z.B. programmgesteuertes Ändern eines Eingabewerts oder Ändern der Eigenschaft display des Elements von none (wobei scrollWidth === 0) in block oder inline-block usw.

3
Joseph Nields

Sie können dieses Problem wie folgt lösen:) http://jsfiddle.net/MqM76/217/

HTML:

<input id="inpt" type="text" />
<div id="inpt-width"></div>

JS:

$.fn.textWidth = function(text, font) {
    if (!$.fn.textWidth.fakeEl) $.fn.textWidth.fakeEl =      $('<span>').hide().appendTo(document.body);
    $.fn.textWidth.fakeEl.text(text || this.val() || this.text()).css('font', font || this.css('font'));
    return $.fn.textWidth.fakeEl.width(); 
};

$('#inpt').on('input', function() {
    var padding = 10; //Works as a minimum width
    var valWidth = ($(this).textWidth() + padding) + 'px';
    $('#'+this.id+'-width').html(valWidth);
    $('#inpt').css('width', valWidth);
}).trigger('input');
3
Adrian B

Anstatt zu versuchen, ein Div zu erstellen und seine Breite zu messen, denke ich, ist es zuverlässiger, die Breite direkt mit einem Canvas-Element zu messen, das genauer ist.

function measureTextWidth(txt, font) {
    var element = document.createElement('canvas');
    var context = element.getContext("2d");
    context.font = font;
    return context.measureText(txt).width;
}

Jetzt können Sie dies verwenden, um die Breite eines Eingabeelements zu einem beliebigen Zeitpunkt zu messen, indem Sie Folgendes tun:

// assuming inputElement is a reference to an input element (DOM, not jQuery)
var style = window.getComputedStyle(inputElement, null);
var text = inputElement.value || inputElement.placeholder;
var width = measureTextWidth(text, style.font);

Dies gibt eine Zahl (möglicherweise Gleitkommazahl) zurück. Wenn Sie das Padding berücksichtigen möchten, können Sie Folgendes versuchen:

  var desiredWidth = (parseInt(style.borderLeftWidth) +
      parseInt(style.paddingLeft) +
      Math.ceil(width) +
      1 + // extra space for cursor
      parseInt(style.paddingRight) +
      parseInt(style.borderRightWidth))
  inputElement.style.width = desiredWidth + "px";
3
ハセン

Mein jQuery-Plugin funktioniert für mich:

Verwendungszweck:

    $('form input[type="text"]').autoFit({

    });

Quellcode von jquery.auto-fit.js:

;
(function ($) {
    var methods = {
        init: function (options) {
            var settings = $.extend(true, {}, $.fn.autoFit.defaults, options);
            var $this = $(this);

            $this.keydown(methods.fit);

            methods.fit.call(this, null);

            return $this;
        },

        fit: function (event) {
            var $this = $(this);

            var val = $this.val().replace(' ', '-');
            var fontSize = $this.css('font-size');
            var padding = $this.outerWidth() - $this.width();
            var contentWidth = $('<span style="font-size: ' + fontSize + '; padding: 0 ' + padding / 2 + 'px; display: inline-block; position: absolute; visibility: hidden;">' + val + '</span>').insertAfter($this).outerWidth();

            $this.width((contentWidth + padding) + 'px');

            return $this;
        }
    };

    $.fn.autoFit = function (options) {
        if (typeof options == 'string' && methods[options] && typeof methods[options] === 'function') {
            return methods[options].apply(this, Array.prototype.slice.call(arguments, 1));
        } else if (typeof options === 'object' || !options) {
            // Default to 'init'
            return this.each(function (i, element) {
                methods.init.apply(this, [options]);
            });
        } else {
            $.error('Method ' + options + ' does not exist on jquery.auto-fit.');
            return null;
        }
    };

    $.fn.autoFit.defaults = {};

})(this['jQuery']);
1
Jeff Tian

Mit Canvas können wir die Breite der Elemente berechnen:

function getTextWidth(text, fontSize, fontName) {
  let canvas = document.createElement('canvas');
  let context = canvas.getContext('2d');
  context.font = fontSize + fontName;
  return context.measureText(text).width;
}

und verwenden Sie es für die ausgewählte Veranstaltung:

function onChange(e) {
  let width = getTextWidth(this.value, $(this).css('font-size'), 
  $(this).css('font-family'));
  $(this.input).css('width', width);
}
0
Henrique Coura

Hier ist meine Modifikation von nrabinowitz 'Lösung . Ich habe die size - Eigenschaft nicht verwendet, da sie bei proportionalen Schriftarten nicht perfekt ist, wie @ Mark feststellt. Meine Lösung fügt ein Element nach Ihrer Eingabe ein und erhält die Breite, die vom Browser (mit jQuery) gezählt wird.

Obwohl ich es nicht teste, funktioniert es wahrscheinlich nur, wenn alle CSS-Eigenschaften, die die Schriftart betreffen, vererbt werden.

Die Eingabebreite ändert sich beim focusout -Ereignis, was für mich besser funktioniert. Sie können jedoch auch die Taste keyup/keypress verwenden, um die Breite der Eingabe auch während der Eingabe zu ändern.

function resizeInput() {

    //Firstly take the content or placeholder if content is missing.
    var content =
        $(this).val().length > 0 ? $(this).val() : $(this).prop("placeholder");

    //Create testing element with same content as input.
    var widthTester = $("<span>"+content+"</span>").hide();

    //Place testing element into DOM after input (so it inherits same formatting as input does).
    widthTester.insertAfter($(this));

    //Set inputs width; you may want to use outerWidth() or innerWidth()
    //depending whether you want to count padding and border or not.
    $(this).css("width",widthTester.width()+"px");

    //Remove the element from the DOM
    widthTester.remove();
 }

 $('.resizing-input').focusout(resizeInput).each(resizeInput);
0
fandasson

versuchen Sie es mit canvas measureText-Lösung

css:

    input{
        min-width:10px!important;
        max-width:99.99%!important;
        transition: width 0.1s;
        border-width:1px;
    }

javascript:

function getWidthOfInput(input){
    var canvas = document.createElement('canvas');
    var ctx = canvas.getContext('2d');
    var text = input.value.length ? input.value : input.placeholder;
    var style = window.getComputedStyle(input);
    ctx.lineWidth = 1;
    ctx.font = style.font;
    var text_width = ctx.measureText(text).width;
    return text_width;
}

function resizable (el, factor) {
    function resize() {
        var width = getWidthOfInput(el);
        el.style.width = width + 'px';
    }
    var e = 'keyup,keypress,focus,blur,change'.split(',');
    for (var i in e){
        el.addEventListener(e[i],resize,false);
    }
    resize();
}

$( "input" ).each( function(i){
    resizable(this);
});
0

Benutzer nrabinowitz 'Lösung funktioniert gut, aber ich benutze das Ereignis keypress anstelle von keyup. Dies verringert die Latenz, wenn der Benutzer langsam eingibt.

0
Timothee A

Eingabeelemente verhalten sich anders als andere Elemente. Sie würden genau das tun, was Sie möchten, wenn Sie ihnen float: left geben (siehe http://jsfiddle.net/hEvYj/5/ ). Ich denke nicht, dass dies möglich ist, ohne es mit JavaScript in irgendeiner Weise zu berechnen (d. H. Fügen Sie der Breite pro Buchstabe in der Box 5px hinzu).

0
Arve Systad