Uwaga! Trwają prace nad nową wersją serwisu. Mogą występować przejściowe problemy z jego funkcjonowaniem. Przepraszam za niedogodności!

⛔ Potrzebujesz wsparcia? Oceny CV? A może Code Review? ✅ Dołącz do naszej społeczności na Discordzie!

Czy to koniec vh? Nowe jednostki CSS – wysokość viewportu

Twórz bezbłędne layouty na urządzenia mobilne!

Każdy programista znający CSS spotkał się z jednostką vh. Jednak mało który zdaje sobie sprawę, jakie konsekwencje może mieć jej nieprzemyślane użycie – szczególnie jeśli mówimy o aplikacjach mobilnych. Zobaczmy, jakie problemy mogą wystąpić podczas korzystania z vh oraz jak im zaradzić!

Chcesz lepiej zapamiętać to zagadnienie? Wykonaj warsztat z HTML i CSS: Responsywność, aby osiągnąć swój cel!

Spis treści

Czy słyszałeś o uciętym buttonie, który kosztował ponad 8 milionów dolarów? Ta historia pokazuje, jak istotne jest poprawne pozycjonowanie elementów na urządzeniach mobilnych. Pozostań po bezpiecznej stronie i naucz się nowych jednostek dla określania wysokości viewportu!

 Geneza wprowadzenia nowych jednostek

Korzystając z przeglądarek internetowych, często wchodzimy na strony, które zajmują 100% dostępnej przestrzeni w pionie. Jako przykład może posłużyć nam strona logowania Facebooka czy Twittera. Aby osiągnąć taki efekt, możemy skorzystać z szeroko wykorzystywanej reguły CSS:

.app-container {
  width: 100%;
  height: 100vh;
  overflow: hidden;
}

Okazuje się jednak, że taki sposób definiowania wysokości kontenerów powoduje spore utrudnienia podczas korzystania z aplikacji webowych na telefonach.

 Dynamiczny pasek URL

W 2015 roku Apple w swoich przeglądarkach Safari wprowadza dynamiczny pasek URL. Chowa się on i wysuwa podczas scrollowania strony. Jest to funkcja, która często pozostaje niezauważona, ale znacząco zwiększa nam dostępną przestrzeń na ekranie. Obecnie chyba każdy producent przeglądarek internetowych zaadoptował to rozwiązanie.

Spójrz na poniższy GIF, aby zobaczyć przykład działania dynamicznego paska.

Chowający się pasek przeglądarki

Niestety tuż po wprowadzeniu tej funkcjonalności użytkownicy zaczęli zgłaszać błędy związane z tym, że layouty stron skaczą, a niektóre przyciski na dole stron internetowych są zasłonięte. Jak to możliwe?

 vh na komputerze różni się od vh na telefonie

Różnica między vh na komputerze i telefonie jest subtelna, ale może powodować sporo problemów.

Na urządzeniach mobilnych obszar viewportu zaczyna się od górnej krawędzi paska, ale jest przesunięty w dół o jego wysokość. Na komputerze viewport zaczyna się od paska i nie ma żadnego przesunięcia.

Spróbujmy wspólnie odtworzyć błąd, który może wynikać z wyżej opisanej różnicy.

 Błędy związane z wysokością 100vh

Stworzę prostą aplikację – formularz subskrypcji usługi. Chciałbym, aby użytkownik miał możliwość skorzystania z darmowego okresu próbnego po kliknięciu przycisku na samym dole ekranu. Korzystając z zasad UX, taki przycisk umieszczam niżej, by miał trochę mniejszą wagę wizualną niż przycisk służący do wyboru płatnej subskrypcji.

Chciałbym, aby przycisk darmowej subskrypcji był „przyklejony” do dołu ekranu. Tworzę wspomnianą wcześniej regułę height: 100vh. Dodatkowo dodaję overflow: hidden, gdyż aplikacja nie ma się scrollować. Korzystam z flexboxa, aby elementy zajmowały całą dostępną przestrzeń.

.app-container {
  height: 100vh;
  overflow: hidden;
}

Aplikację podejrzysz dzięki GitHub Pages, a jej kod znajdziesz na repozytorium. Poniżej załączam zrzuty ekranu, które z niej pochodzą.

W przeglądarce komputerowej nie zobaczymy żadnego problemu, dlatego skorzystałem z przeglądarki Blisk, która emuluje różne telefony. Podgląd z testów umieszczam na zdjęciu poniżej.

Testy layoutu w przeglądarce Blisk

Tutaj też wszystko prezentuje się dobrze. Stronę mogę wrzucić na produkcję i cieszyć się wolnym popołudniem.

Dla pewności sprawdzam projekt na swoim smartfonie i… ku mojemu zdziwieniu strona wcale nie wygląda tak, jak powinna – jest ucięta o wysokość paska URL. Wypchnął on zawartość strony w dół, nie respektując ustawionej wcześniej wartości 100vh.

Zrzut ekranu ze smartfona Huawei P20

Zrzut ekranu ze smartfona Huawei P20

Zrzut ekranu ze smartfona iPhone 8

Zrzut ekranu ze smartfona iPhone 8

Zobaczmy kolejny przykład. Tym razem to prawdziwa gra webowa, gdzie również użyto wysokości 100vh do stworzenia kontenera:

Zdjęcie uciętego widoku gry esviji

Źródło: real-app z https://nicolas-hoizey.com/articles/2015/02/18/viewport-height-is-taller-than-the-visible-part-of-the-document-in-some-mobile-browsers/

Jak widzisz, obecność dynamicznego paska URL przesuwa zawartość strony.

 Rozwiązanie problemu uciętego widoku

Pomoc nadchodzi dopiero po 7 latach od wprowadzenia dynamicznych belek URL.

Grupa robocza CSS tworzy trzy nowe jednostki, a na początku 2022 roku Apple wprowadza je do Safari. Nowe jednostki biorą pod uwagę zachowanie dynamicznych elementów interfejsu przeglądarki (w tym paska URL) i pozwalają w bezpieczny sposób tworzyć layouty rozciągające się na całą dostępną przestrzeń ekranu.

 Nowe jednostki określające wysokość względem viewportu

Grupa robocza CSS wyróżnia trzy nowe jednostki:

  • large viewport-percentage unit, w skrócie lv,
  • small viewport-percentage unit, w skrócie sv,
  • dynamic viewport-percentage unit, w skrócie dv.

W momencie pisania tego artykułu jednostki są dostępne w trzech największych przeglądarkach desktopowych i mobilnych (Chrome, Firefox i Safari), dlatego polecam testowanie ich w tych aplikacjach.

Dostępność nowych jednostek w przeglądarkach

Żródło: https://caniuse.com/viewport-unit-variants

Poznajmy wspólnie każdą z trzech nowych jednostek!

 Large viewport (lv)

Large viewport height (w skrócie lvh) to wysokość widoku obliczona przy założeniu, że elementy interfejsu przeglądarki są schowane.

Aby lepiej zrozumieć definicję, spójrz na poniższą grafikę ilustrującą lvh.

Layout przy zastosowaniu jednostek lvh

Aby skorzystać z jednostki lvh, użyję poniższej reguły CSS. Teraz, gdy wszystkie „pływające” elementy przeglądarki (np. pasek wyszukiwarki, pasek nawigacji) będą schowane, element o klasie .app-container powinien zajmować całą dostępną przestrzeń pionową:

.app-container {
  height: 100lvh;
}

Jednostki lvh stosujemy dla kontenerów, które:

  • mają zajmować 100% dostępnej przestrzeni pionowej, gdy elementy interfejsu przeglądarki się schowają,
  • nie muszą mieścić się na dostępnym obszarze przy załadowaniu strony,
  • nie zmieniają swojego rozmiaru podczas scrollowania strony.

Jeśli by się nad tym zastanowić, to można dojść do wniosku, że 100lvh jest po prostu równe obecnemu 100vh.

 Small viewport (sv)

Small viewport height (w skrócie svh) oznacza wysokość dostępnego obszaru ekranu obliczoną przy założeniu, że elementy interfejsu przeglądarki są wysunięte.

Poniższa grafika pomoże Ci w zrozumieniu definicji svh.

Layout przy zastosowaniu jednostek svh

Reguła CSS może w tym przypadku wyglądać tak:

.app-container {
  height: 100svh;
}

Jednostki svh stosujemy dla kontenerów, które:

  • mają zajmować 100% dostępnej przestrzeni pionowej,
  • muszą zmieścić się przy załadowaniu strony (czyli świetnie nadają się na pozycjonowanie przycisków na dole ekranu),
  • nie zmieniają swojego rozmiaru podczas scrollowania strony.

 Dynamic viewport (dv)

Ostatnią i najbardziej użyteczną jednostką jest dynamiczna wysokość viewportu (dvh).

Oznacza ona wysokość dostępnego obszaru ekranu, która jest obliczana w zależności od stanu interfejsu przeglądarki:

  • jeśli elementy interfejsu są schowane, to 100dvh będzie odpowiadało 100lvh,
  • jeśli elementy interfejsu są wysunięte, to 100dvh będzie równe 100svh.

Layout przy zastosowaniu jednostek dvh

Aby użyć dynamicznej wysokości viewportu, skorzystałbym z tej reguły:

.app-container {
  height: 100dvh;
}

Jednostka dvh wydaje się być najlepszym wyborem. Mamy pewność, że:

  • kontenery będą zajmować 100% dostępnej przestrzeni pionowej,
  • na pewno zmieszczą się przy załadowaniu strony,
  • powiększą się podczas scrollowania strony, w związku z czym zmienią swój rozmiar.

Może teraz zastanawiasz się: po co stosować lvh i svh, skoro dvh łączy najlepsze cechy obu?

Stosowanie dvh zmieni wysokość elementów podczas scrollowania – gdy wyświetlimy stronę i elementy interfejsu przeglądarki będą widoczne, wysokość kontenera będzie mniejsza. Gdy zaczniemy scrollować i elementy interfejsu się schowają, wysokość kontenera będzie większa. Kontener musi więc być ostylowany tak, by zmiany jego wysokości nie wpływały rażąco na wygląd.

Weźmy pod uwagę przykładowy kod:

.text.text-big {
  font-size: 2dvh;
}

Jak myślisz, co stanie się podczas scrollowania strony, gdy wielkość czcionki jest uzależniona od dynamicznej jednostki? Jeśli pomyślałeś, że nagle zmieni się jej wielkość, to miałeś rację!

Podobny problem napotkamy w innych przypadkach, kiedy zależy nam na stałym rozmiarze elementów. Mogą to być na przykład okna iframe, wykresy czy grafiki, które muszą zachować stałe proporcje.

Działanie nowych jednostek możesz przetestować w tej aplikacji, a kod podejrzysz na repozytorium. Jeśli Twoja przeglądarka nie wspiera nowych jednostek, to nie będziesz miał możliwości ich ustawienia.

Działanie nowych jednostek – podgląd GIF

 Podsumowanie

Poznane jednostki pomogą Ci uniknąć popularnych błędów związanych z wysokością kontenerów w aplikacjach webowych. Ciesz się nimi w Twoim kolejnym projekcie i bądź pewien, że layout nie zachowa się w sposób nieprzewidziany. Pamiętaj, by sprawdzić, czy przeglądarka, dla której tworzysz aplikacje, wspiera nowe rozwiązanie.

 Źródła

Udostępnij ten artykuł:

Mentoring to efektywna nauka pod okiem doświadczonej osoby, która:

  • przekazuje Ci swoją wiedzę i nadzoruje Twoje postępy w zdobywaniu umiejętności,
  • uczy Cię dobrych praktyk i wyłapuje złe nawyki,
  • wspiera Twój rozwój i zwiększa zaangażowanie w naukę.

Mam coś dla Ciebie!

W każdy piątek rozsyłam motywujący do nauki programowania newsletter!

Dodatkowo od razu otrzymasz ode mnie e-book o wartości 39 zł. To ponad 40 stron konkretów o nauce programowania i pracy w IT.

PS Zazwyczaj wysyłam 1-2 wiadomości na tydzień. Nikomu nie będę udostępniał Twojego adresu e-mail.