React: How to Make an Input Only as Wide as the Amount of Text Provided

React: how to make an input only as wide as the amount of text provided?

Here is an approach from plain HTML/CSS and a working snippet , hidding the value typed inside a span behind the input set in an absolute position. CSS can make both span and input matching the same lenght/width. Stretching/collapsing a parent (label) will finish the job.

In the courtesy of @silvenon you may also find a react sample below the snippet

var val = document.querySelector('#test');
let tpl = document.querySelector('#tpl');
let text = val.value;
tpl.textContent= text;

val.addEventListener("input", function () {// onchange ...
let text= val.value;
//console.log(text);
tpl.textContent= text;
});
label {
display: inline-block;
position: relative;
min-width: 2em;
min-height: 1.4em;
}

#tpl {
white-space: pre;
/* max-width : could be wised to set a maximum width and overflow:hidden; */
}

#test {
font-family: inherit;
font-size: inherit;
position: absolute;
vertical-align: top;
top: 0;
left: 0;
width: 100%;
background: white;
}
<label><span id="tpl"></span><input id='test' value="Some test to try" ></label>

Auto-scaling input to width of value in React

After a lot of fiddling around, I found a solution!

import React, { useState, useRef, useEffect } from 'react';

export default () => {
const [content, setContent] = useState('');
const [width, setWidth] = useState(0);
const span = useRef();

useEffect(() => {
setWidth(span.current.offsetWidth);
}, [content]);

const changeHandler = evt => {
setContent(evt.target.value);
};

return (
<wrapper>
<span id="hide" ref={span}>{content}</span>
<input type="text" style={{ width }} autoFocus onChange={changeHandler} />
</wrapper>
);
};

To get a reference to the #hide span I employ useRef. Then, the width state variable can be updated via the function defined inside useEffect, which gets called everytime content changes.

I also had to switch the display: none in the css of #hide for position: absolute and opacity: 0, as otherwise targetRef.current.offsetWidth would always be 0.

Here's a working demo.

Adjust width of input field to its input

It sounds like your expectation is that the style be applied dynamically to the width of the textbox based on the contents of the textbox. If so you will need some js to run on textbox contents changing, something like this:

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

Note: this solution only works when every character is exactly 8px wide. You could use the CSS-Unit "ch" (characters) which represents the width of the character "0" in the chosen font. You can read about it here.

How to make an automatic increase in the width of the text input field depending on the number of lines?

onLayout={(event) => {
if (textInputHeight === 0) {
setTextInputHeight(event.nativeEvent.layout.height);
}
}}
onContentSizeChange={(event) => {
setTextInputHeight(event.nativeEvent.contentSize.height);
}}

width:auto for input fields

An <input>'s width is generated from its size attribute. The default size is what's driving the auto width.

You could try width:100% as illustrated in my example below.

Doesn't fill width:

<form action='' method='post' style='width:200px;background:khaki'>
<input style='width:auto' />
</form>

Fills width:

<form action='' method='post' style='width:200px;background:khaki'>
<input style='width:100%' />
</form>

Smaller size, smaller width:

<form action='' method='post' style='width:200px;background:khaki'>
<input size='5' />
</form>

UPDATE

Here's the best I could do after a few minutes. It's 1px off in FF, Chrome, and Safari, and perfect in IE. (The problem is #^&* IE applies borders differently than everyone else so it's not consistent.)

<div style='padding:30px;width:200px;background:red'>
<form action='' method='post' style='width:200px;background:blue;padding:3px'>
<input size='' style='width:100%;margin:-3px;border:2px inset #eee' />
<br /><br />
<input size='' style='width:100%' />
</form>
</div>

Why is my Text Input getting activated only at the width of PlaceHolder?

Try this simple solution,

<TextInput style={[customStyles.text, { flex: 1 }]} {...otherProps} />

Minimal input width growing with value

As @DanFarrell said, <input /> in html is not designed for inline display.

Use <span /> with contentEditable="true", with modified codepen https://codepen.io/valuis/pen/LeVrbx

and code snippet:

@import url(//fonts.googleapis.com/css?family=Roboto:400,300);@import url(//netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.css);
html { font-size: 17px;}
*, *:before, *:after { box-sizing: border-box;}
body { background: #111; font-family: 'Roboto'; -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility;}
.wrapper { background: #48435C; margin: 2rem auto 0; max-width: 80%; color: #fff; border: 1px solid #ddd; padding: 20px 0;}
h1 { padding: 0 30px;}
.formRow { padding: 10px 30px;}
.formRowOdd { background: #383850; }
/* LAYOUT */.formRow { display: flex; flex-direction: row; flex: 1 1;}
.label { display: flex; flex: 1 1;}.valueWrapper { display: flex; flex-direction: row;}
.value { display: flex; margin-right: 5px; min-width: 0; max-width: 80px; display: flex; justify-content: flex-end;}
span { display: flex; color: #fff; background: transparent; text-align: right; min-width: 0; overflow: hidden; max-width: 80px; flex: 1 0 30px; border-width: 0 0 1px; border-color: #ccc; border-style: solid; }
<div class="wrapper">  <h1>Form</h1>  <div class="formRow formRowOdd">    <div class="label">Short value</div>    <div class="valueWrapper">      <div class="value">        <span contentEditable="true">123</span>      </div>      <div class="unit">min</div>    </div>  </div>  <div class="formRow formRowEven">    <div class="label">Long value</div>    <div class="valueWrapper">      <div class="value">        <span contentEditable="true">1234567</span>      </div>      <div class="unit">min</div>    </div>  </div>  <div class="formRow formRowOdd">    <div class="label">Value to be filled</div>    <div class="valueWrapper">      <div class="value">        <span contentEditable="true" />      </div>      <div class="unit">min</div>    </div>  </div></div>

React Native Text Input fields not taking full width even though flex: 1

just try this with only one TextInput

return (
<View style={styles.container}>
<KeyboardAvoidingView
behavior={Platform.OS === "ios" ? "padding" : null}
style={{ flex: 1, width: "100%" }}
>
<ScrollView style={styles.inner}>
<TextInput
style={styles.input}
placeholder="Postal Code"
value={"fdf"}
/>
</ScrollView>
</KeyboardAvoidingView>
</View>
);

It will surely work :)



Related Topics



Leave a reply



Submit