Div'ın altındaki div ile çarpıldığında yukarı kaydırılmasını engeller misiniz?


10

Dün benzer bir soru sordum ama kötü bir şekilde açıkladım ve saf-CSS çözümü için arzumu belirtmedim, ki bunun mümkün olması gerektiğini düşünüyorum, bu yüzden tekrar deniyorum.

Temelde, kaydırılabilir iletilerin bir div ve altında bir giriş alanı var bir sorun var. Bir düğmeyi tıklattığımda, giriş alanının mesajların da kaydırılmasını gerektirmeden giriş alanının 100 piksele çıkmasını istiyorum.

İşte sorunu bütünüyle gösteren bir keman

Gördüğünüz gibi, "kenar boşluğu ekle" düğmesini tıkladığınızda, mesaj div de yukarı kayar. Olduğu yerde kalmasını istiyorum. Benzer şekilde, yalnızca sondan ikinci mesaja görebilmeniz için hafifçe yukarı kaydırılırsanız, düğmeyi tıklatmak da tıklatıldığında aynı konumu korumalıdır.

İlginç olan, bu davranışın "bazen" korunmasıdır. Örneğin, bazı durumlarda (ki tam olarak çıkaramıyorum) kaydırma konumu korunur. Sadece sürekli böyle davranmasını istiyorum.

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>

resim açıklamasını buraya girin


1
Tekrar merhaba, JS kullanarak sorunuzu cevaplayan benim. Yanlış yorumlamış olabileceğiniz bir şey hakkında sizi bilgilendirmek istiyorum. Bahsettiğiniz: mesajlar div de yukarı kayar . Aslında, divyukarı kaydırılan şey değil , azalan div'ın yüksekliği. Peki bu neden önemli? Bunun anlamı, scrollbarkonumunu ayarlamamasıdır. Kaydırma çubuğu yalnızca kabının üstünden göreli konumunu hatırlar . Div'in yüksekliği azaldığında, kaydırma çubuğu yukarı doğru kayıyor gibi görünüyor, ancak aslında değil.
Richard

1
Gönderiniz mükemmel bir anlam ifade ediyor (insanların hangi sonucu istediğinizi bildiği anlamında), ancak bilginin sizin için belirgin olmaması durumunda bir şey paylaşıyorum (çözmeniz için bir fikir bulmanıza yardımcı olabilirse) dedi sorun) ;-)
Richard

Evet çok doğru, açıklama için teşekkürler. Yalnızca yukarı kaydırıyormuş gibi "görünür", çünkü bir zamanlar daha düşük içerikleri göremezsiniz. Gerçekte kaydırma konumu değişmez. Biraz yanılsama. Evet, bu bir çözüm bulmaya yardımcı olabilir.
Ryan Peschel

Yanıtlar:


5

Bu hoşunuza gidebilecek komik bir çözümdür.

Div hakkında bildiklerimiz, kaydırma çubuğunun yalnızca üst konumunu koruduğundan, böylece yükseklik herhangi bir nedenle değiştiğinde kaydırma çubuğu aynı kalır ve bu da soruna neden olur.

Geçici çözüm olarak , içeriği çevirmeyi iptal etmek için .messageskullanarak 180 dereceyi transform: rotate(180deg) scaleX(-1);çevirebilir ve geri çevirebilirsiniz .message, ardından div otomatik olarak alt kaydırma çubuğunu (üstte) korur.

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>


Bu, fare tekerleğini geriye doğru kaydırma sorunudur (yukarı kaydırma aşağı ve aşağı kaydırma yukarı gider)
Ryan Peschel

Tamam ben bu konuda çok zaman geçirdim ama hala diğer geliştiriciler aradığınız 3 cevap var :) ben size iyi şanslar diliyorum yardımcı olmayı umuyordum. ancak sorunuzu cevaplamak için zaman harcayan bir öneri olarak, bunu yaparak ücretlendirilmezsiniz.
Basil

2
Tabi ki.
Neyse

Bu çok akıllı ;-) Ne yazık ki, ters kaydırma biraz yıldırıcı.
Richard

3

Kaydırma çubuğunun normal davranışı üstte olacak şekilde olduğundan, sayfa yüklemesinde en alta ayarladığınızda, kendiniz tutmanız gerekir, çünkü aşağıdaki içerik onu ittiğinde div kaydırma yukarı taşınır.

Size iki çözümüm var:

  1. Mesaj div içindeki mesajları ters çevirerek son mesaj ilk olur, böylece kaydırma her zaman en üstte olur.

  2. Herhangi bir öğenin altına kaydırmak için bir javascript işlevi oluşturdum, böylece sadece aşağıya kaydırmak istediğinizde çağırın.

function scrollbottom(e)
    {
      e.scrollTop = e.clientHeight;
    }

Snippet'i kontrol edin

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>


Ne yazık ki sadece aşağı kaydırmak için kaydırmak istemiyorum. Pozisyonunu korumak istiyorum. Ayrıca, bunun Javascript olmadan da yapılması mümkündür. OP'den: "Benzer şekilde, hafifçe yukarı kaydırılırsanız, yalnızca sondan ikinci mesaja kadar görebiliyorsanız, düğmeyi tıklatmak da tıklandığında bu konumu korumalıdır."
Ryan Peschel

3

Bunu başka bir şekilde yapabilirsiniz , bu durumda .messages vermek yerine yüksekliği vererek .containermesajları etkilemez, divancak bunu verirseniz .containerbölgeniz ana kenarın içindedir çünkü yüksekliği olan div.

Bu pasajı kontrol et

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>


Bu işe yaramaz çünkü marjın uygulanması gerekir .send-message. Benim önceki soruma bakarsanız, bu, sanal klavyeyi mobil cihazlarda açmanın kenar boşluğuna benzediği için yapılır (kenar boşluğu, çözümde hata ayıklamak için sadece 1: 1 yerine geçer)
Ryan Peschel

3

Basit çözüm, scrollTopöncekini geçişe ayarlamaktır . Burada önceki değeri saklamak için veri kümesi kullanıyorum scrollTop, değişken de kullanabilirsiniz.

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>


0

Yani, tam olarak örneğinizi çözen yalnızca CSS çözümü:

.some-margin{margin-bottom:100px;}

.messages{margin-top:-100px;}

ancak sanal klavyedeki orijinal sorununuzda size yardımcı olacağını düşünmüyorum. Ama belki de bu başka birine bir çözüme ilham verebilir.

Ana sorun, kaydırma çubuğunun zaten tam olarak ne istediğinizi yapması gibi görünüyor :

En son okunan içerik görünür olacak şekilde konumunu koruma.

Kaydırma çubuğu hariç, o anda görünür olan içeriğin ÜSTÜNÜ altta değil görmek istediğinize karar verir. (Sayı kullanıp kullanmadığınızı görmek daha kolaydır: https://jsfiddle.net/1co3x48n/ )

Javascript kullanmaya istekli iseniz, her türlü cevap vardır: https://www.google.com/search?q=scrollbar+always+on+bottom+css+site:stackoverflow.com

Dürüst olmak gerekirse, bunun ~ 3 + sayfalarından geçip sadece Javascript cevaplarını bulabileceğiniz gerçeği, bana sadece CSS ile cevap bulamayacağınızı, kesinlikle geniş tarayıcı uyumlu bir cevap bulamayacağınızı söylüyor.


0

Sağlanan çözümlerin hiçbiri maalesef işe yaramıyor gibi görünüyor. onFocusBir metin kutusu için kullanımdaki sorun , metin kutusunun zaten odağı varsa uygulanmamasıdır. Saatlerdir bununla uğraşıyorum ve şimdiye kadar bulduğum en yakın çözüm şu:

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;      
  });
}

Ancak, bu sadece bazen işe yarıyor gibi görünüyor. Metin kutusunu tıklattığında% 100 çalışır, ancak bazı nedenlerden dolayı sanal klavyeyi kapatırken yalnızca yeterince yukarı kaydırıldığında çalışır. Aksi takdirde her seferinde aynı konuma sıfırlanır (tabana yakın, ancak tabana değil).

Buna neyin sebep olduğundan emin değilim. Sanırım yarın daha fazlasını araştırmak zorunda kalacağım. Bu şimdiye kadarki en yakın olanı.


Hepimizin cevaplarında söylediğimiz gibi, sadece CSS ile yapmak imkansız görünüyor. (JS kodunuzla ilgili bir sorun var, yani chatElem.scrollTop 0'dan küçük olamaz , bu yüzden üste çok yakınsa, negatif bir sayı olmaya çalışır, bunun yerine 0 olur, ardından ekranı büyüttüğünüzde yine, daha önce olmadığı yerde bir kaydırma belirir.)
Eliezer Berlin

Aynı şekilde, chatElem.scrollTop, chatElem.scrollHeight - chatElem.offsetHeight'tan daha fazla olamaz , bu yüzden bunu yapmaya çalışırsanız daha önce olmayan bir kaydırma oluşturur.
Eliezer Berlin

0

Yukarıdaki örneklerde olduğu gibi bir kap oluşturun, ancak yazmaya başladığınızda yalnızca CSS'yi değiştirin.

Kaydırma çubuğu konumunu ayarlamıyorum, tüm mesaj kabını yukarı doğru hareket ettirin. Böylece, kaydırma konumunuz ne olursa olsun aynı kalacaktır. En azından aşağıya doğru, elbette üstteki çizgileri göremezsiniz.

Css'i ihtiyaçlarınıza göre ayarlayabilmelisiniz. JS kullanırsanız bile kullanabilirsiniz: odak veya biraz farklı CSS kurulumu, yaratıcı olun :)

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>


0

kenar boşluğu eklerken fonksiyona eklemelisiniz document.querySelector(".messages").scrollTop = 10000;, testsonra scrollTopayarladığınız yükte sona ermeli scrolltopve kenar boşluğu eklediğinizde veya kenar boşluğunu kaldırdığınızda, scrolltopkomut dosyanızı bu şekilde değiştirmeyin

<script>
    window.onload = function(e){ 
    document.querySelector(".messages").scrollTop = 10000;
}

function test() {
    document.querySelector(".send-message").classList.toggle("some-margin")
            document.querySelector(".messages").scrollTop = 10000;
}
    </script>

0

Js geçiş işleviyle ilgili bir sorun var gibi görünüyor. Basit bir saklambaç olarak değiştirdim. Ayrıca giriş etiketine bir genişlik ekledim. Ayrıca bir mesaj: gönderme mesajı div ve alt: mutlak olarak eklemeniz gerekir, böylece altta kalır. ardından konum: kapsayıcıya gönderme mesajı div kap içinde kalacak şekilde yerleştirin. Bu, ileti kabının iletileri kendilerinin etkilemeyeceği ve yukarı doğru itmeyeceği anlamına gelir.

window.onload = function(e) {
  document.querySelector(".messages").scrollTop = 10000;
};

function test() {
  var x = document.querySelector(".send-message");

  if (x.style.display === "none") {
    x.style.display = "block";
  } else {
    x.style.display = "none";
  }
}
.container {
     width: 400px;
     height: 300px;
     border: 1px solid #333;
     display: flex;
     flex-direction: column;
     position: relative;
}
 .messages {
     overflow-y: auto;
     height: 100%;
}
 .send-message {
     width: 100%;
     display: flex;
     flex-direction: column;
     position: absolute;
     bottom: 0;
}
 .send-message input {
     width:100%;
}
 .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">test</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>


Bu çözümü anlamıyorum. Kenar boşluğu ekle'yi tıkladığınızda mesaj gönder metin kutusunu gizliyor musunuz?
Ryan Peschel

-1

Ortaya koyabileceğim saf olmayan bir CSS yaklaşımı şudur:

window.onload = function(e){ 
  document.querySelector(".messages").scrollTop = 10000;
}

document.querySelector('button').addEventListener('click', test)

function test() {
  document.querySelector(".send-message").classList.toggle("some-margin")
  document.querySelector('.wrapper').classList.toggle('wrapper--transformed')
}
.container {
  width: 400px;
  height: 300px;
  border: 1px solid #333;
  display: flex;
  flex-direction: column;
}

.messages {
  position: relative;
  overflow-y: auto;
  height: 100%;
}

.wrapper {
  display: block;
}

.wrapper--transformed {
  transform: translateY(-100px);
  margin-bottom: -100px;
}

.send-message {
  width: 100%;
  display: flex;
  flex-direction: column;
}

.some-margin {
  margin-bottom: 100px;
}
<div class="container">
  <div class="messages">
    <div class = "wrapper">
      <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>
  <div class="send-message">
    <input />
  </div>
</div>
<button>add margin</button>

En üstteki bölümün kenar boşluğu olduğunda küçük bir sorunu vardır. Buradaki hile negatif kenar boşluğu kullanmak ve div'ı "yukarı kaydırmak" (gerçekten bir kaydırma değil, sadece bir yanılsama) için çeviriyi kullanmaktır wrapper.


En üstteki bölüm sorunu biraz sorun, evet. Ayrıca, bu, ne kadar telafi edileceğini bilmek için mobil klavyenin tam boyutunu bildiğini varsayar mı? Bu bilgilere erişimim olup olmadığından emin değilim.
Ryan Peschel

Sorunuzu cevaplamak için: evet. Yukarıdaki teknik klavyenin tam yüksekliğini bilmelidir. Ancak, bir öğenin yüksekliğini belirlemek ve CSS'yi değiştirmek için JS kullanmanın yolları vardır.
Richard

Mobil sanal klavyenin yüksekliğini nasıl belirlersiniz?
Ryan Peschel

@RyanPeschel Bu sanal klavye bir HTML öğesi divmi (örn. )?
Richard

Nasıl kodlandığından emin değilim.
Ryan Peschel

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.