Cihazlar arası web uygulamaları oluşturmaya yönelik duyarlı olmayan bir yaklaşım

Boris Smus
Boris Smus

Medya sorguları harikadır ancak…

Medya sorguları, çeşitli boyutlardaki cihazlarda kullanıcılara daha iyi bir deneyim sunmak için stil sayfalarında küçük ayarlamalar yapmak isteyen web sitesi geliştiricileri için harika bir nimettir. Medya sorguları, sitenizin CSS'sini ekran boyutuna göre özelleştirmenize olanak tanır. Bu makaleyi incelemeden önce duyarlı tasarım hakkında daha fazla bilgi edinin ve medya sorgularının kullanımına dair bazı güzel örneklere mediaqueri.es adresinden göz atın.

Brad Frost'un önceki bir makalesinde belirttiği gibi, görünümü değiştirmek, mobil web için içerik oluştururken dikkate alınması gereken birçok şeyden yalnızca biridir. Mobil web sitenizi oluştururken tek yaptığınız şey düzeninizi medya sorgularıyla özelleştirmekse aşağıdaki durumla karşılaşırsınız:

  • Tüm cihazlar aynı JavaScript, CSS ve öğeleri (resimler, videolar) alır. Bu da gerekli olandan daha uzun yükleme sürelerine neden olur.
  • Tüm cihazlar aynı ilk DOM'u alır. Bu da geliştiricileri aşırı karmaşık CSS yazmaya zorlayabilir.
  • Her cihaza özel özel etkileşimler belirtme konusunda çok fazla esneklik yoktur.

Web uygulamalarının medya sorgularından daha fazlasına ihtiyacı vardır

Beni yanlış anlamayın. Medya sorguları aracılığıyla duyarlı tasarımdan nefret etmiyorum ve bu tasarımın kesinlikle dünyada bir yeri olduğunu düşünüyorum. Ayrıca, yukarıda belirtilen sorunların bazıları duyarlı resimler, dinamik komut dosyası yükleme gibi yaklaşımlarla çözülebilir. Ancak belirli bir noktada çok fazla artımlı ayar yaptığınızı fark edebilirsiniz. Bu durumda farklı sürümler yayınlamak daha iyi olabilir.

Oluşturduğunuz kullanıcı arayüzlerinin karmaşıklığı arttıkça ve tek sayfalık web uygulamalarına yöneldikçe kullanıcı arayüzlerini her cihaz türüne göre özelleştirmek için daha fazla işlem yapmanız gerekir. Bu makalede, bu özelleştirmeleri en az çabayla nasıl yapacağınız açıklanmaktadır. Genel yaklaşım, ziyaretçinizin cihazını doğru cihaz sınıfına sınıflandırmayı ve sürümler arasında kod yeniden kullanımını en üst düzeye çıkarırken bu cihaza uygun sürümü sunmayı içerir.

Hangi cihaz sınıflarını hedefliyorsunuz?

İnternete bağlı çok sayıda cihaz var ve bunların neredeyse hepsinde tarayıcı bulunuyor. Sorun, bu cihazların çeşitliliğinden kaynaklanıyor: Mac dizüstü bilgisayarlar, Windows iş istasyonları, iPhone'lar, iPad'ler, dokunmatik girişli Android telefonlar, kaydırma tekerlekleri, klavyeler, ses girişi, basınç hassasiyeti olan cihazlar, akıllı saatler, tost makineleri ve buzdolapları ve daha pek çok cihaz. Bu cihazlardan bazıları her yerde bulunurken bazıları çok nadirdir.

Çeşitli cihazlar.
Çeşitli cihazlar (source).

İyi bir kullanıcı deneyimi oluşturmak için kullanıcılarınızın kim olduğunu ve hangi cihazları kullandığını bilmeniz gerekir. Fare ve klavye kullanan bir masaüstü kullanıcısı için bir kullanıcı arayüzü oluşturup bunu akıllı telefon kullanıcısına verirseniz arayüzünüz başka bir ekran boyutu ve başka bir giriş modu için tasarlandığından kullanıcının canını sıkar.

Yaklaşımlar yelpazesinin iki uç noktası vardır:

  1. Tüm cihazlarda çalışacak tek bir sürüm oluşturun. Farklı cihazların farklı tasarım özellikleri olduğundan, kullanıcı deneyimi de bundan etkilenir.

  2. Desteklemek istediğiniz her cihaz için bir sürüm oluşturun. Uygulamanızın çok fazla sürümünü oluşturacağınız için bu işlem sonsuza kadar sürer. Ayrıca, bir sonraki yeni akıllı telefon çıktığında (yaklaşık olarak haftada bir) yeni bir sürüm daha oluşturmanız gerekir.

Burada temel bir denge vardır: Ne kadar çok cihaz kategoriniz varsa o kadar iyi bir kullanıcı deneyimi sunabilirsiniz ancak tasarım, uygulama ve sürdürme için o kadar fazla çalışma yapmanız gerekir.

Karar verdiğiniz her cihaz sınıfı için ayrı bir sürüm oluşturmak, performans nedeniyle veya farklı cihaz sınıflarına yayınlamak istediğiniz sürümler arasında büyük farklılıklar varsa iyi bir fikir olabilir. Aksi takdirde duyarlı web tasarımı oldukça makul bir yaklaşımdır.

Olası bir çözüm

Bu durumda, cihazları kategorilere ayırıp her kategori için mümkün olan en iyi deneyimi tasarlayabilirsiniz. Seçtiğiniz kategoriler ürününüze ve hedef kullanıcınıza bağlıdır. Günümüzde mevcut olan popüler web uyumlu cihazları kapsayan örnek bir sınıflandırmayı aşağıda bulabilirsiniz.

  1. küçük ekranlar + dokunmatik (çoğunlukla telefonlar)
  2. büyük ekranlar + dokunmatik (çoğunlukla tabletler)
  3. büyük ekranlar + klavye/fare (çoğunlukla masaüstü/dizüstü bilgisayarlar)

Bu, olası birçok dökümden yalnızca biridir ancak makalenin yazıldığı sırada çok mantıklı bir seçenektir. Dokunmatik ekranı olmayan mobil cihazlar (ör. özellikli telefonlar, bazı özel e-kitap okuyucular) yukarıdaki listede yer almıyor. Ancak bunların çoğunda klavye gezinme veya ekran okuyucu yazılımı yüklüdür. Sitenizi erişilebilirlik göz önünde bulundurarak oluşturursanız bu yazılımlar sorunsuz çalışır.

Form faktörüne özel web uygulamalarına örnekler

Farklı form faktörleri için tamamen farklı sürümler sunan birçok web mülkü örneği vardır. Google Arama ve Facebook da bunu yapar. Bu konuda dikkate alınması gerekenler arasında hem performans (öğe getirme, sayfa oluşturma) hem de daha genel kullanıcı deneyimi yer alır.

Yerel uygulamalar dünyasında birçok geliştirici, deneyimlerini bir cihaz sınıfına göre uyarlamayı tercih eder. Örneğin, iPad için Flipboard'un kullanıcı arayüzü, iPhone'daki Flipboard'dan çok farklıdır. Tablet sürümü iki el kullanımı ve yatay çevirme için optimize edilirken telefon sürümü tek elle etkileşim ve dikey çevirme için tasarlanmıştır. Diğer birçok iOS uygulaması da telefon ve tablet için önemli ölçüde farklı sürümler sunar. Örneğin, aşağıda gösterilen Things (yapılacaklar listesi) ve Showyou (sosyal video) uygulamaları:

Telefon ve tablet için önemli kullanıcı arayüzü özelleştirmeleri.
Telefon ve tablet için önemli kullanıcı arayüzü özelleştirmeleri.

1. Yaklaşım: Sunucu tarafı algılama

Sunucudaki cihaz hakkında çok daha sınırlı bilgiye sahibiz. Kullanabileceğiniz en yararlı ipucu muhtemelen her istekteki User-Agent başlığı aracılığıyla sağlanan kullanıcı aracısı dizesidir. Bu nedenle, burada da aynı UA algılama yaklaşımı işe yarayacaktır. Aslında DeviceAtlas ve WURFL projeleri bunu zaten yapıyor (ve cihaz hakkında birçok ek bilgi veriyor).

Maalesef bunların her biri kendi zorluklarını beraberinde getirir. 20 MB XML içeren WURFL çok büyüktür ve her istek için sunucu tarafında önemli ölçüde ek yük oluşturabilir. Performans nedeniyle XML'i bölen projeler vardır. DeviceAtlas açık kaynak değildir ve kullanılması için ücretli lisans gerekir.

Mobil Tarayıcıları Tespit Et projesi gibi daha basit ve ücretsiz alternatifler de vardır. Bunun dezavantajı, cihaz algılamanın kaçınılmaz olarak daha az kapsamlı olmasıdır. Ayrıca yalnızca mobil ve mobil olmayan cihazlar arasında ayrım yapar ve yalnızca geçici bir dizi ayarlama aracılığıyla sınırlı tablet desteği sağlar.

2. Yaklaşım: İstemci tarafında algılama

Özellik algılama özelliğini kullanarak kullanıcının tarayıcı ve cihazı hakkında çok şey öğrenebiliriz. Belirmemiz gereken en önemli noktalar, cihazın dokunmatik olup olmadığı ve ekranın büyük mü yoksa küçük mü olduğudur.

Küçük ve büyük dokunmatik cihazları ayırt etmek için bir yerde çizgi çekmemiz gerekiyor. 5 inç Galaxy Note gibi uç cihazlarda durum ne? Aşağıdaki grafikte, popüler Android ve iOS cihazların yan yana gösterildiği (ilgili ekran çözünürlükleriyle) bir grup cihaz gösterilmektedir. Yıldız işareti, cihazın iki katı yoğunlukta sunulduğunu veya sunulabileceğini belirtir. Piksel yoğunluğu iki katına çıkarılsa da CSS aynı boyutları raporlamaya devam eder.

CSS'deki piksellerle ilgili kısa bir not: Mobil web'deki CSS pikselleri, ekran pikselleriyle aynı değildir. iOS retina cihazlar, piksel yoğunluğunu ikiye katlama uygulamasını kullanıma sundu (ör. iPhone 3GS ve 4, iPad 2 ve 3). Retina Mobil Safari UA'ları, web'in bozulmasını önlemek için aynı cihaz genişliğini bildirmeye devam eder. Diğer cihazlar (ör. Android) daha yüksek çözünürlüklü ekranlar sunmak için aynı cihaz genişliği hilesini kullanıyor.

Cihaz çözünürlüğü (piksel cinsinden).
Cihaz çözünürlüğü (piksel cinsinden).

Ancak bu kararı verme sürecini karmaşıklaştıran, hem dikey hem de yatay modları dikkate almanın önemidir. Sayfayı farklı şekilde oluşturmak isteyebiliriz ancak cihazı her yeniden yönlendirdiğimizde sayfayı yeniden yüklemek veya ek komut dosyaları yüklemek istemeyiz.

Aşağıdaki şemada kareler, dikey ve yatay ana hatların üst üste binmesi (ve karenin tamamlanması) sonucunda her cihazın maksimum boyutlarını temsil etmektedir:

Dikey + yatay çözünürlük (piksel cinsinden)
Dikey + yatay çözünürlük (piksel cinsinden)

Eşiği 650px olarak ayarlayarak iPhone ve Galaxy Nexus'u "küçük dokunmatik ekran", iPad ve Galaxy Tab'i ise "tablet" olarak sınıflandırırız. Bu durumda, her iki cinsiyete de uygun Galaxy Note "telefon" olarak sınıflandırılır ve telefon düzenini alır.

Bu nedenle, makul bir strateji şöyle görünebilir:

if (hasTouch) {
  if (isSmall) {
    device = PHONE;
  } else {
    device = TABLET;
  }
} else {
  device = DESKTOP;
}

Özellik algılama yaklaşımının kullanıldığı minimum bir örneği inceleyin.

Buradaki alternatif yaklaşım, cihaz türünü algılamak için UA koku alma özelliğini kullanmaktır. Temel olarak bir dizi sezgisel kural oluşturur ve bunları kullanıcınızın navigator.userAgent ile eşleştirirsiniz. Sözde kod şu şekilde görünür:

var ua = navigator.userAgent;
for (var re in RULES) {
  if (ua.match(re)) {
    device = RULES[re];
    return;
  }
}

UA algılama yaklaşımının kullanıldığı bir örneği inceleyin.

İstemci tarafı yüklemeyle ilgili not

Sunucunuzda UA algılama yapıyorsanız yeni bir istek aldığınızda hangi CSS, JavaScript ve DOM'un sunulacağına karar verebilirsiniz. Ancak istemci tarafında algılama yapıyorsanız durum daha karmaşıktır. Birkaç seçeneğiniz vardır:

  1. Bu cihaz türünün sürümünü içeren, cihaz türüne özel bir URL'ye yönlendirin.
  2. Cihaz türüne özel öğeleri dinamik olarak yükleyin.

İlk yaklaşım basittir ve window.location.href = '/tablet' gibi bir yönlendirme gerektirir. Ancak konuma artık bu cihaz türü bilgileri eklenecektir. Bu nedenle, URL'nizi temizlemek için History API'yi kullanabilirsiniz. Maalesef bu yaklaşım, özellikle mobil cihazlarda yavaş olabilecek bir yönlendirme içerir.

İkinci yaklaşımın uygulanması oldukça daha karmaşıktır. CSS ve JS'yi dinamik olarak yüklemek için bir mekanizmaya ihtiyacınız vardır ve (tarayıcıya bağlı olarak) <meta viewport> öğesini özelleştirme gibi işlemleri yapamazsınız. Ayrıca, yönlendirme olmadığından, sunulan orijinal HTML'yi kullanmanız gerekir. Elbette JavaScript ile bu verileri değiştirebilirsiniz ancak bu işlem, uygulamanıza bağlı olarak yavaş ve/veya hantal olabilir.

İstemci veya sunucu seçimi

Bu yaklaşımlar arasındaki farklılıklar şunlardır:

Pro müşteri:

  • UA yerine ekran boyutlarına/özelliklerine dayalı olduğundan geleceğe daha hazırdır.
  • UA listesini sürekli olarak güncellemeniz gerekmez.

Pro sunucusu:

  • Hangi sürümün hangi cihazlara sunulacağına dair tam kontrol.
  • Daha iyi performans: İstemci yönlendirmelerine veya dinamik yüklemeye gerek yoktur.

Kişisel tercihim, device.js ve istemci tarafı algılama ile başlamaktır. Uygulamanız geliştikçe istemci taraflı yönlendirmenin önemli bir performans dezavantajı olduğunu fark ederseniz device.js komut dosyasını kolayca kaldırabilir ve UA algılamayı sunucuda uygulayabilirsiniz.

device.js ile tanışın

Device.js, özel sunucu tarafı yapılandırmaya ihtiyaç duymadan anlamsal, medya sorgusuna dayalı cihaz algılama yapmak için bir başlangıç noktasıdır. Böylece, kullanıcı aracısı dizesi ayrıştırma işlemi için gereken zaman ve çabadan tasarruf edilir.

Buradaki amaç, <head> dosyanızın en üstünde, sitenizin hangi sürümlerini sağlamak istediğinizi belirten arama motoru dostu işaretleme (link rel=alternate) sağlamaktır.

<link rel="alternate" href="http://foo.com" id="desktop"
    media="only screen and (touch-enabled: 0)">

Ardından, sunucu tarafında UA algılama yapabilir ve sürüm yönlendirmesini kendiniz yönetebilir veya özellik tabanlı istemci tarafı yönlendirme yapmak için device.js komut dosyasını kullanabilirsiniz.

Daha fazla bilgi için device.js proje sayfasını ve istemci taraflı yönlendirme için device.js kullanan sahte uygulamayı inceleyin.

Öneri: Form faktörüne özel görünümler içeren MVC

Şu anda muhtemelen her cihaz türü için birer tane olmak üzere üç tamamen ayrı uygulama oluşturmanızı söylediğimi düşünüyorsunuz. Hayır Kod paylaşımı anahtardır.

Umarım Backbone, Ember gibi MVC benzeri bir çerçeve kullanıyordunuz. Bu durumda, sorumlulukları ayırma ilkesine, özellikle de kullanıcı arayüzünüzün (görüntü katmanı) mantığınızdan (model katmanı) ayrılması gerektiğine aşinasınızdır. Bu konu sizin için yeniyse MVC ve JavaScript'te MVC ile ilgili bu kaynaklardan bazılarını inceleyerek başlayın.

Cihazlar arası hikaye, mevcut MVC çerçevenize mükemmel şekilde uyar. Görünümlerinizi kolayca ayrı dosyalara taşıyarak her cihaz türü için özel bir görünüm oluşturabilirsiniz. Ardından, görüntüleme katmanı hariç tüm cihazlara aynı kodu sunabilirsiniz.

Cihazlar arası MVC.
Cihazlar arası MVC.

Projeniz aşağıdaki yapıya sahip olabilir (elbette uygulamanıza en uygun yapıyı seçebilirsiniz):

models/ (ortak modeller) item.js item-collection.js

controllers/ (ortak denetleyiciler) item-controller.js

versions/ (cihaza özgü öğeler) tablet/ desktop/ phone/ (telefona özgü kod) style.css index.html views/ item.js item-list.js

Her cihaz için özel HTML, CSS ve JavaScript'iniz olduğundan bu tür bir yapı, her sürümün hangi öğeleri yükleyeceğini tam olarak kontrol etmenizi sağlar. Bu çok güçlü bir özelliktir ve cihazlar arası web için geliştirme yapmanın en basit ve en performanslı yolunu sunar. Bu sayede, uyarlanabilir resimler gibi hilelere başvurmanız gerekmez.

Favori derleme aracınızı çalıştırdıktan sonra, daha hızlı yükleme için tüm JavaScript ve CSS'nizi tek dosyalarda birleştirip küçülteceksiniz. Üretim HTML'niz aşağıdaki gibi görünecektir (telefon için device.js kullanılır):

<!doctype html>
<head>
  <title>Mobile Web Rocks! (Phone Edition)</title>

  <!-- Every version of your webapp should include a list of all
        versions. -->
  <link rel="alternate" href="http://foo.com" id="desktop"
      media="only screen and (touch-enabled: 0)">
  <link rel="alternate" href="http://m.foo.com" id="phone"
      media="only screen and (max-device-width: 650px)">
  <link rel="alternate" href="http://tablet.foo.com" id="tablet"
      media="only screen and (min-device-width: 650px)">

  <!-- Viewport is very important, since it affects results of media
        query matching. -->
  <meta name="viewport" content="width=device-width">

  <!-- Include device.js in each version for redirection. -->
  <script src="device.js"></script>

  <link rel="style" href="phone.min.css">
</head>
<body>
  <script src="phone.min.js"></script>
</body>

(touch-enabled: 0) medya sorgusunun standart olmadığını (yalnızca Firefox'ta moz tedarikçi ön ekinin arkasında uygulanır) ancak device.js tarafından doğru şekilde işlendiğini (Modernizr.touch sayesinde) unutmayın.

Sürüm geçersiz kılma

Cihaz algılama bazen hatalı olabilir. Bazı durumlarda kullanıcılar telefonlarındaki tablet düzenine bakmayı tercih edebilir (Galaxy Note kullanıyor olabilirler). Bu nedenle, kullanıcılarınıza manuel olarak geçersiz kılmak istediklerinde sitenizin hangi sürümünü kullanacaklarını seçme seçeneği sunmanız önemlidir.

Genel yaklaşım, mobil sürümünüzden masaüstü sürümüne bağlantı sağlamaktır. Bu, uygulanması kolay bir işlemdir ancak device.js bu işlevi device GET parametresiyle destekler.

Sonuç

Özetlemek gerekirse, duyarlı tasarım dünyasına tam olarak uymayan cihazlar arası tek sayfalık kullanıcı arayüzleri oluştururken şunları yapın:

  1. Desteklenecek cihaz sınıflarını ve cihazları sınıflara ayırmak için kullanılacak ölçütleri seçin.
  2. MVC uygulamanızı, görünümleri kod tabanının geri kalanından ayırarak güçlü bir sorumluluk ayrımı ile oluşturun.
  3. İstemci tarafında cihaz sınıfı algılama yapmak için device.js dosyasını kullanın.
  4. Hazır olduğunuzda komut dosyanızı ve stil sayfalarınızı cihaz sınıfı başına birer paket halinde gruplandırın.
  5. İstemci tarafı yönlendirme performansı sorun teşkil ediyorsa device.js'i bırakın ve sunucu tarafı UA algılamaya geçin.