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?
CodePudding user response:
Set max-height
on .chat-container
. You can use another value instead of 500px
. Play with it to find a value that matches your design.
.chat-container {
max-height: 500px
overflow: scroll
}
Update
If the height of the .chat-container
changes and you want to push the input at the bottom, do this:
Give all the parent of the
.chat-container
includinghtml
andbody
height: 100%
.Put the
.chat-container
andform
in ahtml
element that isflex
and itsflex-direction
iscolumn
.Use
flex-grow: 1
on the.chat-container
so that it always takes all the available space.
* {
margin: 0;
padding: 0;
}
html,
body {
height: 100%;
}
.container {
display: flex;
flex-direction: column;
height: 100%;
}
.chat-container {
flex-grow: 1;
overflow: scroll;
}
<div >
<div >
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Possimus expedita reiciendis, magnam provident fugit ad odit, nulla a nisi repellat eaque minus assumenda neque ea cumque blanditiis nobis repudiandae? Aliquid.</p>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Possimus expedita reiciendis, magnam provident fugit ad odit, nulla a nisi repellat eaque minus assumenda neque ea cumque blanditiis nobis repudiandae? Aliquid.</p>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Possimus expedita reiciendis, magnam provident fugit ad odit, nulla a nisi repellat eaque minus assumenda neque ea cumque blanditiis nobis repudiandae? Aliquid.</p>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Possimus expedita reiciendis, magnam provident fugit ad odit, nulla a nisi repellat eaque minus assumenda neque ea cumque blanditiis nobis repudiandae? Aliquid.</p>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Possimus expedita reiciendis, magnam provident fugit ad odit, nulla a nisi repellat eaque minus assumenda neque ea cumque blanditiis nobis repudiandae? Aliquid.</p>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Possimus expedita reiciendis, magnam provident fugit ad odit, nulla a nisi repellat eaque minus assumenda neque ea cumque blanditiis nobis repudiandae? Aliquid.</p>
</div>
<div >
<Form onSubmit={ submit}>
<input ref={ message} />
<Button type="submit" >
Send
</Button>
</Form>
</div>
</div>
You can adjust the height of the form
.
CodePudding user response:
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:
- The container with the chat messages, which should be scrollable and should have a fixed height.
- The container with the input which would have the rest of the height.
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 >
<div >
<div >Some text</div>
<div >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 >Some text</div>
<div >Some text</div>
<div >Some text</div>
<div >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 >Some text</div>
<div >Some text</div>
<div >Some text</div>
<div >Some text</div>
</div>
<div >
<input name="message" />
</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;
}