Poprosiłem podobne pytanie wczoraj, ale wyjaśnił to źle, a nie określił moje pragnienie roztworu czystego CSS, które myślę, że powinno być możliwe, więc jestem znowu próbuje.
Zasadniczo mam problem polegający na tym, że mam div przewijalnych wiadomości i pole wprowadzania poniżej. Kiedy klikam przycisk, chciałbym, aby pole wejściowe zostało powiększone o 100 pikseli, bez przewijania div wiadomości.
Oto skrzypce, które pokazują problem w całości
Jak widać, po kliknięciu przycisku „dodaj margines”, div div również przewija się w górę. Chciałbym, żeby został na miejscu. Podobnie, jeśli jesteś lekko przewinięty w górę, aby zobaczyć tylko ostatnią wiadomość, kliknięcie przycisku powinno podobnie zachować tę pozycję po kliknięciu.
Interesujące jest to, że takie zachowanie jest „czasami” zachowane. Na przykład w niektórych okolicznościach (czego nie mogę do końca wywnioskować) pozycja przewijania jest zachowywana. Chciałbym tylko, żeby konsekwentnie zachowywał się jako taki.
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
przewijanie w górę, to wysokość div, która maleje. Więc dlaczego to ma znaczenie? Cóż, to znaczy, żescrollbar
nie dostosowuje swojej pozycji. Pasek przewijania zapamiętuje jedynie swoją pozycję względem góry kontenera. Gdy wysokość div spada, wydaje się, że pasek przewijania przewija się w górę, ale tak naprawdę nie jest.Odpowiedzi:
To zabawne rozwiązanie, które może ci się spodobać.
Co wiemy o div, że zachowuje on tylko górną pozycję paska przewijania, więc jeśli wysokość zmieni się z jakiegokolwiek powodu, pasek przewijania pozostanie taki sam i to jest przyczyną twojego problemu.
Aby obejść ten problem, możesz obrócić o
.messages
180 stopni za pomocątransform: rotate(180deg) scaleX(-1);
i odwrócić,.message
aby anulować odwracanie zawartości, a następnie div automatycznie utrzyma dolny pasek przewijania (który jest górny).źródło
Normalne zachowanie paska przewijania, aby znajdował się na górze, więc gdy ustawisz go na dole przy ładowaniu strony, musisz zachować to samo, ponieważ kiedy tylko popchnie go poniższa zawartość, przewijanie div przesunie się na górę.
Mam dla ciebie dwa rozwiązania:
Odwróć wiadomości wewnątrz div wiadomości, aby ostatnia wiadomość była pierwsza, więc przewijanie zawsze będzie na górze.
Stworzyłem funkcję javascript, aby przewijać na dół dowolnego elementu, więc wystarczy wywołać go, gdy chcesz przewinąć na dół.
Sprawdź fragment kodu
źródło
Możesz to zrobić na odwrót, podając wysokość
.messages
zamiast zamiast.container
w tym przypadku, nie wpłynie to na wiadomości,div
ale jeśli podasz.container
ją, popchnie div, ponieważ margines znajduje się w głównym div, które mają wysokość.Sprawdź ten fragment kodu
źródło
.send-message
. Jeśli spojrzysz na moje poprzednie pytanie, dzieje się tak, ponieważ jest to podobne do marginesu związanego z otwarciem wirtualnej klawiatury na urządzeniach mobilnych (dolny margines jest tylko zamiennikiem 1: 1 w celu debugowania rozwiązania)Prostym obejściem jest ustawienie poprzedniego
scrollTop
na przełączanie. Tutaj używam zestawu danych do przechowywania poprzedniejscrollTop
wartości, możesz użyć zmiennej albo.źródło
Mam na myśli, że poniższe rozwiązanie jest rozwiązaniem CSS, które rozwiązuje dokładnie Twój przykład:
ale nie sądzę, że pomoże ci to w rozwiązaniu twojego pierwotnego problemu z wirtualną klawiaturą. Ale może to może zainspirować kogoś innego do rozwiązania.
Głównym problemem wydaje się być to, że pasek przewijania działa już dokładnie tak, jak chcesz:
Utrzymanie pozycji tak, aby ostatnio czytana treść była widoczna.
Tyle że pasek przewijania decyduje, że chcesz zobaczyć GÓRĘ aktualnie widocznej zawartości, a nie dół. (Łatwiej jest sprawdzić, czy używasz liczb: https://jsfiddle.net/1co3x48n/ )
Jeśli chcesz używać javascript, znajdziesz wiele różnych odpowiedzi: https://www.google.com/search?q=scrollbar+always+on+bottom+css+site:stackoverflow.com
Szczerze mówiąc, fakt, że możesz przejrzeć ~ 3+ strony tego i znaleźć tylko odpowiedzi Javascript, mówi mi, że nie znajdziesz odpowiedzi tylko CSS, a na pewno nie takiej, która jest kompatybilna z przeglądarką.
źródło
Niestety żadne z dostarczonych rozwiązań nie działa. Problem z używaniem
onFocus
pola tekstowego polega na tym, że nie będzie on stosowany, jeśli pole tekstowe jest już aktywne. Grzebałem w tym od wielu godzin, a najbliższym rozwiązaniem, jakie do tej pory wymyśliłem, jest:Wydaje się to jednak czasami działać. Działa przez 100% czasu po kliknięciu pola tekstowego, ale z jakiegoś powodu podczas zamykania wirtualnej klawiatury działa tylko wtedy, gdy została wystarczająco przewinięta w górę. W przeciwnym razie za każdym razem resetuje się do tej samej pozycji (w pobliżu dna, ale nie do końca).
Nie jestem pewien, co to powoduje. Podejrzewam, że jutro będę musiał zbadać więcej. Jak dotąd jest to najbliższy.
źródło
Utwórz kontener jak w powyższych przykładach, ale po prostu zmień CSS, kiedy zaczniesz pisać.
Nie ustawiam pozycji paska przewijania, wystarczy przesunąć cały pojemnik wiadomości w górę. Niezależnie od tego, jaka będzie Twoja pozycja przewijania, pozostanie taka sama. Przynajmniej w dół oczywiście nie będzie widać linii u góry.
Powinieneś być w stanie dostosować css do swoich potrzeb. Możesz nawet przejść bez JS, jeśli używasz: skupienie lub nieco inna konfiguracja CSS, bądź kreatywny :)
źródło
musisz dodać
document.querySelector(".messages").scrollTop = 10000;
dotest
funkcji po dodaniu marginesu, a następniescrollTop
przejść do końca w ustawionym obciążeniu,scrolltop
a kiedy dodajesz margines lub usuwasz marginesscrolltop
nie ustawiłem ponownie, zmień skrypt w ten sposóbźródło
Wygląda na to, że występuje problem z funkcją przełączania js. Zmieniłem to na zwykły program Hide & Show. Dodałem również szerokość do znacznika wejściowego. Musisz także dodać pozycję: bezwzględną do div wiadomości wysyłanej i na dole: 0, aby pozostała na dole. następnie umieść pozycję: względną na kontenerze, tak aby div wiadomości wysyłającej pozostał w kontenerze. Oznacza to, że kontener wiadomości nie wpłynie na same wiadomości i nie popchnie ich w górę.
źródło
Całkowicie niedoskonałe podejście CSS, które mogę wymyślić, jest następujące:
Najwyższa sekcja ma mały problem, gdy jest margines. Sztuką jest użycie ujemnego marginesu i użycie translacji do „przewinięcia w górę” (nie tak naprawdę zwoju, tylko złudzenie)
wrapper
div.źródło
div
)?Można to bardzo prosto rozwiązać za pomocą nazw kotwic. Spójrz na skrzypce JS na https://jsfiddle.net/gvbz93sx/
Zmiana HTML
<a name="bottom"></a>
Zmiana JS
document.location.hash = "#bottom";
źródło