Reputation: 483
I'm creating a chat application(React). I'm having this textbox which I need to expand vertically upwards as user types. I tried doing it with position absolute but it takes it out of the normal flow. And this does not allow the parent div to move upwards. Is there a way that this can be done? If anyone could point me in the right direction that would be great. Thanks.
Here is the codepen link.
https://codepen.io/ghewadesumit/pen/zYzRjyY
<div class='chat-inputbox-container'>
<div class='chat-inputbox-wrapper'>
<div class='chat-microphone-container'>
<div class='chat-microphone'></div>
</div>
<div class='inputbox-container'>
<div class='inputbox-wrapper'>
<textarea type='text' class='chat-input-box'></textarea>
<div class='input-box-btn'></div>
</div>
<div class='input-character-container'>
<span class='input-character'>
250 out of 250 characters left
</span>
</div>
</div>
</div>
</div>
css
.chat-inputbox-container {
/* border: 1px solid red; */
width: 100%;
height: 113px;
align-self: flex-end;
display: flex;
justify-content: center;
}
.chat-inputbox-wrapper {
width: 736px;
height: 92px;
display: flex;
flex-direction: row;
justify-content: space-between;
}
.chat-microphone-container {
width: 32px;
height: 92px;
/* border: 1px solid orange; */
display: flex;
align-items: center;
justify-content: center;
margin-right: 10px;
}
.chat-microphone {
width: 32px;
height: 32px;
background: orangered;
}
.inputbox-wrapper {
width: 694px;
height: 52px;
/* border: 1px solid blue; */
display: flex;
align-self: flex-end;
align-items: center;
margin-top: 16px;
background: gray;
border: 1px solid red;
box-sizing: border-box;
border-radius: 4px;
}
.chat-input-box {
width: 632px;
height: 20px;
font-size: 14px;
line-height: 20px;
border: hidden;
background: #f7f7f7;
outline: none;
color: #0d1c3d;
margin: 16px 10px;
}
.input-box-btn {
/* Auto Layout */
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
padding: 0px;
position: static;
width: 32px;
height: 32px;
margin-right: 10px;
background: #0078b3;
border-radius: 4px;
flex: none;
order: 0;
flex-grow: 0;
margin: 0px 0px;
}
.input-character-container {
}
.input-character {
font-size: 12px;
line-height: 16px;
color: #677083;
}
Upvotes: 0
Views: 1336
Reputation: 2544
Don't hard code the height
of class .inputbox-wrapper
instead remove height property from there or put height: auto
(which is default value) so that container expand when the the text-area
is expanded
.chat-inputbox-container {
/* border: 1px solid red; */
width: 100%;
height: 113px;
align-self: flex-end;
display: flex;
justify-content: center;
}
.chat-inputbox-wrapper {
width: 736px;
height: 92px;
display: flex;
flex-direction: row;
justify-content: space-between;
}
.chat-microphone-container {
width: 32px;
height: 92px;
/* border: 1px solid orange; */
display: flex;
align-items: center;
justify-content: center;
margin-right: 10px;
}
.chat-microphone {
width: 32px;
height: 32px;
background: orangered;
}
.inputbox-wrapper {
width: 694px;
height: auto;/*Change here*/
/* border: 1px solid blue; */
display: flex;
align-self: flex-end;
align-items: center;
margin-top: 16px;
background: gray;
border: 1px solid red;
box-sizing: border-box;
border-radius: 4px;
}
.chat-input-box {
width: 632px;
height: 20px;
font-size: 14px;
line-height: 20px;
border: hidden;
background: #f7f7f7;
outline: none;
color: #0d1c3d;
margin: 16px 10px;
}
.input-box-btn {
/* Auto Layout */
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
padding: 0px;
position: static;
width: 32px;
height: 32px;
margin-right: 10px;
background: #0078b3;
border-radius: 4px;
flex: none;
order: 0;
flex-grow: 0;
margin: 0px 0px;
}
.input-character-container {
}
.input-character {
font-size: 12px;
line-height: 16px;
color: #677083;
}
<div class='chat-inputbox-container'>
<div class='chat-inputbox-wrapper'>
<div class='chat-microphone-container'>
<div class='chat-microphone'></div>
</div>
<div class='inputbox-container'>
<div class='inputbox-wrapper'>
<textarea type='text' class='chat-input-box'></textarea>
<div class='input-box-btn'></div>
</div>
<div class='input-character-container'>
<span class='input-character'>
250 out of 250 characters left
</span>
</div>
</div>
</div>
</div>
Upvotes: 2
Reputation: 36626
We can use a Javascript ResizeObserver to tell us when the height of the input text has changed. Then we can scroll the window in such a way that the bottom of the input stays in the same position on the viewport - so the elements seem to grow upwards.
Note this snippet uses contenteditable on a div rather than a textarea as the growing/shrinking and text wrapping then happen automatically.
<style>
body {
height: 300vh;
}
.parent {
margin-top: 20vh; /* so we can see it growing not just disappearing */
background: pink;
}
.child {
background: #eeeeee;
}
</style>
<body>
<div class="parent">
Some stuff in the parent<br> here
<div class="child" contenteditable></div>
</div>
<script>
let prevH = 0;
const textArea = document.querySelector('.child');
const resizeObserver = new ResizeObserver(entries => {
for (let entry of entries) {
let h = entry.contentRect.height;
let diff = h - prevH;
if (diff != 0) {
prevH = h;
window.scroll(0, prevH);
}
}
});
resizeObserver.observe(textArea);
</script>
</body>
Upvotes: 3
Reputation: 2901
Textboxes can't expand their height automatically like this by default - you'll need to use a bit of Javascript.
One approach is to dynamically calculate the height of the textfield based on the number of line breaks inside it.
This example from CSS-Tricks has more details on the approach. I've implemented it on your code below.
You also need to change height
to min-height
on your inputbox-wrapper
to allow it to expand as the textfield changes height.
let textarea = document.querySelector(".chat-input-box");
textarea.addEventListener("keyup", () => {
textarea.style.height = calcHeight(textarea.value) + "px";
});
function calcHeight(value) {
let numberOfLineBreaks = (value.match(/\n/g) || []).length;
// min-height + lines x line-height + padding + border
let newHeight = 20 + numberOfLineBreaks * 20 + 0 + 0;
// padding and border are both 0 here but have left in for reference
return newHeight;
}
.chat-inputbox-container {
/* border: 1px solid red; */
width: 100%;
height: 113px;
align-self: flex-end;
display: flex;
justify-content: center;
}
.chat-inputbox-wrapper {
width: 736px;
height: 92px;
display: flex;
flex-direction: row;
justify-content: space-between;
}
.chat-microphone-container {
width: 32px;
height: 92px;
/* border: 1px solid orange; */
display: flex;
align-items: center;
justify-content: center;
margin-right: 10px;
}
.chat-microphone {
width: 32px;
height: 32px;
background: orangered;
}
.inputbox-wrapper {
width: 694px;
min-height: 52px;
/* border: 1px solid blue; */
display: flex;
align-self: flex-end;
align-items: center;
margin-top: 16px;
background: gray;
border: 1px solid red;
box-sizing: border-box;
border-radius: 4px;
}
.chat-input-box {
width: 632px;
height: 20px;
font-size: 14px;
line-height: 20px;
border: hidden;
background: #f7f7f7;
outline: none;
color: #0d1c3d;
margin: 16px 10px;
}
.input-box-btn {
/* Auto Layout */
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
padding: 0px;
position: static;
width: 32px;
height: 32px;
margin-right: 10px;
background: #0078b3;
border-radius: 4px;
flex: none;
order: 0;
flex-grow: 0;
margin: 0px 0px;
}
.input-character-container {
}
.input-character {
font-size: 12px;
line-height: 16px;
color: #677083;
}
<div class='chat-inputbox-container'>
<div class='chat-inputbox-wrapper'>
<div class='chat-microphone-container'>
<div class='chat-microphone'></div>
</div>
<div class='inputbox-container'>
<div class='inputbox-wrapper'>
<textarea type='text' class='chat-input-box'></textarea>
<div class='input-box-btn'></div>
</div>
<div class='input-character-container'>
<span class='input-character'>
250 out of 250 characters left
</span>
</div>
</div>
</div>
</div>
Upvotes: 1
Reputation:
The .inputbox-wrapper
should have a min-height
not a height
if you set only a height, the container will not resize with the textbox
.
On another note, if you want the textarea to expand vertically only, you can add resize: vertical;
to .chat-input-box {
Upvotes: 1