[javascript] 그 아래 div에 부딪 쳤을 때 div 스크롤을 방지합니까?
내가 물었다 비슷한 질문을 어제하지만 가난을 설명하고, 내가 다시 노력하고, 그래서 가능해야한다고 생각 순수 CSS 솔루션에 대한 내 욕망을 지정하지 않았습니다.
기본적으로 스크롤 가능한 메시지 div와 그 아래에 입력 필드가있는 문제가 있습니다. 버튼을 클릭하면 메시지 div를 스크롤하지 않고도 입력 필드가 100 픽셀로 증가하고 싶습니다.
보시다시피, “여백 추가”버튼을 클릭하면 메시지 div도 위로 스크롤됩니다. 나는 그것이 있던 곳에 머물고 싶습니다. 마찬가지로, 약간 위로 스크롤하여 두 번째에서 마지막 메시지 만 볼 수있는 경우 버튼을 클릭하면 클릭시 해당 위치가 유사하게 유지됩니다.
흥미로운 점은이 동작이 “때때로”보존된다는 것입니다. 예를 들어, 어떤 상황에서는 (추론 할 수없는) 스크롤 위치가 유지됩니다. 나는 그것이 일관되게 그렇게 행동하기를 원합니다.
window.onload = function(e) {
document.querySelector(".messages").scrollTop = 10000;
};
function test() {
document.querySelector(".send-message").classList.toggle("some-margin");
}
.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">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>
답변
이것은 당신이 좋아할만한 재미있는 솔루션입니다.
우리가 div에 대해 알고있는 것은 스크롤 막대의 상단 위치 만 유지하므로 어떤 이유로 인해 높이가 변경되면 스크롤 막대가 동일하게 유지되어 문제가 발생합니다.
해결 방법으로 내용을 뒤집기를 취소 하려면 을 .messages
사용하여 180도를 transform: rotate(180deg) scaleX(-1);
뒤집고 뒤로 뒤집을 수 있습니다 .div .message
는 아래쪽 스크롤 막대 (상단)를 자동으로 유지합니다.
function test() {
document.querySelector(".send-message").classList.toggle("some-margin")
}
.container {
width: 400px;
height: 300px;
border: 1px solid #333;
display: flex;
flex-direction: column;
}
.messages {
overflow-y: auto;
height: 100%;
transform: rotate(180deg) scaleX(-1);
}
.message
{
transform: rotate(180deg) scaleX(-1);
}
.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">hello10</div>
<div class="message">hello11</div>
<div class="message">hello12</div>
<div class="message">hello13</div>
<div class="message">hello14</div>
<div class="message">hello15</div>
<div class="message">hello16</div>
<div class="message">hello17</div>
<div class="message">hello18</div>
<div class="message">hello19</div>
<div class="message">hello20</div>
</div>
<div class="send-message">
<input />
</div>
</div>
<button onclick="test()">add margin</button>
답변
스크롤 막대의 정상적인 동작은 상단에 있으므로 페이지로드시 맨 아래에 설정하면 아래 내용을 푸시 할 때 div 스크롤이 맨 위로 이동하기 때문에 자체적으로 유지해야합니다.
그래서 두 가지 해결책이 있습니다.
-
메시지 div 내부의 메시지를 뒤집어 마지막 메시지가 첫 번째 메시지가되도록하여 스크롤이 항상 맨 위에 오도록합니다.
-
모든 요소의 맨 아래로 스크롤하는 자바 스크립트 함수를 만들었으므로 맨 아래로 스크롤 할 때마다 호출하면됩니다.
function scrollbottom(e)
{
e.scrollTop = e.clientHeight;
}
스 니펫 확인
var elem = document.querySelector(".messages");
window.onload = function(e){
scrollbottom(elem);
}
function test() {
document.querySelector(".send-message").classList.toggle("some-margin");
scrollbottom(elem);
}
function scrollbottom(e)
{
e.scrollTop = e.clientHeight;
}
.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">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>
답변
이 경우에 높이를 .messages
주는 대신 높이를 주면 다른 방법으로 할 수 있습니다 .container
. 메시지에는 영향을 미치지 div
않지만 .container
마진이 주 안에 있기 때문에 div를 푸시합니다. 높이가있는 div.
이 스 니펫 확인
function test() {
document.querySelector(".send-message").classList.toggle("some-margin");
}
.container {
width: 400px;
border: 1px solid #333;
display: flex;
flex-direction: column;
}
.messages {
height: 300px;
overflow-y: auto;
}
.send-message {
width: 100%;
display: flex;
flex-direction: column;
}
.some-margin {
margin-bottom: 50px;
}
<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">hello10</div>
<div class="message">hello11</div>
<div class="message">hello12</div>
<div class="message">hello13</div>
<div class="message">hello14</div>
<div class="message">hello15</div>
<div class="message">hello16</div>
<div class="message">hello17</div>
<div class="message">hello18</div>
<div class="message">hello19</div>
<div class="message">hello20</div>
</div>
<div class="send-message">
<input />
</div>
</div>
<button onclick="test()">add margin</button>
답변
간단한 해결 방법은 이전 scrollTop
켜기 토글 을 설정하는 것 입니다. 여기에서 이전 값 을 저장하기 위해 데이터 세트 를 scrollTop
사용하고 있습니다. 변수를 사용할 수도 있습니다.
window.onload = function(e) {
document.querySelector(".messages").scrollTop = 10000;
}
function test() {
let state = document.querySelector(".send-message").classList.toggle("some-margin")
let div = document.querySelector(".messages");
if (state) {
div.dataset.top = div.scrollTop;
div.scrollTop += 100 // same as margin-bottom of .some-margin
} else {
div.scrollTop = div.dataset.top;
}
}
.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">hello10</div>
<div class="message">hello11</div>
<div class="message">hello12</div>
<div class="message">hello13</div>
<div class="message">hello14</div>
<div class="message">hello15</div>
<div class="message">hello16</div>
<div class="message">hello17</div>
<div class="message">hello18</div>
<div class="message">hello19</div>
<div class="message">hello20</div>
</div>
<div class="send-message">
<input />
</div>
</div>
<button onclick="test()">add margin</button>
답변
내 말은, 다음은 귀하의 예를 정확하게 해결하는 CSS 전용 솔루션입니다.
.some-margin{margin-bottom:100px;}
.messages{margin-top:-100px;}
하지만 가상 키보드의 원래 문제를 해결하는 데 도움이되지는 않습니다. 그러나 이것은 아마도 다른 사람에게 해결책을 줄 수 있습니다.
주요 문제는 스크롤 막대가 이미 원하는 것을 정확하게 수행하는 것 같습니다.
가장 최근에 읽은 컨텐츠를 볼 수 있도록 위치를 유지하십시오.
스크롤바를 제외하고는 맨 아래가 아니라 현재 표시된 컨텐츠의 TOP을 보겠다고 결정합니다. (숫자를 사용하는 것이 더 쉽습니다. https://jsfiddle.net/1co3x48n/ )
자바 스크립트를 사용하려는 경우 모든 종류의 답변이 있습니다.
https://www.google.com/search?q=scrollbar+always+on+bottom+css+site:stackoverflow.com
솔직히, 당신이 이것의 ~ 3 + 페이지를 통과하고 Javascript 답변 만 찾을 수 있다는 사실은 CSS 전용 답변을 찾지 못할 것이라는 것을 말해줍니다. 확실히 브라우저와 호환되는 답변은 아닙니다.
답변
제공된 솔루션 중 어느 것도 불행히도 작동하지 않는 것 같습니다. onFocus
텍스트 상자에 사용할 때의 문제 는 텍스트 상자에 이미 포커스가 있으면 적용되지 않는다는 것입니다. 나는 이것을 몇 시간 동안 엉망으로 만들었으며 지금까지 생각해 낸 가장 가까운 해결책은 다음과 같습니다.
componentDidMount() {
this.screenHeight = window.innerHeight;
let chatElem = document.querySelector(".conversations-chat");
window.addEventListener('resize', () => {
let diff = this.screenHeight - window.innerHeight;
chatElem.scrollTop += diff;
this.screenHeight = window.innerHeight;
});
}
그러나 이것은 때때로 작동하는 것 같습니다. 텍스트 상자를 클릭하면 100 % 작동하지만 가상 키보드를 닫을 때 스크롤을 올린 경우에만 작동합니다. 그렇지 않으면 매번 같은 위치로 재설정됩니다 (바닥 근처이지만 바닥은 아님).
그 원인이 무엇인지 잘 모르겠습니다. 내일 더 많은 것을 조사해야 할 것입니다. 이것은 지금까지 가장 가까운 것입니다.
답변
위 예제와 같이 컨테이너를 생성 한 다음 입력을 시작할 때 CSS를 변경하십시오.
스크롤바 위치를 설정하지 않고 전체 메시지 컨테이너를 위로 이동하십시오. 따라서 스크롤 위치에 관계없이 동일하게 유지됩니다. 물론 아래쪽으로 내려 가면 맨 위에 선이 표시되지 않습니다.
CSS를 필요에 맞게 조정할 수 있어야합니다. : focus 또는 약간 다른 CSS 설정을 사용하면 JS 없이도 창의력을 발휘할 수 있습니다. 🙂
function activate(){
document.querySelector("#container").classList.toggle("active");
}
#container{
position:relative;
width:300px;
height:100vh;
max-height:230px;
overflow:hidden;
}
#messages{
position:absolute;
bottom:30px;
overflow:auto;
height:200px;
width:100%;
background:#eee;
}
#container.active #messages {
bottom:100px;
}
#send-message{
position:absolute;
border:1px solid #ccc;
bottom:0;
height:28px;
}
#container.active #send-message{
height:100px;
}
<div id="container">
<div id="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 id="send-message">
<input id="newmessage" onclick="activate()" type="text" />
</div>
</div>