且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何使移动键盘外观与div碰撞,而不是将其自身绝对定位在div上?

更新时间:2023-10-09 10:52:28

幸运的是,有.这里的问题是当.send-message div扩展时(即获得更多的边距),您没有处理.messages的滚动位置.我想您要对其进行调整,以使滚动位置将最后一个 visible 消息作为其枢轴(即,div扩展之前的最后一条可见消息必须在div扩展之后出现,反之亦然) .要调整所述滚动位置,这是一个最小的工作示例(我对您的HTML内容进行了一些更改,以便可以指示最后一条消息是什么,并且我调整了您的JS代码):

Fortunately, there is. The problem here is you are not handling the scroll position of the .messages when the .send-message div expands (i.e. gets more margin). I presume you want to adjust it so that the scroll position takes the last visible message as its pivot (i.e. the last visible message before the div expands has to appear after the div expands, and vice-versa). To adjust said scroll position, here's a minimal working example (I changed your HTML content a little so that you can indicate what the last message is and I adjusted your JS code):

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>

这个想法是:

  • 在div扩展之前获取clientHeight(可见高度,请阅读MDN文档以获取更多详细信息)
  • 获取scrollTop值(从最顶部的可见/不可见元素到最顶部的可见元素测量了多少像素)
  • 当div(.send-message)扩展时,可见高度(clientHeight)的大小会自动减小. scrollTop值仍然相同,这意味着div扩展之前的最强可见元素 仍然可见.但是,这并不是我们想要的:我们希望在div扩展之前保持最底端的可见元素
  • 我们在div扩展之后和div扩展之前测量高度差.从逻辑上讲,高度差是导致可见消息的底部(在div扩展之前)变得不可见(由于溢出)的原因.
  • 要解决该问题,请将高度差添加到先前的scrollTop值,以便在div扩展之前将其很好地滚动到最底部的可见消息.
  • Voila,它有效.当div撤消时,您可以应用相同的逻辑.
  • Get the clientHeight (visible height, read MDN Docs for more details) before the div expands
  • Get the scrollTop value (how many pixels measured from the topmost visible/invisible element to the topmost visible element)
  • When the div (.send-message) expands, the visible height (clientHeight) automatically reduces in size. The scrollTop value is still the same, which means that the topmost visible element before the div expands will still be visible. However, that is not what we want: we want the bottommost visible element before the div expands to remain visible
  • We measure the height difference after the div expands and before the div expands. Logically, the height difference is what is making the bottom parts of the visible messages (before the div expands) to appear invisible (due to overflow).
  • To address that issue, add the height difference to the previous scrollTop value so that it scrolls nicely to the bottommost visible message before the div expands.
  • Voila, it works. You can apply the same logic when the div retracts.