Есть ли способ масштабировать ширину an <input type="text">
до ширины фактического значения?
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" />
Ответы:
Вы можете сделать это простым способом, установив для
size
атрибута длину входного содержимого:function resizeInput() { $(this).attr('size', $(this).val().length); } $('input[type="text"]') // event handler .keyup(resizeInput) // resize on page load .each(resizeInput);
См .: http://jsfiddle.net/nrabinowitz/NvynC/
Кажется, это добавляет некоторые отступы справа, которые, как я подозреваю, зависят от браузера. Если вы хотите, чтобы он был действительно тесно связан с вводом, вы можете использовать метод, подобный тому, который я описываю в этом связанном ответе , используя jQuery для вычисления размера вашего текста в пикселях.
источник
Courier New
шрифт для текстового поля, потому что ширина всех символов в этом шрифте одинакова. ( jsfiddle.net/NabiKAZ/NvynC/745 )ПРОСТОЕ, НО ПИКСЕЛЬНОЕ ИДЕАЛЬНОЕ РЕШЕНИЕ
Я видел несколько способов сделать это, но расчет ширины шрифтов не всегда точен на 100%, это всего лишь оценка.
Мне удалось создать идеальный пиксельный способ регулировки ширины ввода, имея скрытый заполнитель для измерения.
jQuery (рекомендуется)
$(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>
Чистый JavaScript
Мне не удалось определить, как jQuery вычисляет ширину скрытых элементов, поэтому потребовалась небольшая настройка 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>
источник
hide
должен иметь такое же заполнение),height: 0;
часть не будет работать правильно. Обходной путь для этой проблемы - использоватьposition: fixed; top: -100vh;
, вы также можете добавить наopacity: 0;
всякий случай.Если по какой-то причине другие решения не работают для вас, вы можете использовать contenteditable-span вместо элемента input.
<span contenteditable="true">dummy text</span>
Обратите внимание, что это больше похоже на взлом, и у него есть серьезный недостаток, заключающийся в том, что он позволяет вводить полностью несанкционированный ввод HTML, например, позволяет пользователям вводить (и вставлять) разрывы строк, ссылки и другой HTML.
Поэтому вам, вероятно, не стоит использовать это решение, если вы не очень тщательно дезинфицируете ввод ...
Обновление : вы, вероятно, захотите использовать решение DreamTeK ниже .
источник
contenteditable
предназначен для настройки текстового редактора WYSIWYG с форматированным текстом. Не для изменения размера входов.Изменить : теперь плагин работает с завершающими пробелами. Спасибо, что указали на это @JavaSpyder
Поскольку большинство других ответов не соответствовали тому, что мне было нужно (или просто не работало вообще), я изменил ответ Адриана Б на правильный плагин jQuery, который приводит к точному масштабированию ввода до пикселя, не требуя от вас изменения CSS или html.
Пример: https://jsfiddle.net/587aapc2/
Применение:
$("input").autoresize({padding: 20, minWidth: 20, maxWidth: 300});
Плагин:
//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});
источник
font
это сокращение CSS (как ни странно, FF не может с этим справиться ). Вы можете исправить это, определив в первой функции: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(' ');
. Тогда изменитесь,this.css('font')
чтобы быть_this_font
.У меня есть плагин jQuery на GitHub: https://github.com/MartinF/jQuery.Autosize.Input
Он отражает значение ввода, вычисляет ширину и использует ее для установки ширины ввода.
Здесь вы можете увидеть живой пример: http://jsfiddle.net/mJMpw/2175/
Пример того, как его использовать (потому что при публикации ссылки jsfiddle требуется некоторый код):
<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; }
Вы просто используете css, чтобы установить min / max-width и использовать переход по ширине, если хотите получить хороший эффект.
Вы можете указать расстояние / расстояние до конца как значение в нотации json для атрибута data-autosize-input в элементе ввода.
Конечно, вы также можете просто инициализировать его с помощью jQuery
$("selector").autosizeInput();
источник
Здесь уже есть много хороших ответов. Ради интереса я реализовал это решение ниже, основываясь на других ответах и моих собственных идеях.
<input class="adjust">
Элемент ввода настраивается с точностью до пикселя, и может быть определено дополнительное смещение.
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);
Регулировка сглаживается переходом CSS.
.adjust { transition: width .15s; }
Вот скрипка . Я надеюсь, что это поможет другим, ищущим чистое решение.
источник
Вместо того, чтобы пытаться создать div и измерить его ширину, я думаю, что более надежно измерить ширину напрямую, используя более точный элемент холста.
function measureTextWidth(txt, font) { var element = document.createElement('canvas'); var context = element.getContext("2d"); context.font = font; return context.measureText(txt).width; }
Теперь вы можете использовать это для измерения ширины некоторого элемента ввода в любой момент времени, выполнив следующие действия:
// 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);
Это возвращает число (возможно, с плавающей запятой). Если вы хотите учитывать заполнение, вы можете попробовать следующее:
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";
источник
Я нашел другое решение этой проблемы, не связанное с JS. В HTML я просто поместил что-то вроде:
<div> <input class="input" value={someValue} /> <div class="ghost-input">someValue</div> </div>
Все, что нужно, - это установить видимость: скрыто на ghost-input и width: 100% на самом входе. Это работает, потому что ввод масштабируется до 100% своего контейнера, ширина которого рассчитывается самим браузером (на основе того же текста).
Если вы добавите отступ и границу в поле ввода, вам придется соответствующим образом настроить свой класс ввода-призрака (или использовать calc () в классе ввода).
источник
Вы можете решить эту проблему как здесь :) 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');
источник
К сожалению, этот
size
атрибут будет работать не очень хорошо. Иногда будет слишком много места, в зависимости от того, как настроен шрифт. (посмотрите пример)Если вы хотите, чтобы это работало хорошо, попробуйте следить за изменениями на вводе и затем измените его размер. Вы, вероятно, захотите установить его на input
scrollWidth
. Нам также нужно будет учитывать размер коробки.В следующем примере я устанавливаю
size
для ввода значение 1, чтобы не допустить, чтобы он былscrollWidth
больше нашей начальной ширины (установлен вручную с помощью 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>
Я думаю, что это должно работать даже в IE6, но не верьте мне на слово.
В зависимости от вашего варианта использования вам может потребоваться привязать функцию настройки к другим событиям. Например, изменение значения ввода программно или изменение
display
свойства стиля элемента сnone
(гдеscrollWidth === 0
) наblock
илиinline-block
и т. Д.источник
У меня работает плагин jQuery:
Применение:
$('form input[type="text"]').autoFit({ });
Исходный код
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']);
источник
Элементы ввода ведут себя иначе, чем другие элементы, которые будут делать примерно то, что вы хотите, если вы им предоставите
float: left
(см. Http://jsfiddle.net/hEvYj/5/ ). Я не думаю, что это возможно без каких-либо вычислений с помощью JavaScript (т.е. добавление 5 пикселей к ширине каждой буквы в поле).источник
User nrabinowitz решение " работает прекрасно, но я использую
keypress
событие вместоkeyup
. Это снижает задержку, если пользователь печатает медленно.источник
oninput
(илиonpropertychange
для устаревшего IE) является правильным событием, поскольку они реагируют на такие вещи, как вставка щелчком правой кнопкой мыши или выбор «Файл -> Вставить» в строке меню браузераВот моя модификация nrabinowitz решения " . Я не использовал свойство размера , потому что оно не идеально подходит для пропорциональных шрифтов, как заметил @Mark. Мое решение помещает элемент после вашего ввода и получает ширину, подсчитываемую браузером (с использованием jQuery).
Хотя я не тестирую его, я полагаю, что он будет работать только в том случае, если все свойства CSS, влияющие на шрифт, унаследованы.
Ширина ввода изменяется при событии focusout , что для меня работает лучше. Но вы также можете использовать keyup / keypress для изменения ширины ввода при наборе текста.
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);
источник
Используя холст, мы можем рассчитать ширину элементов:
function getTextWidth(text, fontSize, fontName) { let canvas = document.createElement('canvas'); let context = canvas.getContext('2d'); context.font = fontSize + fontName; return context.measureText(text).width; }
и использовать его на выбранном мероприятии:
function onChange(e) { let width = getTextWidth(this.value, $(this).css('font-size'), $(this).css('font-family')); $(this.input).css('width', width); }
источник
попробуйте решение 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); });
источник
Я решил ширину, создав холст и рассчитав его размер. важно, чтобы входное значение и холст имели одинаковые функции шрифта (семейство, размер, вес ...)
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
источник