有没有办法将<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" />
答案 0 :(得分:76)
您可以通过将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/
这似乎在右侧添加了一些填充,我怀疑它是依赖于浏览器的。如果你希望它对输入非常紧张,你可以使用类似the one I describe in this related answer的技术,使用jQuery来计算文本的像素大小。
答案 1 :(得分:33)
如果由于某种原因其他解决方案不适合您,您可以使用contenteditable-span而不是输入元素。
<span contenteditable="true">dummy text</span>
请注意,这更像是一种黑客攻击,并且存在严重的缺点,即允许用户输入(并粘贴)换行符,链接和其他HTML,完全取消黑名单输入。
所以您可能不应该使用此解决方案,除非您非常仔细地清理输入...
更新:您可能想要使用Obsidian的solution below。
答案 2 :(得分:17)
我已经看过几种方法可以做到这一点,但计算字体的宽度并不总是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>
答案 3 :(得分:9)
编辑:该插件现在可以使用尾随空白字符。感谢你指出@JavaSpyder
由于大多数其他答案与我所需的答案相匹配(或根本没有完成工作) 我将Adrian B的答案修改为一个合适的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});
&#13;
<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});
&#13;
答案 4 :(得分:7)
我在GitHub上有一个jQuery插件: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设置最小/最大宽度并在宽度上使用过渡。
您可以指定结尾的空格/距离作为输入元素上data-autosize-input属性的json表示法中的值。
当然你也可以使用jQuery初始化它
$("selector").autosizeInput();
答案 5 :(得分:5)
这里已经有很多好的答案了。为了好玩,我在下面根据其他答案和我自己的想法实现了这个解决方案。
<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;
}
这是the fiddle。我希望这可以帮助其他人寻找一个干净的解决方案。
答案 6 :(得分:4)
我已经找到了不涉及JS的另一种解决方案。在HTML中,我只是输入以下内容:
<div>
<input class="input" value={someValue} />
<div class="ghost-input">someValue</div>
</div>
所需要做的只是设置可见性:隐藏在ghost输入上,宽度:100%输入本身。之所以起作用,是因为输入缩放到其容器的100%,容器的宽度由浏览器本身计算(基于相同的文本)。
如果在输入字段中添加一些填充和边框,则必须相应地调整幽灵输入类(或在输入类中使用calc())。
答案 7 :(得分:3)
你可以在这里解决这个问题:) 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');
答案 8 :(得分:3)
不幸的是size
属性效果不佳。有时会有额外的空间和太小的空间,具体取决于字体的设置方式。 (查看示例)
如果您希望此工作正常,请尝试观察输入的更改,然后调整其大小。您可能希望将其设置为输入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";
}
}
&#13;
* {
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;
}
&#13;
<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>
&#13;
我认为这应该适用于IE6,但不要接受我的话。
根据您的使用情况,您可能需要将adjust函数绑定到其他事件。例如。以编程方式更改输入值,或将元素的display
属性从none
(scrollWidth === 0
}更改为block
或inline-block
等等。
答案 9 :(得分:3)
我认为使用更准确的画布元素直接测量宽度,而不是尝试创建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";
答案 10 :(得分:1)
我的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']);
答案 11 :(得分:0)
用户nrabinowitz' solution效果很好,但我使用keypress
事件代替keyup
。如果用户输入缓慢,这可以减少延迟。
答案 12 :(得分:0)
以下是我对nrabinowitz' solution的修改。我没有使用 size 属性,因为@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);
答案 13 :(得分:0)
输入元素的行为与其他元素的行为不同,如果你给它们float: left
(参见http://jsfiddle.net/hEvYj/5/),它就可以满足您的需求。如果不用JavaScript以某种方式计算它,我认为这是不可能的(即在框中每个字母的宽度加5px)。
答案 14 :(得分:0)
使用画布我们可以计算元素宽度:
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);
}
答案 15 :(得分:0)
尝试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);
});
答案 16 :(得分:0)
我解决了创建画布并计算其尺寸的宽度。输入值和画布共享相同的字体特征(家庭,大小,粗细...)很重要
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
答案 17 :(得分:0)
您可以在此函数中传递任何 input
元素以获得元素的适当宽度。这个宽度就像 input
元素是一个 span
元素,具有原始元素的所有属性。它将考虑 font-family
、font-size
和所有其他可能影响文本总宽度以及 input
元素的水平边框和内边距的字体属性。此外,如果 input
元素中没有任何值,它将返回占位符的宽度。
因此,此宽度值将适用于设置 input
元素的宽度。在这种情况下,您可能还想为元素设置最小宽度,以防它既没有值也没有占位符。
此外,此函数的行为与 offsetWidth
属性有些相似,只是此函数会将 px
附加到宽度值的末尾,即使 input
元素通过将其 display
设置为 none
来隐藏,不会将该值四舍五入为整数,并且不会考虑垂直滚动条的宽度(如果有)。
function getInputWidth(element) {
const text = element.value || element.placeholder;
const elementStyle = window.getComputedStyle(element);
const fontProperty = elementStyle.font;
const horizontalBorder = parseFloat(elementStyle.borderLeftWidth) + parseFloat(elementStyle.borderRightWidth);
const horizontalPadding = parseFloat(elementStyle.paddingLeft) + parseFloat(elementStyle.paddingRight);
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
context.font = fontProperty;
const textWidth = context.measureText(text).width;
const totalWidth = horizontalBorder + horizontalPadding + textWidth + "px";
return totalWidth;
}