Usuwanie białych pasków w Safari na iPhone X

Apple przedstawiło niedawno swojego nowego flagowego smartfona – iPhone X. To co odróżnia go od poprzedników to głównie wyświetlacz rozciągający się od krawędzi do krawędzi. Oprócz pięknego wyglądu, niestety rodzi to pewne nowe problemy – między innymi z tym, że Safari na iOS domyślnie wyświetla białe paski po prawej i lewej na stronach www gdy obrócimy smartfon. Czy możemy zrobić coś, aby temu zaradzić? Okazuje się, że tak!

Wiele osób nabija się z iPhone X:

(więcej śmieszków z iPhone X i Safari 11 tutaj: https://blog.prototypr.io/notch-crazy-iphone-x-mad-475f43d6ee26)

Ale nie o tym ten wpis 😉 Wpis jest o tym, że mój blog domyślnie wygląda w ten sposób na nowym iPhonie:

iPhone X horizontal before

Widoczne są wyraźne paski z prawej i lewej strony. Są szare, gdyż domyślnie przyjmują one background-color z body lub html. Nie można jednak normalnie ustawić tam background-image, czyli żadnych obrazków ani gradientów… Jest to tzw. safe area, za którą użytkownik będzie trzymał telefon palcami i nie będzie sobie niczego zasłaniał. Ma to sens, ale czy mogłoby lepiej wyglądać? I, co ważniejsze, czy mamy na to wpływ? Tak! Poniżej podsumowanie ciekawostek z bloga WebKit.

CSS round display: viewport-fit

Szkic specyfikacji nieznanego mi dotąd CSS Round Display zawiera definicję viewport-fit, z którego Apple postanowiło skorzystać. Najnowsze Safari na iOS na iPhone X pozwala na użycie tej właściwości, aby treść z naszej strony wypełniła puste dotąd fragmenty po bokach. Dodanie tej nowej właściwości do tagu meta viewport na stronie spowoduje poprawę wyglądu strony:

<meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1.0, viewport-fit=cover">

(specyfikacja mówi o wykorzystaniu @viewport w CSS, ale nie próbowałem tego jeszcze z iPhone X i nie wiem czy zadziała – raczej nie, gdyż jest to kontrpropozycja dla przeforsowanego przez Apple tagu meta…). Efekt tagu meta jest następujący:

iPhone X Safari 11 viewport-fit cover

Wygląda to już lepiej, aczkolwiek teraz możemy mieć inny problem: część treści jest zbyt blisko rogów ekranu, albo może być zupełnie schowana za czarnym paskiem (kamera, czujniki…) z prawej strony! Czy i na to można coś poradzić bez karkołomnych zmian w CSS celujących tylko w iPhone X? Okazuje się, że tak!

safe-area-inset-* – top right bottom left

Gdy mamy viewport-fit=cover, możemy skorzystać z kilku wartości dostarczanych przez przeglądarkę w naszych stylach CSS. Posłuży nam do tego constant(…) Jak to działa? Safari na iOS 11 definiuje pewne wartości – np. mówi, że bezpieczna odległość od krawędzi telefonu do treści to ileś pikseli. My, jako twórcy strony możemy z tej wartości skorzystać i odpowiednie elementy o tę odległość przesunąć! Początkowo dla testów chciałem tylko dodać padding do body:

body {
    padding: constant(safe-area-inset-top) constant(safe-area-inset-right) constant(safe-area-inset-bottom) constant(safe-area-inset-left);
}

Oznacza to, że padding będzie wynosił odpowiednio tyle, ile przeglądarka ustali pod nazwami stałych safe-area-inset-top, safe-area-inset-right, safe-area-inset-bottomsafe-area-inset-left. Efekt jest taki:

iPhone X Safari 11 safe-area-inset-left

Po dalszych poprawkach kod ostatecznie wygląda tak:

.entry-header, .entry-summary, .entry-content, .author-info, .entry-meta, #nav-below, #comments, .post-continue-container, #colophon, #mobile-menu {
    padding-left: constant(safe-area-inset-left);
    padding-right: constant(safe-area-inset-right);
}

#sidebar {
    padding-left: calc(3em + constant(safe-area-inset-left));
    padding-right: calc(3em + constant(safe-area-inset-right));
}

#mobile-menu {
    padding-top: calc(6em + constant(safe-area-inset-top));
    padding-bottom: constant(safe-area-inset-bottom);
}

Dzięki czemu zdjęcia oraz menu są rozciągnięte na całą szerokość strony, ale treść nigdy nie zostanie przykryta przez pasek po prawej:

iPhone X Safari 11 safe-area-inset-left viewport-fit cover

Zauważ też, że constant można łączyć z calc!

Ten kod wpływa również na wyświetlanie strony na Safari na MacOS, ale w tym przypadku wszystkie wartości safe-area-inset-* są równe 0.

Muszę tutaj jednak nadmienić, że kilka dni temu słowo kluczowe constant zostało przemianowane w specyfikacji na env. W Safari nadal działa constant, ale niedługo może to ulec zmianie!

Safari Technology Preview od wersji 42 nie ma już constant — zgodnie ze standardem używane jest env. Zmiana ta pojawi się w stabilnym Safari oraz w Safari na iOS za jakiś czas. Więcej informacji: Safari Technology Preview Release Notes (Release 42)

Podsumowanie

Ciekawą uwagę wyraził Comandeer na Facebooku:

Najbardziej mnie śmieszy, że Apple w celu rozwiązania problemu, który sami stworzyli, próbują ustandaryzować w CSS „zmienne pochodzące od klienta użytkownika.

Dyskusja o specyfikacji na GitHubie: https://github.com/w3c/csswg-drafts/issues/1693

Co racja to racja. Jednak z drugiej strony, lepiej przecież w taki sposób, niż gdyby znowu próbować przepychać jakieś właściwości, które nigdy propozycją do standardu nie były i nie będą… Ponadto, z wprowadzanych pomysłów skorzystać mogą też inni producenci urządzeń i przeglądarek, np. podobnych smartfonów bez ramek, albo smartwatchy – gdy zajdzie taka potrzeba. A więc potencjalnie ten kod, mimo że aktualnie wpływa tylko na Safari, może działać bez zmian również na innych urządzeniach!

Warto też przetestować stronę na telefonie w pozycji wertykalnej, a także na desktopowym Safari, które również rozumie constant, ale tam wartości stałych wynoszą 0. U mnie na iPhonie X wygląda to tak: