입력 [type = text]을 값의 너비로 자동 확장 하시겠습니까?


답변:


86

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를 사용하여 텍스트의 픽셀 크기를 계산하는 이 관련 답변에서 설명한 것과 같은 기술을 사용할 수 있습니다 .


23
"오른쪽 패딩"은 브라우저에 종속되지 않습니다. 이는 요소의 크기가 문자로 지정되기 때문입니다. 그러나 많은 글꼴의 경우 모든 문자의 너비가 같지는 않습니다. 가변 너비 글꼴의 'iiiiiiiiiii'로 필드를 채우면 문제를 더 명확하게 볼 수 있습니다.
Mark

@Mark-요점을 찍었지만 브라우저에 따라 달라지는 부분은 "크기"속성이 해석되는 방식입니다. 정확한 너비는 브라우저에서 표준이라고 생각하지 않습니다.
nrabinowitz 2013

... 고정 폭 글꼴로 시도해 보면 일부 브라우저에서 여전히 올바른 패딩이 있음을 알 수 있습니다. jsfiddle.net/nrabinowitz/NvynC/151
nrabinowitz

@nrabinowitz 대부분의 경우에 많이 필요한 MAX 값을 추가하는 약간의 수정 은 jsfiddle.net/NvynC/662 를 참조하십시오 .
GJ 2014 년

1
Courier New이 글꼴의 모든 문자의 너비가 같기 때문에 텍스트 상자에 글꼴을 더 잘 사용하는 것이 좋습니다 . ( jsfiddle.net/NabiKAZ/NvynC/745 )
Nabi KAZ

45

간단하지만 완벽한 픽셀 솔루션

이 작업을 수행하는 여러 가지 방법을 보았지만 글꼴 너비를 계산하는 것이 항상 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>


순수 자바 스크립트

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>


2
멋져요! 나는 여전히 jQuerry없이 그것을 선호하지만 바닐라 JS 만! 위의 코드와 여기에 jsfiddle : jsfiddle.net/kjxdr50a
야간 열차

3
@NightTrain 귀하의 요청에 따라. JavaScript 솔루션이 추가되었습니다. =)
DreamTeK

두 솔루션을 비교할 때 jQuerry : jsfiddle.net/kjxdr50a/42 JS : jsfiddle.net/kjxdr50a/44 jQuerry 솔루션은 결함이 없기 때문에 약간 더 잘 수행됩니다. (2 픽셀을 추가하여 수정했습니다.) @Obsidian이 솔루션을 내 질문 중 하나에서 인용해도 괜찮습니까?
야간 열차

모든 도움에 감사드립니다! 마침내 Angular 앱에 구현했습니다. 데모는 StackBlitz에서 찾을 수 있습니다 . 그리고 응답 입력에 관한 질문 : stackoverflow.com/a/49478320/9058671 . 나는 데모를 내 코드를 개선하기 위해 노력하고 업데이트 할 수 있습니다 ..
밤 기차를

1
좋은 대답은 한 가지 더 추가 할 것입니다. 입력에 패딩이있는 경우 (물론 고스트 요소 hide는 동일한 패딩을 가져야 함) height: 0;부분이 제대로 작동하지 않습니다. 이 문제에 대한 해결 방법은를 사용 하는 것입니다. 안전을 위해 position: fixed; top: -100vh;추가 할 수도 있습니다 opacity: 0;.
Kamil Bęben

35

어떤 이유로 다른 솔루션이 작동하지 않는 경우 입력 요소 대신 contenteditable-span을 사용할 수 있습니다.

<span contenteditable="true">dummy text</span>

이것은 해킹에 가깝고 사용자가 줄 바꿈, 링크 및 기타 HTML을 입력 (및 붙여 넣기) 할 수 있도록하는 것과 같이 완전히 삭제되지 않은 HTML 입력을 허용하는 심각한 단점이 있습니다.

따라서 입력을 매우 신중하게 삭제하지 않는 한이 솔루션을 사용해서는 안됩니다 .

업데이트 : 아래 의 DreamTeK 솔루션 을 사용하고 싶을 것입니다 .


1
이 솔루션은 작업을 브라우저로 연기합니다! 단연 최고의 솔루션입니다!
user2033412

8
사용자는 내용 편집 가능에 줄 바꿈 이상을 붙여 넣을 수 있습니다. 그는 이미지, iframe, 거의 모든 html을 붙여 넣을 수 있습니다.
CodeToad 2014

2
또한 MS Word 또는 PDF 파일과 같은 편집기에서 서식이 지정된 텍스트를 붙여 넣으면 예상치 못한 결과가 발생합니다. 일반적으로 기본 입력 요소 대신 이것을 사용하는 것은 정말 어렵고 가치가 없습니다 (아직).
Senthe

7
이것은 정말로 재난의 비결입니다
Joseph

2
contenteditable서식있는 텍스트 WYSIWYG 텍스트 편집기를 설정하기위한 것입니다. 입력 크기를 조정하기위한 것이 아닙니다.
Joseph Nields

10

편집 : 이제 플러그인이 후행 공백 문자와 함께 작동합니다. @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});
<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});


1
솔루션 니스,하지만 후행 공백을 고려하지 않는 것 (입력에 후행 공백을 잔뜩 추가)
SpyderScript

1
참고 font로, CSS 속기 이기 때문에 Firefox에서 작동하지 않습니다 (이상하게도 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.
Garrett

@Garrett Firefox 수정에 대해 감사드립니다. 당신은 저에게 많은 시간을 절약했습니다.
마이코

8

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();

6

여기에는 이미 좋은 답변이 많이 있습니다. 재미를 위해 다른 답변과 내 아이디어를 기반으로이 솔루션을 아래에서 구현했습니다.

<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, '&nbsp'));

                // 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;
}

여기 에 바이올린이 있습니다. 나는 이것이 깨끗한 해결책을 찾는 다른 사람들에게 도움이되기를 바랍니다.


4

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";

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');

3

불행히도 size속성은 잘 작동하지 않습니다. 글꼴 설정 방법에 따라 여분의 공간과 너무 적은 공간이있을 수 있습니다. (예제 확인)

이것이 잘 작동하도록하려면 입력의 변경 사항을 확인한 다음 크기를 조정하십시오. 당신은 아마 그것을 입력의scrollWidth . 상자 크기도 고려해야합니다.

다음 예제에서는 초기 너비 (CSS로 수동 설정)보다 큰 값 size을 갖지 않도록 입력의을 1로 scrollWidth설정합니다.

// (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에서도 작동한다고 생각하지만 내 말을 받아들이지 마십시오.

사용 사례에 따라 adjust 함수를 다른 이벤트에 바인딩해야 할 수 있습니다. 예를 들어 입력 값을 프로그래밍 방식으로 변경하거나 요소의 스타일 display속성을 none(where scrollWidth === 0)에서 block또는 inline-block로 변경하는 등의 작업이 있습니다.


3

JS와 관련이없는이 문제에 대한 또 다른 해결책을 찾았습니다. HTML에서는 다음과 같이 입력합니다.

<div>
  <input class="input" value={someValue} />
  <div class="ghost-input">someValue</div>
</div>

가시성을 설정하기 만하면됩니다 : 고스트 입력시 숨김, 입력 자체에서 너비 : 100 %. 입력이 컨테이너의 100 %로 조정되기 때문에 작동하며 너비는 브라우저 자체에 의해 계산됩니다 (동일한 텍스트를 기반으로 함).

입력 필드에 패딩과 테두리를 추가하면 그에 따라 고스트 입력 클래스를 조정해야합니다 (또는 입력 클래스에서 calc () 사용).


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']);

jquery.auto-fit.js 에서 세미콜론으로 시작하는 이유는 무엇 입니까? "$ this.keydown (methods.fit)"줄에 세미콜론이없는 이유는 무엇입니까?
Peter Mortensen

1
@PeterMortensen, 신중한 검토에 감사드립니다. 당신이 언급 한 줄 옆에 세미콜론을 추가했습니다. 시작 세미콜론의 경우 세미콜론으로 끝나지 않는 다른 파일로 인한 문제를 피하는 것이 습관이었습니다.
제프 티안

0

입력 요소는 다른 요소와 다르게 작동하므로 사용자가 제공하면 원하는대로 수행 할 수 있습니다 float: left( http://jsfiddle.net/hEvYj/5/ 참조 ). JavaScript로 어떤 식 으로든 계산하지 않고서는 가능하지 않다고 생각합니다 (예 : 상자의 글자 당 너비에 5px 추가).


0

사용자 nrabinowitz 의 솔루션 이 훌륭하게 작동하지만 keypress대신 이벤트를 사용합니다 keyup. 이렇게하면 사용자가 천천히 입력하는 경우 지연 시간이 줄어 듭니다.


사용 oninput(또는 onpropertychange그들이 오른쪽 클릭으로 붙여 넣기 또는 선택 등의 작업에 응답으로 기존의 IE에 대한) 올바른 이벤트 - 브라우저의 메뉴 표시 줄에서 "파일> 붙여 넣기"
조셉 Nields

0

다음은 nrabinowitz 의 솔루션을 수정 한 것입니다 . @Mark가 지적했듯이 비례 글꼴에는 완벽하지 않기 때문에 size 속성을 사용하지 않았습니다 . 내 솔루션은 입력 뒤에 요소를 배치하고 브라우저에서 너비를 계산합니다 (jQuery 사용).

테스트하지는 않지만 글꼴에 영향을 미치는 모든 CSS 속성이 상속 된 경우에만 작동한다고 생각합니다.

포커스 아웃 이벤트에서 입력 너비가 변경되어 더 잘 작동합니다. 그러나 입력 할 때도 입력 폭을 변경하기 위해 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);

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);
}

0

캔버스 measureText 솔루션 사용해보기

CSS :

    input{
        min-width:10px!important;
        max-width:99.99%!important;
        transition: width 0.1s;
        border-width:1px;
    }

자바 스크립트 :

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);
});

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.