我正在开发一个简单的聊天组件,但遇到一个问题,在移动设备上,如果我单击文本框发送消息,而不是弹出其上方的消息列表,虚拟键盘会将自己绝对定位在它。
这是不可取的,因为我希望用户在键入消息时能够看到最新消息。但是,我不知道如何纠正这种行为。 (而且我不能将文本框放在messages
div 因为它应该始终位于底部)
我创建了一个示例片段来演示问题在这里(添加底部边距演示的问题与单击文本框并弹出移动键盘相同)
基本上,如果您滚动到底部并单击“添加边距”按钮,您会看到它不是将内容推到其上方(这样您仍然可以看到最新消息),而是向上滚动。有什么办法可以避免这种情况吗?
这是代码的副本,以防小提琴出现故障:
<div class="container">
<div class="messages">
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
<div class="message">hello</div>
</div>
<div class="send-message">
<input />
</div>
</div>
<button onclick="test()">add margin</button>
.container {
width: 400px;
height: 300px;
border: 1px solid #333;
display: flex;
flex-direction: column;
}
.messages {
overflow-y: auto;
height: 100%;
}
.send-message {
width: 100%;
display: flex;
flex-direction: column;
}
.some-margin {
margin-bottom: 100px;
}
function test() {
document.querySelector(".send-message").classList.toggle("some-margin")
}
幸运的是,有。这里的问题是你没有处理滚动位置.messages
当。。。的时候.send-message
div 扩展(即获得更多边距)。我想你想调整它以便滚动位置最后visible消息作为其枢轴(即 div 展开之前的最后一条可见消息必须在 div 展开之后出现,反之亦然)。要调整所述滚动位置,这里有一个最小的工作示例(我稍微更改了您的 HTML 内容,以便您可以指示最后一条消息是什么,并且我调整了您的 JS 代码):
function test() {
let messageBox = document.querySelector('.messages')
let beforeMessageBoxHeight = messageBox.clientHeight
let afterMessageBoxHeight
let messageBoxHeightDifference
let beforeScrollTop = messageBox.scrollTop
let afterScrollTop
document.querySelector(".send-message").classList.toggle("some-margin")
afterMessageBoxHeight = messageBox.clientHeight
messageBoxHeightDifference = beforeMessageBoxHeight - afterMessageBoxHeight
afterScrollTop = beforeScrollTop + messageBoxHeightDifference
messageBox.scrollTop = afterScrollTop
}
.container {
width: 400px;
height: 300px;
border: 1px solid #333;
display: flex;
flex-direction: column;
}
.messages {
overflow-y: auto;
height: 100%;
}
.send-message {
width: 100%;
display: flex;
flex-direction: column;
}
.some-margin {
margin-bottom: 100px;
}
<div class="container">
<div class="messages">
<div class="message">hello1</div>
<div class="message">hello2</div>
<div class="message">hello3</div>
<div class="message">hello4</div>
<div class="message">hello5</div>
<div class="message">hello6</div>
<div class="message">hello7</div>
<div class="message">hello8</div>
<div class="message">hello9</div>
<div class="message">hello1</div>
<div class="message">hello2</div>
<div class="message">hello3</div>
<div class="message">hello4</div>
<div class="message">hello5</div>
<div class="message">hello6</div>
<div class="message">hello7</div>
<div class="message">hello8</div>
<div class="message">hello9</div>
<div class="message">hello1</div>
<div class="message">hello2</div>
</div>
<div class="send-message">
<input />
</div>
</div>
<button onclick="test()">add margin</button>
这个想法是:
- Get the
clientHeight
(可见高度,请阅读 MDN 文档以获取更多详细信息)在 div 展开之前
- Get the
scrollTop
值(从最上面的可见/不可见元素到最上面的可见元素测量的像素数)
- 当 div (
.send-message
) 展开,可见高度 (clientHeight
)自动缩小尺寸。这scrollTop
值仍然相同,这意味着最上面的可见元素beforediv 展开后仍然可见。然而,这不是我们想要的:我们希望在 div 展开之前最底部的可见元素保持可见
- 我们测量div展开后和div展开前的高度差。从逻辑上讲,高度差导致可见消息的底部部分(在 div 展开之前)显得不可见(由于溢出)。
- 要解决这个问题,请将高度差添加到之前的高度差中
scrollTop
值,以便在 div 展开之前很好地滚动到最底部的可见消息。
- 瞧,它有效。当 div 缩回时,您可以应用相同的逻辑。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)