programing tip

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

itbloger 2020. 10. 14. 07:35
반응형

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


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


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

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

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

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

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


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

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


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


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

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

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

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


이 문제는 다음과 같이 해결할 수 있습니다. :) 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속성은 잘 작동하지 않습니다. 글꼴 설정 방법에 따라 여분의 공간과 너무 적은 공간이있을 수 있습니다. (예제 확인)

이것이 잘 작동하도록하려면 입력의 변경 사항을 확인한 다음 크기를 조정하십시오. 입력의 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으로 변경하는 등.


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

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

Input elements do behave differently from other elements, which would do just about what you want if you give them float: left (see http://jsfiddle.net/hEvYj/5/). I do not think that is possible without calculating it in some way with JavaScript (i.e. add 5px to the width per letter in the box).


User nrabinowitz' solution is working great, but I use the keypress event instead of keyup. That reduces the latency if the user types slowly.


Here is my modification of nrabinowitz' solution. I didn't use the size property, because it's not perfect with proportional fonts as @Mark noted. My solution place an element after your input and gets width counted by browser (using jQuery).

Although I don't test it, I suppose it will work only if all CSS properties affecting font are inherited.

The input width changes on focusout event, which works better for me. But you can use keyup/keypress to change input's width when typing as well.

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

Using canvas we could calculate the elements width:

function getTextWidth(text, fontSize, fontName) {
  let canvas = document.createElement('canvas');
  let context = canvas.getContext('2d');
  context.font = fontSize + fontName;
  return context.measureText(text).width;
}

and use it on the chosen event:

function onChange(e) {
  let width = getTextWidth(this.value, $(this).css('font-size'), 
  $(this).css('font-family'));
  $(this.input).css('width', width);
}

try canvas measureText solution

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

참고URL : https://stackoverflow.com/questions/8100770/auto-scaling-inputtype-text-to-width-of-value

반응형