Czy istnieje sposób skalowania szerokości an <input type="text">
do szerokości rzeczywistej wartości?
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" />
Odpowiedzi:
Możesz to zrobić w prosty sposób, ustawiając
size
atrybut na długość zawartości wejściowej:function resizeInput() { $(this).attr('size', $(this).val().length); } $('input[type="text"]') // event handler .keyup(resizeInput) // resize on page load .each(resizeInput);
Zobacz: http://jsfiddle.net/nrabinowitz/NvynC/
Wydaje się, że dodaje to wypełnienie po prawej stronie, które, jak podejrzewam, zależy od przeglądarki. Jeśli chcesz, aby dane wejściowe były naprawdę ograniczone, możesz użyć techniki podobnej do tej, którą opisuję w tej powiązanej odpowiedzi , używając jQuery do obliczenia rozmiaru piksela twojego tekstu.
źródło
Courier New
czcionki dla pola tekstowego, ponieważ szerokość wszystkich znaków w tej czcionce jest równa. ( jsfiddle.net/NabiKAZ/NvynC/745 )PROSTE, ALE PERFEKCYJNE ROZWIĄZANIE PIKSELI
Widziałem kilka sposobów, aby to zrobić, ale obliczanie szerokości czcionek nie zawsze jest w 100% dokładne, to tylko szacunki.
Udało mi się stworzyć pikselowy, doskonały sposób dostosowywania szerokości wejściowej, mając ukryty element zastępczy do pomiaru.
jQuery (zalecane)
$(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>
Czysty JavaScript
Nie byłem w stanie określić, w jaki sposób jQuery oblicza szerokość ukrytych elementów, więc do dostosowania tego rozwiązania potrzebna była niewielka zmiana w css.
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>
źródło
hide
musi mieć takie samo wypełnienie),height: 0;
część nie będzie działać poprawnie. Obejściem tego problemu byłoby użycieposition: fixed; top: -100vh;
, możesz również dodaćopacity: 0;
tylko dla bezpieczeństwa.Jeśli z jakiegoś powodu inne rozwiązania nie działają dla Ciebie, możesz użyć elementu contenteditable-span zamiast elementu wejściowego.
<span contenteditable="true">dummy text</span>
Zwróć uwagę, że jest to bardziej hack i ma poważną wadę polegającą na umożliwieniu całkowicie niezanieczyszczonego wprowadzania danych HTML, na przykład pozwalaniu użytkownikom na wprowadzanie (i wklejanie) podziałów wierszy, linków i innego kodu HTML.
Więc prawdopodobnie nie powinieneś używać tego rozwiązania, chyba że bardzo dokładnie odkażasz wejście ...
Aktualizacja : prawdopodobnie chcesz skorzystać z rozwiązania DreamTeK poniżej .
źródło
contenteditable
służy do konfigurowania edytora tekstu w formacie WYSIWYG. Nie do zmiany rozmiaru danych wejściowych.Edycja : wtyczka działa teraz z końcowymi białymi znakami. Dzięki za wskazanie tego @JavaSpyder
Ponieważ większość innych odpowiedzi nie pasowała do tego, czego potrzebowałem (lub po prostu nie działała), zmodyfikowałem odpowiedź Adriana B na odpowiednią wtyczkę jQuery, która zapewnia doskonałe skalowanie danych wejściowych bez konieczności zmiany css lub html.
Przykład: https://jsfiddle.net/587aapc2/
Stosowanie:
$("input").autoresize({padding: 20, minWidth: 20, maxWidth: 300});
Podłącz:
//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});
źródło
font
jest skrótem CSS (dziwnie FF nie może tego obsłużyć ). Można rozwiązać ten problem poprzez zdefiniowanie w pierwszej funkcji:var _this_font = [this.css('font-style'), this.css('font-variant'), this.css('font-weight'), 'normal', this.css('font-size') + ' / ' + this.css('line-height'), this.css('font-family')].join(' ');
. Następnie zmieńthis.css('font')
się_this_font
.Mam wtyczkę jQuery na GitHub: https://github.com/MartinF/jQuery.Autosize.Input
Odzwierciedla wartość wejścia, oblicza szerokość i używa jej do ustawienia szerokości wejścia.
Możesz zobaczyć przykład na żywo tutaj: http://jsfiddle.net/mJMpw/2175/
Przykład, jak go używać (ponieważ przy wysyłaniu linku jsfiddle potrzebny jest jakiś kod):
<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; }
Po prostu użyj css, aby ustawić minimalną / maksymalną szerokość i użyj przejścia na szerokość, jeśli chcesz uzyskać ładny efekt.
Można określić odstęp / odległość do końca jako wartość w notacji JSON dla atrybutu data-autosize-input w elemencie wejściowym.
Oczywiście możesz też po prostu zainicjować go za pomocą jQuery
$("selector").autosizeInput();
źródło
Tutaj jest już wiele dobrych odpowiedzi. Dla zabawy wdrożyłem to rozwiązanie poniżej, opierając się na innych odpowiedziach i własnych pomysłach.
<input class="adjust">
Element wejściowy jest dostosowywany z dokładnością do pikseli i można zdefiniować dodatkowe przesunięcie.
function adjust(elements, offset, min, max) { // Initialize parameters offset = offset || 0; min = min || 0; max = max || Infinity; elements.each(function() { var element = $(this); // Add element to measure pixel length of text var id = btoa(Math.floor(Math.random() * Math.pow(2, 64))); var tag = $('<span id="' + id + '">' + element.val() + '</span>').css({ 'display': 'none', 'font-family': element.css('font-family'), 'font-size': element.css('font-size'), }).appendTo('body'); // Adjust element width on keydown function update() { // Give browser time to add current letter setTimeout(function() { // Prevent whitespace from being collapsed tag.html(element.val().replace(/ /g, ' ')); // Clamp length and prevent text from scrolling var size = Math.max(min, Math.min(max, tag.width() + offset)); if (size < max) element.scrollLeft(0); // Apply width to element element.width(size); }, 0); }; update(); element.keydown(update); }); } // Apply to our element adjust($('.adjust'), 10, 100, 500);
Dostosowanie jest wygładzane za pomocą przejścia CSS.
.adjust { transition: width .15s; }
Oto skrzypce . Mam nadzieję, że pomoże to innym szukającym czystego rozwiązania.
źródło
Zamiast próbować utworzyć element div i zmierzyć jego szerokość, myślę, że bardziej wiarygodne jest zmierzenie szerokości bezpośrednio przy użyciu elementu canvas, który jest dokładniejszy.
function measureTextWidth(txt, font) { var element = document.createElement('canvas'); var context = element.getContext("2d"); context.font = font; return context.measureText(txt).width; }
Teraz możesz użyć tego do zmierzenia szerokości jakiegoś elementu wejściowego w dowolnym momencie, wykonując następujące czynności:
// 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);
Zwraca liczbę (prawdopodobnie zmiennoprzecinkową). Jeśli chcesz uwzględnić dopełnienie, możesz spróbować tego:
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";
źródło
Możesz rozwiązać ten problem tak jak tutaj :) 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');
źródło
Niestety
size
atrybut nie będzie działał zbyt dobrze. Czasami będzie dodatkowe miejsce, a czasami za mało, w zależności od konfiguracji czcionki. (zobacz przykład)Jeśli chcesz, aby to działało dobrze, spróbuj obserwować zmiany na wejściu, a następnie zmień jego rozmiar. Prawdopodobnie chcesz ustawić to na wejście
scrollWidth
. Musielibyśmy również uwzględnić rozmiary pudełek.W poniższym przykładzie ustawiam
size
wejście na 1, aby zapobiec jego wartościscrollWidth
większej niż nasza początkowa szerokość (ustawiana ręcznie za pomocą CSS).// (no-jquery document.ready) function onReady(f) { "complete" === document.readyState ? f() : setTimeout(onReady, 10, f); } onReady(function() { [].forEach.call( document.querySelectorAll("input[type='text'].autoresize"), registerInput ); }); function registerInput(el) { el.size = 1; var style = el.currentStyle || window.getComputedStyle(el), borderBox = style.boxSizing === "border-box", boxSizing = borderBox ? parseInt(style.borderRightWidth, 10) + parseInt(style.borderLeftWidth, 10) : 0; if ("onpropertychange" in el) { // IE el.onpropertychange = adjust; } else if ("oninput" in el) { el.oninput = adjust; } adjust(); function adjust() { // reset to smaller size (for if text deleted) el.style.width = ""; // getting the scrollWidth should trigger a reflow // and give you what the width would be in px if // original style, less any box-sizing var newWidth = el.scrollWidth + boxSizing; // so let's set this to the new width! el.style.width = newWidth + "px"; } }
* { font-family: sans-serif; } input.autoresize { width: 125px; min-width: 125px; max-width: 400px; } input[type='text'] { box-sizing: border-box; padding: 4px 8px; border-radius: 4px; border: 1px solid #ccc; margin-bottom: 10px; }
<label> Resizes: <input class="autoresize" placeholder="this will resize" type='text'> </label> <br/> <label> Doesn't resize: <input placeholder="this will not" type='text'> </label> <br/> <label> Has extra space to right: <input value="123456789" size="9" type="text"/> </label>
Myślę, że to powinno działać nawet w IE6, ale nie wierz mi na słowo.
W zależności od przypadku użycia może być konieczne powiązanie funkcji Adjust z innymi zdarzeniami. Np. Programowa zmiana wartości danych wejściowych lub zmiana właściwości stylu elementu
display
znone
(gdziescrollWidth === 0
) nablock
lubinline-block
itp.źródło
Znalazłem inne rozwiązanie tego problemu, które nie obejmuje JS. W HTML po prostu umieściłem coś takiego:
<div> <input class="input" value={someValue} /> <div class="ghost-input">someValue</div> </div>
Wystarczy ustawić widoczność: ukryta na wejściu ducha i szerokość: 100% na samym wejściu. Działa, ponieważ dane wejściowe skalują się do 100% swojego kontenera, którego szerokość jest obliczana przez samą przeglądarkę (na podstawie tego samego tekstu).
Jeśli dodasz dopełnienie i obramowanie do pola wejściowego, musisz odpowiednio dostosować swoją klasę wejścia widma (lub użyj funkcji calc () w klasie wejściowej).
źródło
Moja wtyczka jQuery działa dla mnie:
Stosowanie:
$('form input[type="text"]').autoFit({ });
Kod źródłowy
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']);
źródło
Elementy wejściowe zachowują się inaczej niż inne elementy, które zrobiłyby dokładnie to, co chcesz, gdybyś je podał
float: left
(patrz http://jsfiddle.net/hEvYj/5/ ). Myślę, że nie jest to możliwe bez obliczania tego w jakiś sposób za pomocą JavaScript (tj. Dodaj 5px do szerokości każdej litery w polu).źródło
User nrabinowitz rozwiązanie ' działa świetnie, ale używam
keypress
zdarzenie zamiastkeyup
. Zmniejsza to opóźnienie, jeśli użytkownik pisze powoli.źródło
oninput
(lub wonpropertychange
przypadku starszej wersji IE) jest właściwym zdarzeniem, ponieważ reagują na takie rzeczy, jak wklejanie prawym przyciskiem myszy lub wybranie „Plik -> wklej” z paska menu przeglądarkiOto moja modyfikacja nrabinowitz rozwiązanie " . Nie użyłem właściwości size , ponieważ nie jest idealna z proporcjonalnymi czcionkami, jak zauważył @Mark. Moje rozwiązanie umieszcza element po wpisaniu i otrzymuje szerokość zliczoną przez przeglądarkę (przy użyciu jQuery).
Chociaż tego nie testuję, przypuszczam, że zadziała tylko wtedy, gdy wszystkie właściwości CSS wpływające na czcionkę zostaną odziedziczone.
Szerokość wejścia zmienia się po zdarzeniu fokusu , co dla mnie działa lepiej. Ale możesz użyć klawisza / klawisza, aby zmienić szerokość wejścia podczas pisania.
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);
źródło
Na kanwie możemy obliczyć szerokość elementów:
function getTextWidth(text, fontSize, fontName) { let canvas = document.createElement('canvas'); let context = canvas.getContext('2d'); context.font = fontSize + fontName; return context.measureText(text).width; }
i użyj go na wybranym wydarzeniu:
function onChange(e) { let width = getTextWidth(this.value, $(this).css('font-size'), $(this).css('font-family')); $(this.input).css('width', width); }
źródło
wypróbuj rozwiązanie Canvas MeasureText
css:
input{ min-width:10px!important; max-width:99.99%!important; transition: width 0.1s; border-width:1px; }
javascript:
function getWidthOfInput(input){ var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); var text = input.value.length ? input.value : input.placeholder; var style = window.getComputedStyle(input); ctx.lineWidth = 1; ctx.font = style.font; var text_width = ctx.measureText(text).width; return text_width; } function resizable (el, factor) { function resize() { var width = getWidthOfInput(el); el.style.width = width + 'px'; } var e = 'keyup,keypress,focus,blur,change'.split(','); for (var i in e){ el.addEventListener(e[i],resize,false); } resize(); } $( "input" ).each( function(i){ resizable(this); });
źródło
Rozwiązałem szerokość tworząc płótno i obliczając jego rozmiar. ważne jest, aby wartość wejściowa i płótno miały te same cechy czcionki (rodzina, rozmiar, waga ...)
import calculateTextWidth from "calculate-text-width"; /* requires two props "value" and "font" - defaultFont: normal 500 14px sans-serif */ const defaultText = 'calculate my width' const textFont = 'normal 500 14px sans-serif' const calculatedWidth = calculateTextWidth(defaultText, textFont) console.log(calculatedWidth) // 114.37890625
GitHub: https://github.com/ozluy/calculate-text-width CodeSandbox: https://codesandbox.io/s/calculate-text-width-okr46
źródło