34

I have a input type text

<input type="text" id="txtid">

When i start typing text inside input, i should be able to get the lenght of the entered text.

This is what I tried:

document.getElementById("txtid").offsetWidth;

and

var test = document.getElementById("txtid");
var width = (test.clientWidth + 1) + "px";

These two does not give the width of the text entered

Basically what I want is:

enter image description here

For suppose input text width is 320px. I need the width of the entered text i.e 120px, which keeps on changing when I enter.

6
  • 11
    I think this is not trivial. You could generate a invisible span which always contains the same content as your inputbox. and then measure it's width. Commented Jun 1, 2017 at 8:52
  • 1
    Maybe you can use this: stackoverflow.com/a/21015393/4108884 as a workaround Commented Jun 1, 2017 at 8:53
  • 3
    There exists another dependency: The font it self. The width of each letter in every font have a different width. Even the letters have different width. In examplate: the 'i' is defnitly smaller than 'w'. Commented Jun 1, 2017 at 8:58
  • @Paflow Nice . better you could post the answer. Commented Jun 1, 2017 at 8:59
  • 1
    Possible duplicate of Calculate text width with JavaScript Commented Jun 1, 2017 at 12:43

6 Answers 6

27

I see two ways.

First:

You can use a div with content editable instead input. Like this you can see the width of the div.

var elemDiv = document.getElementById('a');

elemDiv.onblur = function() {
  console.log(elemDiv.clientWidth + 'px');
}
div {
  width: auto;
  display: inline-block;
}
<div id='a' contenteditable="plaintext-only">Test</div>

Note : Like @Leon Adler say, this way allows pasting images, tables and formatting from other programs. So you maybe need some validation with javascript to check the content before get the size.


Second:

Use an input type text and paste the content into an invisible div. And you can see the width of the invisible div.

var elemDiv = document.getElementById('a'),
  elemInput = document.getElementById('b');

elemInput.oninput = function() {
  elemDiv.innerText = elemInput.value;
  console.log(elemDiv.clientWidth + 'px');
}
.div {
  width: auto;
  display: inline-block;
  visibility: hidden;
  position: fixed;
  overflow:auto;
}
<input id='b' type='text'>
<div id='a' class='div'></div>

Note : For this way, you must have the same font and font size on input and div tags.

Sign up to request clarification or add additional context in comments.

2 Comments

This allows pasting images, tables and formatting from other programs. Contenteditable is everything but trivial.
@LeonAdler Right, I post another way, to get more choice.
12

I have modified Chillers answer slightly, because it looks like you wanted the width rather than the letter count. I have created a span, which is absolute positioned off the screen. I am then adding the value of the input to it and then getting the width of the span. To make it more fancy you could create the span with javascript.

Note that the input and the span would have to have the same CSS styling for this to be accurate.

document.getElementById("txtid").addEventListener("keyup", function(){
  var mrspan = document.getElementById("mrspan");
  mrspan.innerText = this.value;
  console.log(mrspan.offsetWidth + "px");
});
<input type="text" id="txtid">
<span id="mrspan" style="position:absolute;left:-100%;"></span>

7 Comments

Downvoted, This opens the possibility for an HTML injection attack, use innerText instead of innerHTML for user provided data
Thanks, I wasn't aware of that. I have updated the answer.
@Ferrybig I'm curious to know how?
I think it has something to do with InnerText stripping out any HTML tags e.g. someone could enter a malicious code <script>if(theirMoney > myMoney) { return theirMoney; }</script>;
@WizardCoder When you are reading its value, yes, the content is converted to text, removing the tags. But when writing its value, the tags are escaped, not removed.
|
11

Canvas measureText() method can be helpful in such a case. Call the following function whenever you need to get your text width:

function measureMyInputText() {
    var input = document.getElementById("txtid");
    var c = document.createElement("canvas");
    var ctx = c.getContext("2d");
    var txtWidth = ctx.measureText(input.value).width;

    return txtWidth;
}

For more accurate result, you may set font styling to the canvas, especially if you set some font properties to the input. Use the following function to get the input font:

 function font(element) {
     var prop = ["font-style", "font-variant", "font-weight", "font-size", "font-family"];
     var font = "";
     for (var x in prop)
         font += window.getComputedStyle(element, null).getPropertyValue(prop[x]) + " ";

     return font;
 }

Then, add this line to the frist function:

ctx.font = font(input);

1 Comment

Add 'letter-spacing' to list of props?
6

UPDATE

Two things I want to put forward

  • Doing display none will not give you any offsetWidth if we are trying using vanilla JS. we can use visibility: hidden; or opacity:0 for that.

  • we need to add overflow:auto to the hidden span or else the text will be warped to the next line if it exceeds the browser window width and the width will stay fixed (width of window)

OLD

You can try this approach

Add a span and hide it

<span id="value"></span>

and then onkeyup add the text of the textfield on your hidden span and get its width.

WITH THE HELP OF JQUERY

SNIPPET (UPDATED)

function update(elm,value) {
     $('#value').text(value);
     var width =   $('#value').width();
     $('#result').text('The width of '+ value +' is '+width +'px');
   
}
#value{
  display:none;
  overflow:auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<input type="text" oninput='update(this,this.value)'>
<span id="value"></span>
<div id="result"></div>

USING JS ONLY

SNIPPET (UPDATED)

function update(elm,value) {
     var span = document.getElementById('value');
     span.innerHTML = value;    
     var width = span.offsetWidth;
     document.getElementById('result').innerHTML = 'The width of '+ value +' is '+ width+ 'px';
   
}
#value{
  opacity:0;
  overflow:auto;
}
<input type="text" oninput='update(this,this.value)'>
<span id="value"></span>
<div id="result"></div>

7 Comments

If enter 1 in the text box I get "The length is of is 0".
it's working now but the user wants using javascript.
you are pasting it not typing
@nadir-lasker Caught if fixed this issue it would be perfect.
You can use onchange event for that
|
4

Using the above solution, I turned it into a single function.

let getWidth = (fontSize, value) => {
  let div = document.createElement('div');
  div.innerText = value;
  div.style.fontSize = fontSize;
  div.style.width = 'auto';
  div.style.display = 'inline-block';
  div.style.visibility = 'hidden';
  div.style.position = 'fixed';
  div.style.overflow = 'auto';
  document.body.append(div)
  let width = div.clientWidth;
  div.remove();
  return width;
};
getWidth('10px', 'test');

Comments

0

Here is my approach:

I create a fake 'span' element, which copies all font styles of the input element, then measures it's width

function measureInputValueWidth(input: HTMLInputElement): number {
  const span = document.createElement("span");
  span.style.whiteSpace = "pre";
  span.style.fontFamily = input.style.fontFamily;
  span.style.fontSize = input.style.fontSize;
  span.style.fontWeight = input.style.fontWeight;
  span.style.fontStyle = input.style.fontStyle;
  span.style.letterSpacing = input.style.letterSpacing;
  span.style.textTransform = input.style.textTransform;
  span.style.padding = input.style.padding;
  span.style.margin = input.style.margin;
  span.style.border = input.style.border;
  span.style.boxSizing = input.style.boxSizing;
  span.style.position = "absolute";
  span.style.left = "-9999px";
  span.style.top = "-9999px";
  span.innerText = input.value;
  document.body.appendChild(span);
  const width = span.getBoundingClientRect().width;
  document.body.removeChild(span);
  return width;
}

function updateInputWidthToMatchValue(input: HTMLInputElement) {
  input.style.width = `${measureInputValueWidth(input)}px`;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.