Điều chỉnh độ rộng của trường đầu vào với đầu vào của nó


170
<html>
  <head>
  </head>
  <body>
    <input type="text" value="1" style="min-width:1px;" />
  </body>
</html>

Đây là mã của tôi và nó không hoạt động. Có cách nào khác trong HTML, JavaScript, PHP hoặc CSS để đặt độ rộng tối thiểu không?

Tôi muốn một trường nhập văn bản có chiều rộng thay đổi động, để trường đầu vào trôi chảy xung quanh nội dung của nó. Mỗi đầu vào đều có phần đệm tích hợp 2em, đó là vấn đề và vấn đề thứ hai là nó hoàn toàn min-widthkhông hoạt động với đầu vào.

Nếu tôi đặt chiều rộng nhiều hơn mức cần thiết thì toàn bộ chương trình sẽ lộn xộn, tôi cần chiều rộng 1px, chỉ nhiều hơn nếu cần.


Điều này có trả lời câu hỏi của bạn không? Tạo một textarea với tự động thay đổi kích thước
DreamTeK

Câu trả lời:


96

Có vẻ như kỳ vọng của bạn là phong cách được áp dụng linh hoạt cho chiều rộng của hộp văn bản dựa trên nội dung của hộp văn bản. Nếu vậy, bạn sẽ cần một số js để chạy trên nội dung hộp văn bản thay đổi, đại loại như thế này :

<input id="txt" type="text" onkeypress="this.style.width = ((this.value.length + 1) * 8) + 'px';">

Lưu ý: giải pháp này chỉ hoạt động khi mỗi ký tự chính xác 8pxrộng.


41
@Kerc & Tahbaza: có, nhưng điều này sẽ chỉ hoạt động nếu chiều rộng của mỗi ký tự chính xác là 8 pixel.
Marcel Korpel

6
Tôi đồng ý, Marcel (và mã được đăng không phải là thứ tôi có thể thấy thực sự sử dụng) nhưng nó thể hiện hành vi mong muốn. Bạn có biết làm thế nào để tính chiều rộng thực tế của văn bản được hiển thị có tính đến phông chữ, kích thước, trọng lượng, độ sáng, v.v. không? Nếu vậy, xin vui lòng chia sẻ vì tôi sẽ thấy rằng một chút mã hữu ích.
Tahbaza

1
- Tôi đã nghĩ rằng đó chỉ là một ví dụ. Tuy nhiên, không khó để tính chiều rộng của đầu vào. Hãy nhìn vào câu trả lời của tôi.
Marcel Korpel

đơn vị em là chiều rộng của ký tự "m". Điều này sẽ hữu ích cho việc tính toán độ rộng của chuỗi. Tôi đã thấy các sự cố trình duyệt chéo với các đơn vị em được áp dụng cho một số thuộc tính mặc dù vậy cũng nên kiểm tra nó.
Archonic

7
bạn đã quên sự kiện PASTE, bạn của tôi;) bạn nên đổi nó thànhonInput
vsync

114

Trong các phiên bản trình duyệt hiện đại, đơn vị CSS chcũng có sẵn. Theo hiểu biết của tôi, nó là đơn vị độc lập với phông chữ, trong đó 1chbằng với chiều rộng của ký tự 0(không) trong bất kỳ phông chữ nào.

Do đó, một cái gì đó đơn giản như sau có thể được sử dụng như chức năng thay đổi kích thước:

var input = document.querySelector('input'); // get the input element
input.addEventListener('input', resizeInput); // bind the "resizeInput" callback on "input" event
resizeInput.call(input); // immediately call the function

function resizeInput() {
  this.style.width = this.value.length + "ch";
}
input{ font-size:1.3em; padding:.5em; }
<input>

Ví dụ đó sẽ thay đổi kích thước "elem" thành chiều dài của giá trị + thêm 2 ký tự.


13
Tôi ngạc nhiên khi nhận xét này không được bình chọn cao hơn, bởi vì đây là một giải pháp tuyệt vời và khoảng 95% ( 1 ) trình duyệt hỗ trợ điều này.
Husky

8
Đây hoàn toàn không phải là một câu trả lời hay, vì phép đo không chính xác và không tính đến các kiểu tài khoản có thể xảy ra trên inputphần tử, chẳng hạn như font-style, letter-spacingv.v. Tôi đã chỉnh sửa câu trả lời bằng bản demo trực tiếp.
vsync

5
Hoạt động tuyệt vời nếu bạn sử dụng một phông chữ đơn cách. Với các phông chữ khác, số dặm của bạn có thể thay đổi vì nó sử dụng độ rộng ký tự của ký tự 0 rõ ràng.
Jilles van Gurp

2
Điều này thực sự tuyệt vời. Mặc dù lưu ý rằng đôi khi nó bị lỗi / không hoạt động như tôi mong đợi khi .gặp phải.
Rishav

1
Điều này hoạt động hoàn hảo nếu bạn đặt kích thước hộp trên đầu vào thành 'hộp nội dung'. Bằng cách đó, nó bỏ qua phần đệm khi bạn đặt kích thước.
Hypersapien

65

Để tính chiều rộng của đầu vào hiện tại, bạn sẽ phải nhúng nó vào một spanphần tử tạm thời , gắn vật đó vào DOM, lấy chiều rộng được tính toán (tính bằng pixel) bằng cách sử dụng thuộc scrollWidthtính và xóa spanlại. Tất nhiên, bạn sẽ phải đảm bảo rằng cùng một họ phông chữ, cỡ chữ, v.v., được sử dụng trong phần tử inputcũng như trong spanphần tử. Vì vậy, tôi đã giao cùng một lớp cho họ.

Tôi đã gắn chức năng này vào keyupsự kiện, vì trên keypresský tự đầu vào chưa được thêm vào đầu vào value, do đó sẽ dẫn đến độ rộng sai. Thật không may, tôi không biết làm thế nào để thoát khỏi việc cuộn trường nhập liệu (khi thêm ký tự vào cuối trường); nó cuộn, bởi vì ký tự được thêm vào và hiển thị trước adjustWidthOfInput()được gọi. Và, như đã nói, tôi không thể làm điều này theo cách khác bởi vì sau đó bạn sẽ có giá trị của trường nhập trước khi ký tự được nhấn. Tôi sẽ cố gắng giải quyết vấn đề này sau.

BTW, tôi chỉ thử nghiệm điều này trong Firefox (3.6.8), nhưng tôi sẽ nhận được điểm, tôi hy vọng.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Get/set width of &lt;input&gt;</title>
    <style>
      body {
        background: #666;
      }

      .input-element {
        border: 0;
        padding: 2px;
        background: #fff;
        font: 12pt sans-serif;
      }

      .tmp-element {
        visibility: hidden;
        white-space: pre;
      }
    </style>
  </head>
  <body>
    <input id="theInput" type="text" class="input-element" value="1">
    <script>
      var inputEl = document.getElementById("theInput");

      function getWidthOfInput() {
        var tmp = document.createElement("span");
        tmp.className = "input-element tmp-element";
        tmp.innerHTML = inputEl.value.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
        document.body.appendChild(tmp);
        var theWidth = tmp.getBoundingClientRect().width;
        document.body.removeChild(tmp);
        return theWidth;
      }

      function adjustWidthOfInput() {
        inputEl.style.width = getWidthOfInput() + "px";
      }

      adjustWidthOfInput();
      inputEl.onkeyup = adjustWidthOfInput;
    </script>
  </body>
</html>

Tôi thích câu trả lời của bạn và thậm chí đã triển khai nó bằng jQuery / Underscore: gist.github.com/3745941 . Tuy nhiên, tôi có thể đưa ra một số giả định nhất định: (1) chiều rộng của bất kỳ ký tự nào không quá 14px, (2) có thể chấp nhận được phần tử đầu vào mở rộng 14px vượt quá giá trị của phần tử. Tôi có điều này gắn liền với một sự kiện keydown và nó hoạt động rất tốt!
Nathan

11
Bạn nên thêm white-space: pre;vào css theo cách này : .tmp-element{ visibility: hidden; white-space: pre;}. Mặt khác, khoảng trắng được kết hợp và tính toán độ rộng không thành công. <input><span>hành xử khác nhau liên quan đến xử lý không gian trắng, <input>giữ lại các khoảng trắng và <span>kết hợp các khoảng trắng tuần tự thành một nếu white-space: pre;không được thêm vào.
Timo Kähkönen

2
tmp.getBoundingClientRect().widthtốt hơn tmp.scrollWidth, bởi vì đôi khi trả về 0
lisak

@lisak Cảm ơn, tôi đã điều chỉnh câu trả lời của mình, nhưng đã có câu trả lời tốt hơn ở đây.
Marcel Korpel

Tốt hơn? Tôi sẽ không nói như vậy. Câu trả lời được đánh dấu thiếu độ chính xác, những người khác (+ ở đây 1ở đây 2 ) sử dụng jQuery - Tôi không vì React. Canvas không thể cung cấp cho bạn chiều cao văn bản AFAIK. Ý tưởng: vấn đề với không gian cũng có thể được giải quyết với:.replace(/ /g, "&nbsp;")
Milan Jaros

30

Đây là một sửa đổi của câu trả lời của Lyth có tính đến:

  • Xóa
  • Khởi tạo
  • Giữ chỗ

Nó cũng cho phép bất kỳ số lượng các trường đầu vào! Để xem nó trong hành động: http://jsfiddle.net/4Qsa8/

Kịch bản:

$(document).ready(function () {
    var $inputs = $('.resizing-input');

    // Resize based on text if text.length > 0
    // Otherwise resize based on the placeholder
    function resizeForText(text) {
        var $this = $(this);
        if (!text.trim()) {
            text = $this.attr('placeholder').trim();
        }
        var $span = $this.parent().find('span');
        $span.text(text);
        var $inputSize = $span.width();
        $this.css("width", $inputSize);
    }

    $inputs.find('input').keypress(function (e) {
        if (e.which && e.charCode) {
            var c = String.fromCharCode(e.keyCode | e.charCode);
            var $this = $(this);
            resizeForText.call($this, $this.val() + c);
        }
    });

    // Backspace event only fires for keyup
    $inputs.find('input').keyup(function (e) { 
        if (e.keyCode === 8 || e.keyCode === 46) {
            resizeForText.call($(this), $(this).val());
        }
    });

    $inputs.find('input').each(function () {
        var $this = $(this);
        resizeForText.call($this, $this.val())
    });
});

Phong cách:

.resizing-input input, .resizing-input span {
    font-size: 12px;
    font-family: Sans-serif;
    white-space: pre;
    padding: 5px;
}

HTML:

<div class="resizing-input">
    <input type="text" placeholder="placeholder"/>
    <span  style="display:none"></span>
</div>


Chào Michael. Mã của bạn hoạt động rất tốt nhưng tôi có một vấn đề. Một trong những lĩnh vực của tôi là một trường tự động tìm địa điểm của Google. Và khi tôi chọn đúng địa chỉ từ menu thả xuống, độ rộng của trường nhập không bị thay đổi theo độ dài của địa chỉ đã chọn. Có một sửa chữa đơn giản cho nó?
Tối đa

2
@Maxence nghe changehoặc inputsự kiện sẽ đủ
yarwest

Tôi gặp vấn đề với màn hình của span: không có kiểu dáng nào vì nó đã đăng ký khoảng là 0 chiều rộng. Tốt hơn để sử dụng định vị tuyệt đối với khả năng hiển thị: ẩn cho nhịp.
jayt

Xin chào @yarwest, cảm ơn vì tiền boa. Bạn có biết làm thế nào để điều chỉnh tập lệnh gốc với thiết lập này không? (kiến thức của tôi về Js / jquery rất rất hạn chế)
Maxence

21

Đây là một giải pháp không cần phông chữ đơn cách , chỉ với đoạn mã javascript rất nhỏ , không cần tính toán các kiểu tính toán và thậm chí hỗ trợ ime , hỗ trợ các văn bản rtl .

// copy the text from input to the span
    $(function () {
      $('.input').on('input', function () { $('.text').text($('.input').val()); });
    });
    * {
      box-sizing: border-box;
    }
    
    .container {
      display: inline-block;
      position: relative;
    }
    
    .input,
    .text {
      margin: 0;
      padding: 2px 10px;
      font-size: 24px;
      line-height: 32px;
      border: 1px solid #ccc;
      box-radius: 3px;
      height: 36px;
      font: 20px/20px sans-serif;
      /* font: they should use same font; */
    }

    .text {
      padding-right: 20px;
      display: inline-block;
      visibility: hidden;
      white-space: pre;
    }
    
    .input {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      width: 100%;
    }
    
<script src="https://code.jquery.com/jquery-3.2.0.min.js"></script>

<div class="container">
  <span class="text">
    some text
  </span>
  <input class="input" value="some text" />
</div>

Sử dụng span.textđể phù hợp với chiều rộng của văn bản và để đầu vào có cùng kích thước với nó bằng cách position: absolutechứa. Sao chép giá trị của đầu vào vào spanmỗi lần thay đổi (bạn có thể thay đổi đoạn mã này thành vanilla js một cách dễ dàng). Vì vậy, đầu vào sẽ chỉ "phù hợp" với kích thước của nội dung của nó.


18

CHO MỘT CUỐN SÁCH & CẢM NHẬN

Bạn nên sử dụng sự kiện keypress () của jQuery kết hợp với String.fromCharCode (e.which) để lấy ký tự được nhấn. Do đó bạn có thể tính toán chiều rộng của bạn sẽ là gì . Tại sao? Bởi vì nó sẽ trông gợi cảm hơn rất nhiều :)

Dưới đây là một jsfiddle dẫn đến một hành vi đẹp so với các giải pháp sử dụng sự kiện keyup: http://jsfiddle.net/G4FKW/3/

Dưới đây là một vanilla JS lắng nghe inputsự kiện của một <input>phần tử và đặt spananh chị em có cùng giá trị văn bản để đo lường nó.

document.querySelector('input').addEventListener('input', onInput)

function onInput(){
    var spanElm = this.nextElementSibling;
    spanElm.textContent = this.value; // the hidden span takes the value of the input; 
    this.style.width = spanElm.offsetWidth + 'px'; // apply width of the span to the input
};
/* it's important the input and its span have same styling */
input, .measure {
    padding: 5px;
    font-size: 2.3rem;
    font-family: Sans-serif;
    white-space: pre; /* white-spaces will work effectively */
}

.measure{  
  position: absolute;
  left: -9999px;
  top: -9999px;
}
<input type="text" />
<span class='measure'></span>


1
Có vẻ tốt, nhưng nó không đưa Backspace và Xóa vào tài khoản.
Marcel Korpel

Vâng, đối với điều này, bạn cần sự kiện keydown. Bạn có thể thêm xử lý cụ thể cho backspace và xóa bằng cách làm như vậy (e.which === 46 để xóa, e.which === 8 cho backspace). Nhưng bạn vẫn cần sự kiện nhấn phím để có quyền truy cập vào e.charCode cho phần còn lại.
Lyth

Nếu bạn không hỗ trợ IE8, bạn có thể sử dụng sự kiện oninput thay vì kiểm tra e.which: developer.mozilla.org/en-US/docs/Web/Events/input
Frinsh

1
Tôi đã chỉnh sửa câu trả lời của bạn để loại bỏ jQuery và chỉ sử dụng vanilla JS. lưu ý rằng giải pháp này không tối ưu vì bạn muốn một giải pháp chung không liên quan đến việc mã hóa thủ công a spanvà css cho nó.
vsync

17

Đây là một câu trả lời dành riêng cho Angular, nhưng điều này hiệu quả với tôi và đã rất thỏa mãn về tính đơn giản và dễ sử dụng của nó:

<input [style.width.ch]="value.length" [(ngModel)]="value" />

Nó tự động cập nhật thông qua các đơn vị nhân vật trong câu trả lời của Jani .


3
Điều này. Là. Sử thi.
Daniel Flippance

Nghiêm túc. Huyền diệu.
DongBin Kim

12

Đây là một cách khác để giải quyết vấn đề này bằng cách sử dụng DIV và thuộc tính 'có thể di chuyển nội dung':

HTML:

<div contenteditable = "true" class = "fluidInput" data-placeholder = ""></div>

CSS: (để cung cấp cho DIV một số kích thước và giúp dễ nhìn hơn)

.fluidInput {

    display         : inline-block;
    vertical-align  : top;

    min-width       : 1em;
    height          : 1.5em;

    font-family     : Arial, Helvetica, sans-serif;
    font-size       : 0.8em;
    line-height     : 1.5em;

    padding         : 0px 2px 0px 2px;
    border          : 1px solid #aaa;
    cursor          : text;
}


.fluidInput * {

    display         : inline;

}


.fluidInput br  {

    display         : none;

}


.fluidInput:empty:before {

    content         : attr(data-placeholder);
    color           : #ccc;

}

Lưu ý: Nếu bạn dự định sử dụng phần tử FORM này mà bạn dự định gửi, bạn sẽ cần sử dụng Javascript / jQuery để bắt sự kiện gửi để bạn có thể phân tích 'giá trị' ( .innerHTMLhoặc .html()tương ứng) của DIV.


1
Điều này xứng đáng được nâng cao hơn. Thật thanh lịch và đơn giản (miễn là sử dụng JS để xác thực mẫu không phải là vấn đề đối với bạn).
Daniel Bonell

2
Nhưng nó không phải là một đầu vào!
Toni Michel Caubet

8

Bạn cũng có thể đặt chiều rộng của đầu vào bằng thuộc tính kích thước . Kích thước của một đầu vào xác định chiều rộng của nó bằng ký tự.

Một đầu vào có thể tự động điều chỉnh kích thước của nó bằng cách lắng nghe các sự kiện chính.

Ví dụ

$("input[type='text']").bind('keyup', function () {
    $(this).attr("size", $(this).val().length );
});

JsFiddle ở đây


7

Bạn có thể làm một cái gì đó như thế này

// HTML
<input id="input" type="text" style="width:3px" />
// jQuery
$(function(){
  $('#input').keyup(function(){
    $('<span id="width">').append( $(this).val() ).appendTo('body');
    $(this).width( $('#width').width() + 2 );
    $('#width').remove();
  });
});

Hay nói, là một tài tài của, qua, qua, qua một tài khác, qua giữ, qua một tài khác

Hay nói, là một tài tài của, qua, qua, qua một tài khác, qua giữ, qua một tài khác


Nếu bạn tăng kích thước khi gõ phím, nó sẽ dẫn đến một hành vi xấu. Đầu vào cần phải tăng kích thước của nó ngay trước khi nhân vật đi vào nó để thoải mái hơn.
Lyth

5

Chỉ cần thêm vào đầu câu trả lời khác.

Tôi nhận thấy rằng ngày nay trong một số trình duyệt, trường nhập liệu có scrollWidth. Nghĩa là:

this.style.width = this.scrollWidth + 'px';

nên làm việc tốt thử nghiệm trong chrome, firefox và safari.

Để hỗ trợ xóa, bạn có thể thêm '= 0' trước rồi điều chỉnh lại.

this.style.width = 0; this.style.width = this.scrollWidth + 'px';

3
Vui lòng thêm mã có liên quan ở đây - liên kết có thể bị chết trong tương lai và sau đó bài đăng này là vô ích.
Uooo

3
Điều này làm việc tuyệt vời, cảm ơn! Tôi không biết tại sao câu trả lời này không có nhiều sự ủng hộ hơn. Đó là giải pháp đơn giản nhất, ít chiếm dụng (js).
Mẫu

4

Dưới đây là một JS đơn giản và một plugin jQuery mà tôi đã viết sẽ xử lý thay đổi kích thước phần tử đầu vào bằng cách sử dụng canvas và kích thước phông chữ / họ để xác định độ dài chuỗi thực tế khi được hiển thị. (chỉ hoạt động trong> IE9, chrome, safari, firefox, opera và hầu hết các trình duyệt chính khác đã triển khai phần tử canvas).

Đồng bằng:

function autoSize(input, o) {
    o || (o = {});
    o.on || (o.on = 'keyup');

    var canvas = document.createElement('canvas');
    canvas.setAttribute('style', 'position: absolute; left: -9999px');
    document.body.appendChild(canvas);

    var ctx = canvas.getContext('2d');

    input.addEventListener(o.on, function () {
        ctx.font = getComputedStyle(this,null).getPropertyValue('font');
        this.style.width = ctx.measureText(this.value + '  ').width + 'px';
    });
}

//Usage
autoSize(document.getElementById('my-input'));

Plugin jQuery:

$.fn.autoSize = function(o) {
  o = $.extend({}, {
    on: 'keyup'
  }, o);

  var $canvas = $('<canvas/>').css({position: 'absolute', left: -9999});
  $('body').append($canvas);

  var ctx = $canvas[0].getContext('2d');

  return this.on(o.on, function(){
    var $this = $(this);
    ctx.font = $this.css('font');
    $this.width(ctx.measureText($this.val()).width + 'px');
  })
}

//Usage:
$('#my-input').autoSize();

Lưu ý: điều này sẽ không xử lý các biến đổi văn bản, khoảng cách dòng và khoảng cách chữ và có thể một số thuộc tính thay đổi kích thước văn bản khác. Để xử lý tập thuộc tính biến đổi văn bản và điều chỉnh giá trị văn bản cho phù hợp với thuộc tính đó. Những người khác có lẽ là khá thẳng về phía trước. Tôi sẽ thực hiện nếu điều này bắt đầu đạt được một số lực kéo ...


4

Điều đáng chú ý là thay đổi kích thước đẹp mắt có thể được thực hiện khi phông chữ được đơn cách hóa, vì vậy chúng ta có thể thay đổi kích thước inputphần tử một cách hoàn hảo bằng cách sử dụngch đơn vị.

Cũng trong cách tiếp cận này, chúng tôi có thể cập nhật độ rộng của trường bằng cách chỉ cập nhật biến CSS (thuộc tính tùy chỉnh ) trên inputsự kiện và chúng tôi cũng nên quan tâm đến đầu vào đã được điền sẵn vào DOMContentLoadedsự kiện

Bản demo Codepen


Đánh dấu

<input type="text" value="space mono font" class="selfadapt" />

CSS

:root { --size: 0; }

.selfadapt {
   padding: 5px;
   min-width: 10ch;
   font-family: "space mono";
   font-size: 1.5rem;
   width: calc(var(--size) * 1ch);
}

Là một biến gốc mà chúng ta đặt --size: 0: biến này sẽ chứa độ dài của đầu vào và nó sẽ được nhân với 1chbên trongcalc() biểu thức. Theo mặc định, chúng tôi cũng có thể đặt chiều rộng tối thiểu, ví dụ:10ch

Phần Javascript đọc độ dài của giá trị được chèn và cập nhật biến --size :

Mã não

let input = document.querySelector('.selfadapt');
let root  = document.documentElement.style;

/* on input event auto resize the field */
input.addEventListener('input', function() {
   root.setProperty('--size', this.value.length );
});

/* resize the field if it is pre-populated */
document.addEventListener("DOMContentLoaded", function() {
   root.setProperty('--size', input.value.length);
});

tất nhiên điều này vẫn hoạt động ngay cả khi bạn không sử dụng phông chữ đơn cách, nhưng trong trường hợp đó, bạn sẽ cần thay đổi calc()công thức bằng cách nhân --sizebiến với giá trị khác (nó phụ thuộc hoàn toàn vào font-familyfont-size) khác với 1ch.


3

Câu trả lời này cung cấp một trong những phương pháp lấy độ rộng văn bản chính xác nhất có sẵn trong trình duyệt và chính xác hơn câu trả lời được chấp nhận. Nó sử dụng phần tử canvas html5 và không giống như các câu trả lời khác không thêm phần tử vào DOM và do đó tránh mọi vấn đề về dòng chảy lại do thêm quá nhiều phần tử vào DOM.

Đọc thêm về phần tử Canvas ở đây liên quan đến chiều rộng văn bản.

LƯU Ý: Theo MDN, các phiên bản tốc ký của getPropertyValue()phương thức như phông chữ có thể không đáng tin cậy. Tôi khuyên bạn nên lấy các giá trị đơn lẻ để cải thiện khả năng tương thích. Tôi chỉ sử dụng nó ở đây cho tốc độ.

/**
 * returns the width of child text of any DOM node as a float
 */
function getTextWidth(el) {
  // uses a cached canvas if available
  var canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas"));
  var context = canvas.getContext("2d");
  // get the full font style property
  var font = window.getComputedStyle(el, null).getPropertyValue('font');
  var text = el.value;
  // set the font attr for the canvas text
  context.font = font;
  var textMeasurement = context.measureText(text);
  return textMeasurement.width;
}

var input = document.getElementById('myInput');
// listen for any input on the input field
input.addEventListener('input', function(e) {
  var width = Math.floor(getTextWidth(e.target));
  // add 10 px to pad the input.
  var widthInPx = (width + 10) + "px";
  e.target.style.width = widthInPx;
}, false);
#myInput {
  font: normal normal 400 normal 18px / normal Roboto, sans-serif;
  min-width: 40px;
}
<input id="myInput" />


2

Bạn có thể làm điều đó thậm chí đơn giản hơn trong angularjs bằng cách sử dụng lệnh ng-style tích hợp .

Trong html của bạn:

  <input ng-style="inputStyle(testdata)" ng-model="testdata" />

Trong bộ điều khiển của bạn:

 $scope.testdata = "whatever";

 $scope.inputStyle = function(str) {
    var charWidth = 7;
    return  {"width": (str.length +1) * charWidth + "px" };
    };

Trong css của bạn:

input { font-family:monospace; font-size:12px; }

Điều chỉnh charWidth để phù hợp với chiều rộng của phông chữ của bạn. Nó dường như là 7 ở cỡ chữ 12px;


3
Điều này thật tuyệt vời và tiện dụng để biết, nhưng việc thêm angularjs vào một ứng dụng để tự động thay đổi kích thước một yếu tố đầu vào thực sự quá mức cần thiết, đặc biệt là khi OP yêu cầu các giải pháp "HTML, JavaScript, PHP hoặc CSS". Người ta có thể lập luận rằng jQuery cũng quá mức cho việc này, nhưng - không giống như Angular - là một bộ công cụ thao tác DOM là cốt lõi cho mục đích của jQuery.
vlasits

Làm thế nào tôi có thể biết chiều rộng của nhân vật được gõ? Thật không dễ dàng để giả định nó là một phông chữ đơn sắc.
Ethan

1
Bạn không thể yêu cầu một phông chữ đơn cách và không cần Angular. Câu trả lời của brendan về cơ bản là giống nhau.
Dan Dascalescu

2

Nếu bạn sử dụng Bootstrap, nó có thể được thực hiện rất dễ dàng:

<div contenteditable="true" class="form-control" style="display: inline"></div>

Bạn sẽ chỉ cần tìm nạp nội dung của div và đặt nó vào một đầu vào ẩn trước khi gửi biểu mẫu.


1

Tôi nghĩ rằng bạn đang hiểu sai về thuộc tính CSS chiều rộng tối thiểu . chiều rộng tối thiểu thường được sử dụng để xác định chiều rộng DOM tối thiểu trong bố cục chất lỏng, như:

input {
  width: 30%;
  min-width: 200px;
}

Điều đó sẽ đặt phần tử đầu vào thành chiều rộng tối thiểu 200 pixel. Trong ngữ cảnh này, "px" là viết tắt của "pixel".

Bây giờ, nếu bạn đang cố kiểm tra để đảm bảo rằng trường đầu vào chứa ít nhất một ký tự khi người dùng gửi nó, bạn sẽ cần thực hiện một số xác thực mẫu bằng JavaScript và PHP. Nếu đó thực sự là những gì bạn đang cố gắng thực hiện, tôi sẽ chỉnh sửa câu trả lời này và cố gắng hết sức để giúp bạn.


Tôi biết px có nghĩa là gì và tôi biết javascript có chức năng cho độ rộng tối thiểu nhưng nó không hoạt động cho văn bản đầu vào.
Kerc

1
@Kerc: javascript có chức năng dành cho min-width - cái nào? Ý anh là gì? - Đây không phải là một mô tả tốt về vấn đề. Cố gắng xây dựng trên hành vi dự định.
Marcel Korpel

Bạn thậm chí đã thử ví dụ của tôi, hơn bạn thấy rằng đó không phải là 1 px và bạn cũng không. Điều này sẽ không hoạt động cho dù tôi viết nó bằng html, css
Kerc

Có lẽ có một chức năng php cho việc này, có ai biết không?
Kerc

Tôi đã thử ví dụ của bạn, nhưng tôi cho rằng trường đầu vào rộng 1 pixel không phải là thứ bạn đang tìm kiếm. Nếu có, hãy thử<input type="text" value="1" style="width:1px;" />
peterjmag

1

Tôi thực sự thích câu trả lời của Lyth , nhưng cũng thực sự muốn nó:

  1. Xử lý backspace và xóa
  2. Không yêu cầu bạn tự thêm một thẻ liền kề.
  3. Thực hiện một chiều rộng tối thiểu.
  4. Tự động được áp dụng cho các phần tử với một lớp cụ thể

Tôi đã điều chỉnh JSFiddle của anh ấy và đưa ra điều này . Một cải tiến không có trong câu đố này là sử dụng một cái gì đó như jQuery CSS Parser để đọc chiều rộng ban đầu từ quy tắc autosize của input.textbox và sử dụng nó làm minWidth. Phải, tôi chỉ đơn giản là sử dụng một thuộc tính trên, điều này tạo ra một bản demo nhỏ gọn nhưng không lý tưởng. vì nó đòi hỏi một thuộc tính bổ sung trên mỗi đầu vào. Bạn cũng có thể chỉ muốn đặt minWidth là 100 ngay trong JavaScript.

HTML:

<div id='applicationHost'>
<div>Name:   <input class='textbox-autosize' data-min-width='100' type="text" /></div>
<div>Email:  <input class='textbox-autosize' data-min-width='100' type="email" /></div>
<div>Points: <input class='textbox-autosize' data-min-width='100' type="number" /></div>
</div>

CSS:

#applicationHost {
    font-family: courier;
    white-space: pre;
}

input.textbox-autosize, span.invisible-autosize-helper {
    padding:0;
    font-size:12px;
    font-family:Sans-serif; 
    white-space:pre;
}
input.textbox-autosize {
    width: 100px; /* Initial width of textboxes */
}

/*
In order for the measurements to work out, your input and the invisible
span need to have the same styling.
*/

JavaScript:

$('#applicationHost').on('keyup', '.textbox-autosize', function(e) {
    // Add an arbitary buffer of 15 pixels.
    var whitespaceBuffer = 15;
    var je = $(this);
    var minWidth = parseInt(je.attr('data-min-width'));
    var newVal = je.val();
    var sizingSpanClass = 'invisible-autosize-helper';
    var $span = je.siblings('span.' + sizingSpanClass).first();
    // If this element hasn't been created yet, we'll create it now.
    if ($span.length === 0) {
        $span = $('<span/>', {
            'class': sizingSpanClass,
            'style': 'display: none;'
        });
        je.parent().append($span);
    }
    $span = je.siblings('span').first();
    $span.text(newVal) ; // the hidden span takes 
    // the value of the input
    $inputSize = $span.width();
    $inputSize += whitespaceBuffer;
    if($inputSize > minWidth)
        je.css("width", $inputSize) ; // apply width of the span to the input
    else
        je.css("width", minWidth) ; // Ensure we're at the min width
});

1

Tốt hơn là onvalue:

<input id="txt" type="text" onvalue="this.style.width = ((this.value.length + 1) * 8) + 'px';">

Nó cũng liên quan đến việc dán, kéo và thả, v.v.


1

Đây là 2 xu của tôi. Tạo một div vô hình trống. Điền nó với nội dung đầu vào và trả lại chiều rộng cho trường đầu vào. Khớp các kiểu văn bản giữa mỗi hộp.

$(".answers_number").keyup(function(){
    $( "#number_box" ).html( $( this ).val() );
    $( this ).animate({
        width: $( "#number_box" ).width()+20
        }, 300, function() {
    });
});
#number_box {
   position: absolute;
   visibility: hidden;
   height: auto;
   width: auto;
   white-space: nowrap;
   padding:0 4px;
   /*Your font styles to match input*/
   font-family:Arial;
   font-size: 30px; 
}
    
.answers_number {
   font-size: 30px; 
   font-family:Arial;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="number" class="answers_number" />
<div id="number_box">
</div>


1

Khá đơn giản:

oninput='this.style.width = (this.scrollWidth - N) + "px";'

Trong đó N là một số (2 trong ví dụ, 17 về thứ tôi đang phát triển) được xác định bằng thực nghiệm.

Trừ N sẽ ngăn không gian mở rộng kỳ lạ này tích lũy từ lâu trước khi văn bản đến cuối hộp văn bản.

Đối chiếu. Hãy chú ý cẩn thận đến cách thay đổi kích thước chỉ sau ký tự đầu tiên.

<p>Subtracting N:</p>    
<input type="text" placeholder="enter lots of text here" oninput='this.style.width = (this.scrollWidth-2) + "px";'>

<p>Not Subtracting N:</p>    
<input type="text" placeholder="enter lots of text here" oninput='this.style.width = (this.scrollWidth) + "px";'>


Tôi đã không thử nghiệm rộng rãi với việc này, nhưng bạn chỉ có thể thay đổi oninput='this.style.width = (this.scrollWidth-2) + "px";'bằng cách oninput='this.style.width = 0; this.style.width = this.scrollWidth + "px";'để thoát khỏi không gian lũy
MaxCloutier

0

Tôi chỉ dành một chút thời gian để tìm ra cách để làm điều đó.
Trên thực tế, cách đơn giản nhất mà tôi tìm thấy là di chuyển giá trị đầu vào sang ngay trước đầu vào, giữ chiều rộng 1 ký hiệu đầu vào. Mặc dù tôi không thể chắc chắn rằng nó phù hợp với nhu cầu ban đầu của bạn.
Có thể đó là một số mã bổ sung, nhưng trong ứng dụng dựa trên phản ứng + thông lượng thì đó là giải pháp khá tự nhiên.


0

Dựa trên câu trả lời của Michael, tôi đã tạo phiên bản này của riêng mình bằng jQuery. Tôi nghĩ rằng nó là một phiên bản sạch hơn / ngắn hơn của hầu hết các câu trả lời ở đây và nó dường như hoàn thành công việc.

Tôi đang làm điều tương tự như hầu hết mọi người ở đây bằng cách sử dụng một nhịp để viết văn bản đầu vào vào sau đó lấy chiều rộng. Sau đó, tôi đang thiết lập chiều rộng khi các hành động keyupblur được gọi.

Đây là một codepen làm việc . Codepen này cho thấy làm thế nào điều này có thể được sử dụng với nhiều trường đầu vào.

Cấu trúc HTML:

<input type="text" class="plain-field" placeholder="Full Name">
<span style="display: none;"></span>

jQuery:

function resizeInputs($text) {
    var text = $text.val().replace(/\s+/g, ' '),
        placeholder = $text.attr('placeholder'),
        span = $text.next('span');
        span.text(placeholder);
    var width = span.width();

    if(text !== '') {
        span.text(text);
    var width = span.width();
    }

    $text.css('width', width + 5);
};

Hàm trên nhận giá trị đầu vào, cắt các khoảng trắng thừa và đặt văn bản vào khoảng để lấy chiều rộng. Nếu không có văn bản, thay vào đó, nó sẽ giữ chỗ và thay vào đó vào trong khoảng đó. Khi nó nhập văn bản vào khoảng đó, sau đó đặt chiều rộng của đầu vào. Các + 5trên chiều rộng là bởi vì không có mà đầu vào bị cắt đứt một chút nhỏ trong Edge Browser.

$('.plain-field').each(function() {
    var $text = $(this);
    resizeInputs($text);
});

$('.plain-field').on('keyup blur', function() {
    var $text = $(this);
    resizeInputs($text);
});

$('.plain-field').on('blur', function() {
    var $text = $(this).val().replace(/\s+/g, ' ');
    $(this).val($text);
});

Nếu điều này có thể được cải thiện xin vui lòng cho tôi biết vì đây là giải pháp sạch nhất tôi có thể đưa ra.


0

Tại sao không sử dụng chỉ css?

<div id="wrapper">
  <input onkeyup="keyup(event)">
  <div id="ghost"></div>
</div>

function keyup(e) {
	document.getElementById('ghost').innerText = e.target.value;
}
#wrapper {
  position: relative;
  min-width: 30px;
  display: inline-block;
}

input {
  position: absolute;
  left:0;
  right:0;
  border:1px solid blue;
  width: 100%;
}

#ghost {
  color: transparent;
}
<div id="wrapper">
  <input onkeyup="keyup(event)">
  <div id="ghost"></div>
</div>

wrapper {
  position: relative;
  min-width: 30px;
  border: 1px solid red;
  display: inline-block;
}

input {
  position: absolute;
  left:0;
  right:0;
  width: 100%;
}

#ghost {
  color: transparent;
}

mã này được giới thiệu bởi @Iain Todd và tôi nghĩ tôi nên chia sẻ nó


Nó không chỉ là css. Nó chỉ là một phương pháp js khác. Thú vị một.
vatavale

0

Một cách chống đạn, chung chung phải:

  1. Hãy tính đến tất cả các kiểu có thể có của inputphần tử đo
  2. Có thể áp dụng phép đo trên bất kỳ đầu vào nào mà không cần sửa đổi HTML hoặc

Bản demo Codepen

var getInputValueWidth = (function(){
  // https://stackoverflow.com/a/49982135/104380
  function copyNodeStyle(sourceNode, targetNode) {
    var computedStyle = window.getComputedStyle(sourceNode);
    Array.from(computedStyle).forEach(key => targetNode.style.setProperty(key, computedStyle.getPropertyValue(key), computedStyle.getPropertyPriority(key)))
  }
  
  function createInputMeassureElm( inputelm ){
    // create a dummy input element for measurements
    var meassureElm = document.createElement('span');
    // copy the read input's styles to the dummy input
    copyNodeStyle(inputelm, meassureElm);
    
    // set hard-coded styles needed for propper meassuring 
    meassureElm.style.width = 'auto';
    meassureElm.style.position = 'absolute';
    meassureElm.style.left = '-9999px';
    meassureElm.style.top = '-9999px';
    meassureElm.style.whiteSpace = 'pre';
    
    meassureElm.textContent = inputelm.value || '';
    
    // add the meassure element to the body
    document.body.appendChild(meassureElm);
    
    return meassureElm;
  }
  
  return function(){
    return createInputMeassureElm(this).offsetWidth;
  }
})();


// delegated event binding
document.body.addEventListener('input', onInputDelegate)

function onInputDelegate(e){
  if( e.target.classList.contains('autoSize') )
    e.target.style.width = getInputValueWidth.call(e.target) + 'px';
}
input{ 
  font-size:1.3em; 
  padding:5px; 
  margin-bottom: 1em;
}

input.type2{
  font-size: 2.5em;
  letter-spacing: 4px;
  font-style: italic;
}
<input class='autoSize' value="type something">
<br>
<input class='autoSize type2' value="here too">


0

Bạn chỉ có thể đặt sizethuộc tính. Nếu bạn đang sử dụng một trong các khung phản ứng, những điều sau đây sẽ là đủ:

<input size="{{ yourValue.length }}" [value]="yourValue" />

nhưng nếu bạn đang sử dụng js thuần, bạn nên đặt trình xử lý sự kiện, như:

<input oninput="this.setAttribute('size', this.value.length)" />
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.