Window Controls Overlay: PWA'da Başlık Çubuğunu Devralmak
Masaüstüne kurulan bir PWA'da başlık çubuğu ölü alandır: otuz küsur piksellik bir şerit, içinde sadece pencere butonları. Window Controls Overlay o şeridi uygulamaya devreder ve butonların kapladığı kutuyu CSS değişkenleriyle bildirir. Kazanılan şey görsellik değil, yer. Asıl iş de orada başlıyor: o yeri butonların altında kalmayacak biçimde bölmek.
Manifest tarafı iki satır
manifest.json içine display_override ekleyin, listenin başına window-controls-overlay yazın:
"display": "standalone", "display_override": [ "window-controls-overlay", "standalone" ]
Chromium tabanlı masaüstü tarayıcılarda bunun için ayrı bir flag açmanız gerekmiyor, özellik yerleşik geldi. Ama yalnızca kurulu uygulamada ve yalnızca masaüstünde çalışıyor. Sekmede açılan aynı site, mobildeki aynı site, Safari'deki aynı site hiçbir şey olmamış gibi davranır. Bu yüzden overlay bir görünüm katmanıdır, üzerine düzen kurulacak bir zemin değil.
env() değerleri her zaman orada değil
Overlay aktifken tarayıcı dört değişken tanımlar: titlebar-area-x, titlebar-area-y, titlebar-area-width, titlebar-area-height. Bunlar başlık çubuğunun boş kalan kısmını tarif eder, pencerenin tamamını değil.
İki yerde tökezleniyor. Birincisi: overlay kapalıyken bu değişkenler tanımsızdır, yedeksiz yazılan height: env(titlebar-area-height) kuralı sekmede sessizce düşer. Her zaman ikinci argümanı verin.
.app-bar { position: fixed; left: env(titlebar-area-x, 0px); top: env(titlebar-area-y, 0px); width: env(titlebar-area-width, 100%); height: env(titlebar-area-height, 40px); } İkincisi daha sinsi: pencere butonlarının sağda olduğunu varsayıp sağa padding vermek. macOS'ta butonlar solda durur, Windows'ta sağda. titlebar-area-x tam da bunun için var; sıfır olduğunu varsayarsanız arayüzünüz iki platformdan birinde butonların altına kayar. Sabit bir kenardan değil, x ve width ikilisinden hesaplayın.
Sürükleme alanı ve altında kaybolan butonlar
Başlık çubuğunu devraldığınızda pencereyi taşıma işi de size geçer. -webkit-app-region: drag bir öğeyi tutamağa çevirir, ama bu miras yoluyla alt öğelere de iner ve o bölgedeki tıklamalar artık sürükleme sayılır. Şeridin içine koyduğunuz arama kutusu odaklanmaz, menü düğmesi açılmaz.
Üst şeridin tamamına drag vermem; ince bir tutamak bırakıp etkileşimli çocuklara -webkit-app-region: no-drag yazmak hem daha az sürprizli hem de sonradan öğe eklemeyi ucuzlatıyor.
.app-bar { -webkit-app-region: drag; } .app-bar button, .app-bar input { -webkit-app-region: no-drag; } Geometri değişince
navigator.windowControlsOverlay üzerinden visible alanını okuyabilir, getTitlebarAreaRect() ile alanın anlık ölçüsünü alabilir, geometrychange olayını dinleyebilirsiniz. Pencere yeniden boyutlandırılırken bu olay art arda tetiklenir, dinleyicinin içinde düzen hesabı yapıyorsanız işlemi geciktirin.
Yalnız şu sırayı bozmayın: CSS ile çözülen şeyi JS'e taşımak burada net bir kayıp. env() değerleri zaten tarayıcı tarafından güncelleniyor, aynı hesabı JS'te tekrarlamak sadece iki kaynaklı doğruluk problemi üretir. JS'i, alan belli bir genişliğin altına düştüğünde içeriği tamamen alt satıra almak gibi CSS'in tarif edemediği kararlar için saklayın.
Ne zaman zahmete değer
Overlay, üst şeride gerçekten bir şey koyacaksanız kazandırır: sekme listesi, arama, aktif doküman adı. Sadece logoyu oraya taşımak için üstlendiğiniz maliyet, iki platformluk konum farkı, drag alanı yönetimi ve sekmede çalışan bir yedek düzen, aldığınız otuz pikselden büyüktür.
Katlanabilir ekranlar, çentikler ve sanal klavye için gelen benzer API'lerin hepsi aynı mantıkla çalışıyor: tarayıcı size kullanılabilir alanı bir dikdörtgen olarak bildiriyor, düzeni o dikdörtgene göre kurmak sizin işiniz. Kutunun dışına çıkmak bir tasarım kararından çok, sabit sayıları değişkenlerle değiştirme alışkanlığı.
Kaynaklar