I am trying to learn some React and CSS and I am struggling with one thing.
I am trying to create a chat page , but when there are many messages , the message - container pushes down the input box. React code:
const message = useRef()
function submit(e) {
e.preventDefault();
addMessage(msgBox => [...msgBox , message.current.value])
}
const [msgBox, addMessage] = useState(["John: Hi"])
return (
<>
<div className = "chat-container">
{msgBox.map((msg) => {
return <div><span>{msg}</span><br/></div>
})}
</div>
<div className = "message-box">
<Form onSubmit = {submit}>
<input ref = {message} />
<Button type = "submit" className = "mb-1 position-fixed">
Send
</Button>
</Form>
</div>
</>
)
CSS :
* {
margin: 0;
padding: 0;
}
.chat-container {
min-height: 90vh;
min-width: 80%;
position: relative;
}
span {
padding: 60px;
}
.message-box {
min-height: 10vh;
position: absolute;
}
.message-box > form > input {
margin-left: 60px;
}
I tried to play around with the position properties, but I coudn't make it happen.I want the message-box to not be pushed down by chat-container when there are too many messages.
I want when there are too many messages the chat-container not to overlap at all the message-box and be able to scroll there.
Any help?
I just want to add a bit more to the solution, as the previous answers are quite poor, since whenever the viewport changes, the 500px value would not work. In this app case, we have:
I suppose you are designing an app like WhatsApp Web, so you would have something like the following:
Here is how the structure would look in HTML:
<div class="chat-wrapper">
<div class="chat-messages">
<div class="message left">Some text</div>
<div class="message left">Lorem ipsum dolor sit amet, consectetur adipiscing elit. In nulla sem, placerat a est eu, interdum consectetur ipsum. Sed sed libero ac mauris scelerisque convallis et eget elit. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Mauris vel iaculis purus. Nunc placerat nisi sapien, id facilisis sapien faucibus sit amet. Vestibulum felis eros, fermentum quis augue eu, vehicula dapibus nisi. Suspendisse potenti.</div>
<div class="message right">Some text</div>
<div class="message right">Some text</div>
<div class="message left">Some text</div>
<div class="message right">Lorem ipsum dolor sit amet, consectetur adipiscing elit. In nulla sem, placerat a est eu, interdum consectetur ipsum. Sed sed libero ac mauris scelerisque convallis et eget elit. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Mauris vel iaculis purus. Nunc placerat nisi sapien, id facilisis sapien faucibus sit amet. Vestibulum felis eros, fermentum quis augue eu, vehicula dapibus nisi. Suspendisse potenti.</div>
<div class="message left">Some text</div>
<div class="message right">Some text</div>
<div class="message right">Some text</div>
<div class="message left">Some text</div>
</div>
<div class="chat-input">
<input name="message" class="chat-input" />
</div>
</div>
Now, the window height would be the 100%
of the height, which is the same as 100vh
. From here, you can create a parent container, whose height would be the entire viewport:
.chat-wrapper {
height: 100vh;
width: 50%;
margin: auto;
}
The chat wrapper would be the class for the parent of the div
containers of the messages. Then, we would define two more classes, that will be the containers for the div
's of the messages and the input
itself:
/* Container for the message */
.chat-messages {
padding: 16px 36px 0;
min-height: calc(100% - 75px);
max-height: calc(100% - 75px);
overflow: auto;
}
/* Container for the input */
.chat-input {
background-color: #efefef;
min-height: 75px;
max-height: 75px;
display: flex;
justify-content: flex-left;
align-items: center;
padding: 0 32px;
}
The trick here, is how we calculate the height
of the messages. As you can see, we are using the 100%
of the height, but we are also subtracting the fixed height
of the input container. Therefore, the messages container will always push the input container to the bottom, without removing it from the actual viewport. Plus, we add the overflow: auto
prop, which will allow the scrolling inside the container.
Finally, we can add other styling classes to the other fields.
/* Default styling for the messages */
.message {
padding: 8px;
border-radius: 8px;
width: fit-content;
max-width: 65%;
margin-bottom: 8px;
border: 1px solid #dedede;
}
/* Default styling for the right messages */
/* You could also modify the styled for the left messages with the left class */
.message.right {
background-color: #dcf8c6;
margin-left: auto;
}
.chat-input {
padding: 8px;
width: 100%;
height: 65%;
border-radius: 8px;
outline: none;
border: none;
}