随着文本输入增加,增大输入字段的大小

5

我有一个相对简单的CSS问题。我有一个输入文本框,在页面加载时希望它的宽度为150px。

然而,当用户输入一些文本时,如果文本的宽度大于150px,则宽度应自动调整。

这是一个plunker:

http://plnkr.co/edit/ig0BQrJDiEtXKV8zJ2w2?p=preview

HTML:

<input class="input-class" type="text" placeholder="Placeholder">

CSS:

.input-class-2 {
  -moz-border-bottom-colors: none;
  -moz-border-left-colors: none;
  -moz-border-right-colors: none;
  -moz-border-top-colors: none;
  border-color: -moz-use-text-color -moz-use-text-color #ef8e80;
  border-image: none;
  border-style: none none dashed;
  border-width: 0 0 1px;
  color: #ef8e80;
  cursor: pointer;
  font-family: Gotham-Book;
  font-size: 18px;
  min-width: 150px;
}

我认为min-width会做到这一点。


您可以使用JavaScript监视键盘事件,并随着用户输入内容的变化调整输入大小。 - Morb
1
最好使用自动扩展文本区域/输入的库或插件。这里有一个问题可以帮助你: https://dev59.com/SHNA5IYBdhLWcg3wgeOk - Tony Barnes
就像@Morb所说的那样,我怀疑你无法在不使用javascript的情况下实现该效果。 - Joel Almeida
1
@Akshay - 是的,可以使用jQuery。 - Oam Psy
4个回答

7

目前,使用纯CSS无法实现此操作,也许一旦可以结合使用calcattr,但目前还不行。因此,我们必须退回到JavaScript。

没有什么真正的理由使用jQuery。你可以认为你的“关注点应该分离”,即代码应该与标记分开,但使用addEventListener很容易做到。然而,如果我正在处理一些小的JavaScript代码,使用内联事件监听程序往往更快-在实现、页面渲染甚至对那些试图追踪使输入表现奇怪的原因的人来说都是如此。

<input type="text" 
       style="min-width: 150px;" 
       onkeyup="this.size = Math.max(this.value.length, 1)" 
/>

或者:

<input type="text" 
       style="width: 150px;" 
       onkeyup="
         this.style.width = '1px';
         this.style.width = (
             this.scrollWidth &gt; 140
           ? this.scrollWidth + 10
           : 150
         )+'px';
       " 
/>

免责声明:显然,如果您正在实现许多此类输入,则编写一个通用函数来处理它们要好得多。此外,通过使用样式表避免内联样式始终更好。
/**
 * Directly setting the size attribute, with minWidth
 */
function autosize(elm, minWidth){
  var keyup = function(e){
    var t = e.target || e.srcElement;
    var v = Math.max(t.value.length, 1);
    t.setAttribute
      ? t.setAttribute('size', v)
      : (t['size'] = v)
    ;
  };
  elm.style.minWidth = minWidth+'px';
  elm.addEventListener
    ? elm.addEventListener('keyup', keyup)
    : elm.attachEvent('onkeyup', keyup)
  ;
};

尺寸属性是迄今为止最明显的选择,虽然您可以直接使用scrollWidth设置宽度——如果您愿意的话。

/**
 * Directly setting width, with minWidth
 */
function autosize(elm, minWidth){
  var keyup = function(e){
    var t = e.target || e.srcElement;
    t.style.width = '1px';
    t.style.width = t.scrollWidth + 'px';
  };
  elm.style.minWidth = minWidth+'px';
  elm.addEventListener
    ? elm.addEventListener('keyup', keyup)
    : elm.attachEvent('onkeyup', keyup)
  ;
};

您可以通过将您的目标元素作为第一个参数传递来触发这两个函数。有许多方法可以找到您的元素,最简单且最通用的方法是使用getElementById。但是,只有在浏览器解析了您的元素后才能找到它,因此您使用的脚本标签 - 用于运行以下代码的标签 - 要么放置在标记中的元素下面,即 <body> 的底部(更可取),要么等待窗口加载或DOM准备就绪后再使用。
autosize( document.getElementById('myinput'), 150 );

/**
 * Directly setting width, with minWidth
 */
function autosize1(elm, minWidth){
  var keyup = function(e){
    var t = e.target || e.srcElement;
    t.style.width = '1px';
    t.style.width = t.scrollWidth + 'px';
  };
  elm.style.minWidth = minWidth+'px';
  elm.addEventListener
    ? elm.addEventListener('keyup', keyup)
    : elm.attachEvent('onkeyup', keyup)
  ;
};

/**
 * Directly setting the size attribute, with minWidth
 */
function autosize2(elm, minWidth){
  var keyup = function(e){
    var t = e.target || e.srcElement;
    var v = Math.max(t.value.length, 1);
    t.setAttribute
      ? t.setAttribute('size', v)
      : (t['size'] = v)
    ;
  };
  elm.style.minWidth = minWidth+'px';
  elm.addEventListener
    ? elm.addEventListener('keyup', keyup)
    : elm.attachEvent('onkeyup', keyup)
  ;
};

autosize1( document.getElementById('a'), 150 );
autosize2( document.getElementById('b'), 150 );
<p>Each input is using a different implementation:</p>
<input type="text" 
       style="min-width: 150px;" 
       onkeyup="this.size = Math.max(this.value.length, 1)" 
/><br />
<input type="text" 
       style="width: 150px;" 
       onkeyup="
         this.style.width = '1px';
         this.style.width = (
             this.scrollWidth &gt; 140
           ? this.scrollWidth + 10
           : 150
         )+'px';
       " 
/><br />
<input type="text" id="a" /><br />
<input type="text" id="b" /><br />


为什么你使用keyup和keydown输入而不是oninput? - Persijn
1
@Persijn ~ 很好的问题。纯粹为了支持,oninput 从 IE9 开始就被支持了。对于我的一些项目,我仍然需要支持 IE8(幸运的是不再需要支持 IE6)。你可以很愉快地切换到使用 oninput 或两者都使用。 - Pebbl

2
你可以试试这样做:
function resizeInput() {
    $(this).attr('size', $(this).val().length);
}

$('input[type="text"]')
    .keyup(resizeInput)
    .each(resizeInput);

JSFIDDLE演示

使用 JavaScript 的另一种选择是

<span contenteditable="true">Some Text</span>

使用Input标签的替代方法。

JSFIDDLE DEMO


1
你可以尝试像这样的东西。

$('.input-class').keyup(function(){
    var textlength=$('.input-class').val().length
    $(this).width(textlength * 8)
})
.input-class{
  -moz-border-bottom-colors: none;
  -moz-border-left-colors: none;
  -moz-border-right-colors: none;
  -moz-border-top-colors: none;
  border-color: -moz-use-text-color -moz-use-text-color #ef8e80;
  border-image: none;
  border-style: none none dashed;
  border-width: 0 0 1px;
  color: #ef8e80;
  cursor: pointer;
  font-family: Gotham-Book;
  font-size: 18px;
  min-width: 150px;
    width:auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<input class="input-class" type="text" placeholder="Placeholder">


这个解决方案还可以,除了你已经硬编码了字体的宽度。这可能会因设备而异,字体支持也可能不同,因此自动测量所需宽度的版本会更好。 - Pebbl
你的方法并没有差太多,对于大多数情况下,像你所做的那样猜测字体的宽度就足够了。如果你感兴趣的话,你可以使用这个新的度量单位来改进你的版本(至少适用于现代浏览器):https://developer.mozilla.org/en/docs/Web/CSS/length#ch - Pebbl
@Pebbl 谢谢,我会看一下的。 - Akshay

1
尝试使用纯JavaScript。我隐藏了一个对用户不可见的span元素(visibility:hidden;)。然后计算渲染宽度,并将其设置为输入容器的大小。
将输入设为width:100%;,使其扩展到其父元素的大小。

var field = document.getElementById("grow");
field.oninput = function() {
  var ruler = document.getElementById("ruler");
  ruler.innerHTML = field.value.replace(/ /g,"&nbsp;");
  var outer = document.getElementById("outer");
  if (ruler.offsetWidth > 100) {
    outer.setAttribute('style', "width:" + (ruler.offsetWidth + 5) + "px;");
  } else {
    outer.setAttribute('style', "");
  }
};
#grow {
  height: 100%;
  width: 100%;
  font-size: inherit;
  font-family: inherit;
}
#outer {
  width: 100px;
  font-size: 1rem;
  font-family: Serif, "Times New Roman", Georgia;
}
.hidden {
  position: absolute;
  display: inline;
  visibility: hidden;
  padding: 0;
  font-size: inherit;
  font-family: inherit;
  white-space: nowrap;
}
<div id="outer">
  <span id="ruler" class="hidden"></span>
  <input id="grow" type="text/plain"/>
</div>
<p>+ Expands</p>
<p>+ shrinks</p>
<p>+ whitespace handling</p>


1
不错的测量想法,但是为了使其正常工作,输入和span的字体和字号必须完全相同。一个令人烦恼的问题一直困扰着我,就是无法将一个元素类型的默认值应用到另一个元素类型上;因此修复这个问题的唯一方法(因为无法从不支持子元素的元素继承,即输入)是明确指定字体和字号,使用固定或类似比例的单位。您还可以让代码允许输入缩小,当前如果删除字符,则不会变小。 - Pebbl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接