
📜 Blok przewijania w CSS i jQuery: stała wysokość z przewijaniem
Przydługie tasiemce SEO, komentarze na pół ekranu, logi w panelu administracyjnym i tabele na 30 kolumn, wszystko to rozjeżdża układ i zmusza czytelnika do kręcenia kółkiem w nieskończoność. Brzmi znajomo? Rozwiązanie jest i jest ono wręcz nieprzyzwoicie proste: blok ze stałą wysokością i wewnętrznym przewijaniem.
Kiedy dopiero zaczynałem układać strony, upychałem treść w overflow: hidden i modliłem się, żeby nikt nie zauważył obciętego tekstu. Z czasem doszedłem do bloku przewijanego i to zmieniło wszystko: teksty SEO klientów stały się schludne, strony przestały się rozdymać na urządzeniach mobilnych, a sąsiednie skrypty przestały ze sobą kolidować.
Poniżej dwa sprawdzone podejścia: czysty CSS (do większości zadań) oraz nakładka jQuery (do niestandardowych scenariuszy). Oba przetestowane w boju na dziesiątkach projektów, działają poprawnie na urządzeniach mobilnych i nie zaczepiają sąsiednich skryptów.
💡 Szybki przegląd:
- Proszę owinąć treść w
<div>z klasamiscroll-blockiscroll-content - Proszę ustawić w CSS
max-height+overflow-y: auto, blok przewijany jest gotowy - Proszę podłączyć wtyczkę jQuery z artykułu, aby uzyskać autoprzewijanie, animację i zdarzenia
- Proszę ostylować pasek przewijania przez
::-webkit-scrollbarzgodnie z projektem strony
Czym jest blok przewijany i gdzie jest naprawdę potrzebny
Blok przewijany to kontener o stałej wysokości, którego zawartość przewija się wewnątrz niezależnie od głównego przewijania strony. Przeglądarka dodaje pasek przewijania automatycznie, gdy treść przekroczy zadaną wysokość.
Gdzie stosuję to rozwiązanie stale:
- Teksty SEO. Klient chce tasiemiec na 3000 słów w środku landing page’a, owijam go w blok przewijany, strona nie zamienia się w nieskończone płótno.
- Komentarze i logi. Długie łańcuchy dyskusji lub logi debugowania w panelu administracyjnym, stała wysokość ratuje interfejs przed rozjechaniem.
- Tabele z danymi. Przewijanie poziome dla tabel to klasyka, ale przewijanie pionowe w tabeli z ponad 50 wierszami rozwiązuje problem nie gorzej.
- Widgety czatu i powiadomienia. Okno czatu z historią wiadomości to ten sam blok przewijany, tylko z autoprzewijaniem do ostatniej wiadomości.
Technicznie wszystko opiera się na dwóch właściwościach CSS: max-height (lub height) i overflow-y. Ale diabeł tkwi w szczegółach: przeglądarki mobilne, zagnieżdżone kontenery, konflikty z position: fixed oraz specyfika iOS Safari wymagają ostrożnego podejścia.
Proszę obejrzeć krótki samouczek dotyczący właściwości overflow, pokazuje on wizualnie wszystkie tryby przewijania i ich zachowanie:
Rozwiązanie CSS: szybko i bez JavaScript
W zdecydowanej większości przypadków JavaScript nie jest potrzebny. Wystarczą trzy linijki CSS:
1 .scroll-block { 2 max-height: 320px; 3 overflow-y: auto; 4 border: 1px solid #e0e0e0; 5 padding: 16px; 6 }
Rozbiór na czynniki pierwsze. max-height wyznacza pułap: blok nie urośnie powyżej 320px, ale może być mniejszy, jeśli treści jest mało. overflow-y: auto mówi przeglądarce: „pokaż pasek przewijania tylko wtedy, gdy treść przepełni kontener". Obramowanie i padding są opcjonalne, ale bez paddingu tekst przykleja się do paska przewijania, co wygląda tandetnie.
Kod HTML pozostaje przy tym semantycznie czysty:
1 <div class="scroll-block"> 2 <p>Ваш длинный SEO-текст, логи, таблица или что угодно.</p> 3 </div>
To rozwiązanie działa identycznie w Chrome, Firefox, Safari i Edge: specyfikacja overflow jest stabilna od CSS2 i jest wspierana przez wszystkie nowoczesne przeglądarki. Na urządzeniach mobilnych przewijanie wewnątrz bloku nie koliduje z głównym przewijaniem strony (w przeciwieństwie do sprytnych rozwiązań JavaScript z lat 2010., które przechwytywały touchmove i często psuły przewijanie).
Jest jednak pewien niuans z iOS Safari: domyślnie przewijanie wewnątrz bloku jest „niesprężyste", nie ma natywnego efektu rubber-band. Jeśli potrzebne jest płynne, inercyjne przewijanie, jak w głównej treści, proszę dodać:
1 .scroll-block { 2 -webkit-overflow-scrolling: touch; 3 }
Właściwość -webkit-overflow-scrolling: touch włącza natywne przewijanie momentum na iOS. Proszę wziąć pod uwagę: wraz z premierą iOS 13 Apple uczyniło to zachowanie domyślnym dla overflow: auto, więc dla nowszych wersji prefiks jest opcjonalny. Jeśli jednak projekt wspiera starsze iPady, proszę go zostawić.
Rozwiązanie jQuery: gdy potrzebna jest pełna kontrola
Sposób CSS rozwiązuje większość zadań. Pozostałe przypadki to sytuacje, gdy potrzebne jest programowe przewinięcie do dołu (czat), niestandardowe zdarzenia przy osiągnięciu granic bloku lub animacja przewijania za pomocą przycisku. Tutaj wkracza jQuery.
Podaję gotową wtyczkę, minimalistyczną, bez zależności poza samym jQuery, sprawdzoną w projektach z nowoczesnymi wersjami WordPressa i niekolidującą z innymi skryptami w szablonie:
1 (function($) { 2 $.fn.scrollBlock = function(options) { 3 var settings = $.extend({ 4 maxHeight: 320, 5 autoScroll: false, 6 scrollSpeed: 400, 7 onTopReached: null, 8 onBottomReached: null 9 }, options); 10 11 return this.each(function() { 12 var $block = $(this); 13 14 $block.css({ 15 'max-height': settings.maxHeight + 'px', 16 'overflow-y': 'auto' 17 }); 18 19 if (settings.autoScroll) { 20 $block.animate({ 21 scrollTop: $block[0].scrollHeight 22 }, settings.scrollSpeed); 23 } 24 25 $block.on('scroll', function() { 26 var scrollTop = $block.scrollTop(); 27 var maxScroll = $block[0].scrollHeight - $block.outerHeight(); 28 29 if (scrollTop <= 0 && settings.onTopReached) { 30 settings.onTopReached.call(this); 31 } 32 if (scrollTop >= maxScroll && settings.onBottomReached) { 33 settings.onBottomReached.call(this); 34 } 35 }); 36 }); 37 }; 38 })(jQuery);
Miejsce uruchomienia: Pana/Pani skrypt (osobny plik JS szablonu lub sekcja <script> w stopce). Podłączenie po jQuery:
1 $(document).ready(function() { 2 $('.scroll-content').scrollBlock({ 3 maxHeight: 400, 4 autoScroll: true, 5 scrollSpeed: 600, 6 onBottomReached: function() { 7 console.log('Достигнут низ блока'); 8 } 9 }); 10 });
Co tu się dzieje: wtyczka przyjmuje selektor, nakłada ograniczenia CSS co do wysokości, opcjonalnie przewija blok do dołu i śledzi osiągnięcie górnej/dolnej granicy przez callbacki. Żadnej magii, nakładka na standardowe metody jQuery .css(), .animate() i zdarzenie scroll.
Warto użyć tego rozwiązania, gdy: a) trzeba autoprzewinąć czat do ostatniej wiadomości; b) potrzebna jest płynna animacja przewijania za pomocą zewnętrznego przycisku „W dół" / „W górę"; c) trzeba podpiąć analitykę pod zdarzenie „użytkownik doczytał do końca".
Kilka bloków na jednej stronie
Sytuacja: na stronie są trzy bloki przewijane z różną treścią. Jeśli nada się jedną klasę .scroll-block bez unikalnych identyfikatorów, wszystko działa, CSS stosuje się do wszystkich naraz. Ale gdy tylko każdy blok potrzebuje własnej wysokości, witamy w świecie ID.
CSS dla kilku bloków o różnej wysokości:
1 #seo-text-block { 2 max-height: 320px; 3 overflow-y: auto; 4 } 5 6 #changelog-block { 7 max-height: 480px; 8 overflow-y: auto; 9 } 10 11 #comments-block { 12 max-height: 600px; 13 overflow-y: auto; 14 }
HTML:
1 <div id="seo-text-block" class="scroll-block"> 2 <!-- Длинный SEO-текст --> 3 </div> 4 5 <div id="changelog-block" class="scroll-block"> 6 <!-- Список изменений --> 7 </div>
Z wtyczką jQuery ta sama logika: inicjalizuje Pan/Pani każdy blok osobno z własnymi ustawieniami:
1 $('#seo-text-block').scrollBlock({ maxHeight: 320 }); 2 $('#changelog-block').scrollBlock({ maxHeight: 480, autoScroll: true }); 3 $('#comments-block').scrollBlock({ maxHeight: 600, autoScroll: true, scrollSpeed: 300 });
Jeśli bloków jest dużo (10+) i wszystkie są jednakowe, wystarczy wspólna klasa. Jeśli są różne, ID plus indywidualne ustawienia. Żadnej magii z nth-child ani ręcznym iterowaniem: selektory CSS załatwiają to od razu.
Stylizacja paska przewijania: żeby nie wyglądało jak rok 2007
Domyślny pasek przewijania przeglądarki to szary prostokąt z epoki Windows XP. Dwie minuty CSS i wpasowuje się w projekt:
1 .scroll-block::-webkit-scrollbar { 2 width: 6px; 3 } 4 5 .scroll-block::-webkit-scrollbar-track { 6 background: #f1f1f1; 7 border-radius: 3px; 8 } 9 10 .scroll-block::-webkit-scrollbar-thumb { 11 background: #c1c1c1; 12 border-radius: 3px; 13 } 14 15 .scroll-block::-webkit-scrollbar-thumb:hover { 16 background: #a1a1a1; 17 }
Ważne: pseudoelementy ::-webkit-scrollbar działają w Chrome, Edge, Safari i Operze, czyli pokrywają zdecydowaną większość użytkowników. Firefox używa osobnych właściwości scrollbar-width: thin i scrollbar-color, ale nie można globalnie stylizować paska przewijania w Firefoksie na poziomie elementu (tylko na poziomie całej strony). Dla Firefoksa wystarczy:
1 html { 2 scrollbar-width: thin; 3 scrollbar-color: #c1c1c1 #f1f1f1; 4 }
Proszę nie przesadzać z szerokością paska przewijania: 4-8px to optymalny zakres. Cieńszy niż 4px, użytkownik nie trafi palcem na urządzeniu mobilnym. Grubszy niż 8px, pasek zaczyna przyciągać zbyt dużo uwagi.
⁉️🤔 Często zadawane pytania
Czy blok przewijany działa na urządzeniach mobilnych?
Tak, i to bez protez. Właściwość CSS
overflow-y: autojest natywnie wspierana przez iOS Safari i Chrome na Androida. Wewnętrzne przewijanie bloku nie koliduje z głównym przewijaniem strony: przeglądarka sama określa, który kontener przewijać, na podstawie położenia palca. Jedyny niuans: na starszych iOS (przed 13) proszę dodać-webkit-overflow-scrolling: touchdla przewijania inercyjnego.
Czy można używać bloku przewijanego wewnątrz kontenera Flexbox lub Grid?
Można. Blok przewijany potrzebuje stałej wysokości: proszę ją zadać przez
max-heightw pikselach lub przezflex-basis/grid-rowz wartością bezwzględną. Proszę nie używać wysokości procentowej wewnątrz potomka flex bez jawnej wysokości rodzica: przeglądarka nie będzie w stanie obliczyć bazy do wyliczenia przepełnienia i przewijanie się nie pojawi.
Jak zrobić płynne przewijanie bloku do dołu bez jQuery?
Na czystym JavaScript:
element.scrollTo({ top: element.scrollHeight, behavior: 'smooth' }). MetodascrollToz opcjąbehavior: 'smooth'jest wspierana przez wszystkie nowoczesne przeglądarki. Dla autoprzewijania czatu proszę wywoływać tę linijkę po dodaniu każdej nowej wiadomości.
Czy blok przewijany koliduje z innymi skryptami na stronie?
Rozwiązanie CSS, nie. To natywne właściwości przeglądarki, działają w izolacji. Wtyczka jQuery z artykułu używa własnej przestrzeni nazw
$.fn.scrollBlocki nie rusza zmiennych globalnych, więc konflikty są wykluczone. Sprawdzono na stronach z ponad 20 aktywnymi wtyczkami, problemów nie było.
Czy można animować pojawienie się bloku przewijanego?
Tak. Proszę dodać
max-height: 0ioverflow: hiddenw stanie początkowym, a następnie animować do docelowej wysokości. Gdy animacja się zakończy, proszę przełączyćoverflownaauto. W jQuery robi się to przez.animate({ 'max-height': '320px' }, 500, function() { $(this).css('overflow-y', 'auto') }). Na czystym CSS, przeztransition: max-height 0.5s ease.
JQuery czy CSS: co wybrać w 2026 roku
Rozwiązanie CSS pokrywa zdecydowaną większość scenariuszy i waży zero kilobajtów. Jeśli potrzebuje Pan/Pani po prostu schludnego bloku z wewnętrznym przewijaniem, proszę je wziąć i nie komplikować.
Wtyczka jQuery jest uzasadniona, gdy: robi Pan/Pani czat z autoprzewijaniem, podpina analitykę pod zdarzenia przewijania lub animuje przewijanie za pomocą zewnętrznego przycisku. W innych przypadkach nakładka jQuery to rozwiązanie nadmiarowe, które dodaje zależność od biblioteki dla trzech linijek CSS.
Proszę wypróbować wariant CSS od razu: proszę skopiować trzy linijki stylów, owinąć testową treść w <div class="scroll-block"> i otworzyć stronę na telefonie. Rezultat zobaczy Pan/Pani w minutę, bez npm install, bez bundlerów, bez bólu.



