programing

입력[type=text]을 값의 너비로 자동 스케일링하시겠습니까?

jooyons 2023. 10. 7. 10:45
반응형

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

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

나는 이것을 할 수 있는 몇 가지 방법을 보았지만 글꼴의 너비를 계산하는 것은 항상 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;
}

#txt:focus-visible {
  outline: none;
}

#hide {
  display: none;
  white-space: pre;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.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를 약간 수정해야 했습니다.

const hide = document.getElementById('hide');
const 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;
}

#txt:focus-visible {
  outline: none;
}

#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>

어떤 이유로 다른 솔루션이 사용자에게 적합하지 않을 경우 입력 요소 대신 내용 편집 가능 범위를 사용할 수 있습니다.

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

이것은 해킹에 가까우며 사용자가 줄 바꿈, 링크 및 기타 HTML을 입력(및 붙여넣기)하는 것과 같이 완전히 비위생적인 HTML 입력을 허용하는 심각한 단점을 가지고 있습니다.

그러니까용액을 사용해서는 안 되겠군요 입력을 아주 조심스럽게 소독하지 않는 한...

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

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

저는 JS를 포함하지 않는 이 문제에 대한 다른 해결책을 찾았습니다.HTML에 다음과 같은 내용을 넣었습니다.

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

가시성을 설정하기만 하면 됩니다. 고스트 입력과 너비에 숨겨져 있습니다. 입력 자체에 100%가 필요합니다.입력이 브라우저 자체에서 계산한 너비(동일한 텍스트를 기준으로)의 100% 컨테이너로 확장되기 때문에 작동합니다.

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

GitHub: https://github.com/MartinF/jQuery.Autosize.Input 에 jQuery 플러그인이 있습니다.

입력 값을 반영하여 폭을 계산하고 입력의 폭을 설정하는 데 사용합니다.

여기서 라이브 예시를 보실 수 있습니다: 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를 사용하여 min/max-width를 설정하고 좋은 효과를 원한다면 폭에 대한 전환을 사용하면 됩니다.

입력 요소의 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;
}

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

디브를 만들고 폭을 측정하려고 하는 것보다 캔버스 요소를 사용하여 직접 폭을 측정하는 것이 더 정확하다고 생각합니다.

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

이 문제는 여기서 해결하시면 됩니다 :) 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 박스 사이징도 고려해야 합니다.

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";
    }
}
* {
  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에서도 작동해야 한다고 생각하지만, 제 말을 믿지 마세요.

사용 사례에 따라 조정 기능을 다른 이벤트에 바인딩해야 할 수도 있습니다.예: 입력의 값을 프로그래밍 방식으로 변경하거나 요소의 스타일을 변경합니다.display로부터의 재산none(어디에scrollWidth === 0) 로block아니면inline-block,기타.

화폭을 재어 보다텍스트 솔루션

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

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

입력 요소는 다른 요소와 다르게 동작합니다. 이것은 만약 당신이 입력 요소를 준다면 당신이 원하는 것을 할 것입니다.float: left(http://jsfiddle.net/hEvYj/5/) 참조.자바스크립트로 어떤 식으로든 계산하지 않고서는 불가능하다고 생각합니다(즉, 상자 안의 글자당 너비에 5px를 더하는 것).

nrabinowitz 사용자의 솔루션은 잘 작동하고 있지만, 저는 그 솔루션을 사용합니다.keypress대신 이벤트keyup. 사용자가 느리게 입력하면 대기 시간이 줄어듭니다.

nrabinowitz 솔루션을 수정한 내용입니다.@Mark가 언급한 것처럼 비례 글꼴로 완벽하지 않기 때문에 사이즈 속성을 사용하지 않았습니다.나의 솔루션은 당신의 입력 뒤에 요소를 배치하고 브라우저로 너비를 계산합니다(jQuery 사용).

테스트는 하지 않지만 폰트에 영향을 미치는 CSS 속성이 모두 상속되어야 작동할 것 같습니다.

포커스 아웃 이벤트 때 입력 폭이 바뀌는데 그게 더 잘 맞아요.그러나 입력할 때 키 업/키 누름을 사용하여 입력의 너비를 변경할 수도 있습니다.

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

캔버스를 사용하여 요소 폭을 계산할 수 있습니다.

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

캔버스를 만들고 크기를 계산하면서 폭을 해결했습니다.입력 값과 캔버스가 동일한 글꼴 특징(가족, 크기, 무게...)을 공유하는 것이 중요합니다.

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 코드샌드박스 : https://codesandbox.io/s/calculate-text-width-okr46

어느 것이든 통과할 수 있습니다.input요소의 적절한 너비를 얻기 위해 이 함수에 있는 요소.이 너비는 다음과 같습니다.input요소 면적span원래 요소의 모든 속성을 가진 요소.그것은 다음을 고려할 것입니다.font-family,font-size, 그리고 텍스트의 전체 너비뿐만 아니라 가로 테두리와 패딩에 영향을 미칠 수 있는 다른 모든 글꼴 속성.input요소. 또한 값이 없는 경우 자리 표시자의 너비를 반환합니다에 합니다.input요소.

이 은 하는 데 입니다.input요소.없는 .이 경우 요소에 값이나 자리 표시자가 없는 경우 최소 너비를 설정할 수도 있습니다.

이은 할 것입니다.offsetWidthpx까지,합니다.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;
}

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

반응형