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

Boris Smus
Boris Smus

Medya sorguları harikadır, ancak...

Medya sorguları harikadır. Farklı boyutlardaki cihazların kullanıcılarına daha iyi bir deneyim sunmak için stil sayfalarında ufak değişiklikler yapmak isteyen web sitesi geliştiricileri için harika bir fırsattır. Medya sorguları, temelde ekran boyutuna göre sitenizin CSS'sini özelleştirmenize olanak tanır. Bu makaleyi incelemeden önce duyarlı tasarım hakkında daha fazla bilgi edinin ve medya sorguları kullanımına ilişkin bazı güzel örnekleri şurada inceleyin: mediaqueri.es.

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

  • Tüm cihazlar aynı JavaScript, CSS ve öğeleri (resim, video) alır. Bu da gerekenden daha uzun yükleme sürelerine neden olur.
  • Tüm cihazlar aynı başlangıç DOM'sini alır ve bu da geliştiricileri aşırı karmaşık CSS'ler yazmaya zorlayabilir.
  • Her bir cihaza göre özelleştirilmiş özel etkileşimler belirtme konusunda çok az esneklik vardır.

Web uygulamaları, medya sorgularından daha fazlasını gerektirir

Yanlış anlama. Medya sorguları üzerinden duyarlı tasarımdan nefret etmiyorum ve kesinlikle dünyada bir yeri olduğunu düşünüyorum. Ayrıca, yukarıda bahsedilen sorunlardan bazıları duyarlı resimler ve dinamik komut dosyası yükleme gibi yaklaşımlarla çözülebilir. Ancak bir noktada, çok fazla sayıda artımlı ince ayar yaptığınızı fark edebilir ve farklı sürümler sunmanız 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 her cihaz türüne yönelik kullanıcı arayüzlerini özelleştirmek için daha fazlasını yapmak isteyeceksiniz. Bu makalede, bu özelleştirmeleri en az çabayla nasıl yapacağınız hakkında bilgi verilmektedir. Genel yaklaşım, ziyaretçinizin cihazını doğru cihaz sınıfında sınıflandırmayı ve bu cihaza uygun sürümü sunmayı içerir. Aynı zamanda, sürümler arasında kodun yeniden kullanımını en üst düzeye çıkarır.

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

İnternet bağlantısı olan tonlarca cihaz var ve neredeyse hepsinin tarayıcısı var. Karmaşıklık, cihazların çeşitliliğinde yatı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, buzdolapları ve daha pek çok cihaz. Bu cihazlardan bazıları her yerde bulunurken bazıları çok nadirdir.

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

İ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. Bir masaüstü kullanıcısı için fare ve klavyeyle bir kullanıcı arayüzü oluşturup bu arayüzü akıllı telefon kullanıcısına verirseniz arayüzünüz farklı bir ekran boyutu ve farklı bir giriş modu için tasarlandığından hayal kırıklığı yaratacaktır.

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

  1. Tüm cihazlarda çalışan bir sürüm oluşturun. Sonuç olarak farklı cihazlarda farklı tasarım noktaları olduğu için kullanıcı deneyimi olumsuz yönde etkilenir.

  2. Desteklemek istediğiniz her cihaz için bir sürüm oluşturun. Uygulamanızın çok fazla sürümünü derleyeceğiniz için bu işlem geri alınamaz. Ayrıca, bir sonraki yeni akıllı telefon geldiğinde (yaklaşık olarak haftada bir kez gerçekleşir) yeni bir sürüm oluşturmak zorunda kalırsınız.

Burada temel bir denge söz konusudur: Ne kadar çok cihaz kategorisine sahip olursanız, o kadar iyi bir kullanıcı deneyimi sunabilirsiniz, ancak tasarım, uygulama ve bakım için o kadar fazla çalışma 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 sunmak istediğiniz sürümlerin büyük farklılıklar gösterdiği durumlarda iyi bir fikir olabilir. Bunun dışında, duyarlı web tasarımı son derece makul bir yaklaşımdır.

Olası bir çözüm

Burada bir uzlaşma vardır: Cihazları kategoriler halinde sınıflandırın ve her bir kategori için mümkün olan en iyi deneyimi tasarlayın. Hangi kategorileri seçeceğiniz, ürüne ve hedef kullanıcıya bağlıdır. Aşağıda, günümüzde kullanılan web özellikli, popüler cihazlara ait bir örnek sınıflandırma verilmiştir.

  1. küçük ekranlar + dokunma (çoğunlukla telefonlar)
  2. büyük ekranlar + dokunma (ç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 yazılırken bu çok mantıklı olan bir dökümdür. Yukarıdaki listede bulunmayan mobil cihazlar, dokunmatik ekranı olmayan mobil cihazlarıdır (ör. özellikli telefonlar, bazı özel e-kitap okuyucular). Ancak, bu özelliklerin çoğunda klavyeyle gezinme veya ekran okuyucu yazılımı yüklüdür. Bu yazılımlar, sitenizi erişilebilirliği göz önünde bulundurarak oluşturuyorsanız düzgün çalışacaktır.

Form faktörüne özel web uygulaması örnekleri

Farklı form faktörleri için tamamen farklı sürümler sunan birçok web mülkü örneği vardır. Bunu Facebook'ta olduğu gibi Google Arama'da da yapıyor. Hem performans (öğe getirme, sayfa oluşturma) hem de daha genel kullanıcı deneyimi, bu konuda dikkat edilmesi gereken noktalar arasındadır.

Yerel uygulama dünyasında birçok geliştirici, deneyimlerini bir cihaz sınıfına uyarlamayı tercih eder. Örneğin iPad için Flipboard, iPhone'daki Flipboard'dan çok farklı bir kullanıcı arayüzüne sahiptir. Tablet sürümü, iki elle kullanım ve yatay çevirme için optimize edilmiştir. Telefon sürümü ise tek elle etkileşim ve dikey çevirme için tasarlanmıştır. Diğer birçok iOS uygulaması da aşağıda belirtilen Things (Yapılacaklar listesi) ve Showyou (sosyal video) gibi önemli ölçüde farklı telefon ve tablet sürümleri sağlar:

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

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

Sunucuda, kullandığımız cihazla ilgili çok daha sınırlı bilgiye sahibiz. Muhtemelen kullanabileceğiniz en yararlı ipucu, her istekte User-Agent başlığı üzerinden sağlanan kullanıcı aracısı dizesidir. Bu nedenle, aynı UA algılama yaklaşımı burada da işe yarar. Hatta DeviceAtlas ve WURFL projeleri bunu zaten yapar (ve cihaz hakkında birçok ek bilgi sağlar).

Ne yazık ki bunların her birinin kendine özgü zorlukları var. WURFL oldukça büyük bir dosyadır ve 20 MB'lık XML içerir. Bu durum, her bir istek için sunucu tarafında önemli miktarda ek yüke neden olabilir. XML'yi performans nedeniyle bölen projeler vardır. DeviceAtlas açık kaynak değildir ve kullanmak için ücretli bir lisans gerektirir.

Mobil Tarayıcıları Algılama projesi gibi daha basit ve ücretsiz alternatifler de vardır. Elbette dezavantajı, cihaz algılamanın kaçınılmaz olarak daha az kapsamlı olmasıdır. Ayrıca, yalnızca mobil ve mobil olmayan cihazları ayırt eder ve yalnızca anlık ince ayarlar aracılığıyla sınırlı tablet desteği sağlar.

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

Özellik algılama özelliğini kullanarak kullanıcının tarayıcısı ve cihazı hakkında çok şey öğrenebiliriz. Belirlememiz gereken esas unsur, cihazın dokunma özelliğine sahip olup olmadığı ve cihazın büyük mü yoksa küçük bir ekran mı olduğudur.

Küçük ve büyük dokunmatik cihazları ayırt etmek için çizgiyi bir yere çizmemiz gerekir. 5 inç Galaxy Note gibi uç kılıflara ne dersin? Aşağıdaki grafikte, popüler Android ve iOS cihazlar yer paylaşımlı olarak (karşılık gelen ekran çözünürlükleriyle) gösterilmektedir. Yıldız işareti, cihazın iki kat yoğunlukta geldiğini veya gelebileceğini belirtir. Piksel yoğunluğu iki kat artırılsa da CSS aynı boyutları raporlamaya devam eder.

CSS'deki pikseller hızlıca ele alınır: Mobil web'deki CSS pikselleri, ekran pikselleriyle aynı değildir. iOS retina cihazları, piksel yoğunluğunu iki katına çıkarma uygulamasını (ör. iPhone 3GS/4, iPad 2/3) kullanıma sunmuştur. Retina Mobil Safari UA'ları, web'i bozmamak için aynı cihaz genişliğini bildirmeye devam eder. Diğer cihazlarda (ör. daha yüksek çözünürlüklü ekranlara sahip olduklarında aynı cihaz genişliğinde olup olmadıklarını görebilirler.

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

Ancak bu kararı karmaşık hale getirmek için hem dikey hem de yatay modları dikkate almamız gerekiyor. Sayfayı farklı şekilde oluşturmak isteyebiliriz, ancak cihazın yönünü her değiştirdiğimizde sayfayı yeniden yüklemek veya ek komut dosyaları yüklemek istemiyoruz.

Aşağıdaki şemada kareler, dikey ve yatay dış çizgilerin yerleştirilmesinin (ve karenin tamamlanmasının) sonucunda her bir 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 ayarladığınızda iPhone, Galaxy Nexus'u "tablet" olarak, iPad, Galaxy Tab'i ise "tablet" olarak sınıflandırırız. Androjen Galaxy Note bu örnekte "telefon" olarak sınıflandırılır ve telefon düzenini alır.

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 pratik örneğini inceleyin.

Buradaki alternatif yaklaşım, cihaz türünü tespit etmek için UA yoklama yöntemini kullanmaktır. Temel olarak bir bulgular grubu oluşturur ve bunları kullanıcınızın navigator.userAgent metriğiyle eşleştirirsiniz. Sözde kod şuna benzer:

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

UA algılama yaklaşımının uygulamadaki bir örneğini görün.

İstemci tarafı yükleme hakkında not

Sunucunuzda UA algılama işlemi yapıyorsanız yeni bir istek aldığınızda hangi CSS, JavaScript ve DOM'un sunulacağına karar verebilirsiniz. Ancak istemci tarafı 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 kullanmak isteyebilirsiniz. Ne yazık ki bu yaklaşım, özellikle mobil cihazlarda yavaş olabilen bir yönlendirme içeriyor.

İkinci yaklaşımın uygulanması oldukça 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> özelleştirme gibi işlemleri yapamayabilirsiniz. Ayrıca, yönlendirme olmadığından, sunulan orijinal HTML'de kalırsınız. Elbette bunu JavaScript ile değiştirebilirsiniz, ancak uygulamanıza bağlı olarak bu yavaş ve/veya yetersiz olabilir.

İstemci mi yoksa sunucuya mı karar verme

Yaklaşımlar arasındaki dengeler şu şekildedir:

Pro istemcisi:

  • UA yerine ekran boyutları/özellikleri temel alındığından geleceğe daha fazla uyum sağla.
  • UA listesini sürekli güncellemeniz gerekmez.

Pro sunucusu:

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

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

device.js ile tanışın

Device.js, sunucu tarafı özel yapılandırmaya gerek kalmadan anlamsal, medya sorgusuna dayalı cihaz algılaması yapmak için bir başlangıç noktasıdır. Böylece, kullanıcı aracısı dizesini ayrıştırmak için gereken zamandan ve emekten tasarruf edersiniz.

Buradaki fikir, sitenizin hangi sürümlerini sağlamak istediğinizi belirten <head> sayfanızın üst kısmında arama motoru dostu işaretleme (link rel=alternate) sağlamanızdır.

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

Ardından, sunucu tarafı UA algılaması yapıp sürüm yönlendirmesini kendiniz yapabilir 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ına ve istemci tarafı yönlendirme için device.js kullanan sahte bir uygulamaya bakın.

Öneri: Form faktörüne özel görünümlere sahip MVC

Şimdiye kadar büyük olasılıkla sana her cihaz türü için birer tane olmak üzere tamamen ayrı üç uygulama oluşturmanızı söylediğimi düşünüyorsunuz. Hayır Önemli olan kod paylaşımıdır.

Omurga, Kız gibi MVC benzeri bir çerçeve kullandığınızı umuyoruz. Bu konuda bilgi sahibi değilseniz MVC ile ilgili kaynaklardan bazılarını ve JavaScript'teki MVC'yi kullanarak başlayın.

Cihazlar arası hikaye, mevcut MVC çerçevenize mükemmel uyum sağlar. Görünümlerinizi kolayca ayrı dosyalara taşıyabilirsiniz. Böylece her cihaz türü için özel bir görünüm oluşturabilirsiniz. Daha sonra, aynı kodu görünüm katmanı hariç tüm cihazlara sunabilirsiniz.

Cihazlar arası MVC.
Cihazlar arası MVC.

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

modeller/ (paylaşılan modeller) item.js item-collection.js

denetleyiciler/ (paylaşılan denetleyiciler) item-controller.js

sürümler/ (cihaza özel öğeler) tablet/ masaüstü/ telefon/ (telefona özel kod) style.css index.html görünümler/ item.js item-list.js

Bu tür bir yapı, her cihaz için özel HTML, CSS ve JavaScript'e sahip olduğunuzdan, her bir sürümün hangi öğeleri yükleneceğini tam olarak kontrol edebilmenizi sağlar. Bu çok güçlü bir yöntemdir ve uyarlanabilir resimler gibi püf noktalarına dayanmadan, cihazlar arası web için geliştirmenin en düşük ve en iyi performansı göstermesini sağlayabilir.

Sık kullandığınız derleme aracını çalıştırdıktan sonra, tüm JavaScript ve CSS'nizi daha hızlı yükleme için tekli dosyalara birleştirip küçültürsünüz. Üretim HTML'niz aşağıdaki gibi görünür (telefon için, device.js kullanarak):

<!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 firma önekiyle birlikte uygulanır) ancak device.js tarafından doğru şekilde (Modernizr.touch sayesinde) işlendiğini unutmayın.

Sürümü geçersiz kılma

Cihaz algılama bazen hatalı olabilir ve bazı durumlarda kullanıcı telefonundaki tablet düzenine bakmayı tercih edebilir (belki de Galaxy Note kullanıyor olabilir). Bu nedenle, manuel olarak geçersiz kılmak istediklerinde kullanıcılarınıza sitenizin hangi sürümünü kullanacakları konusunda seçenek sunmanız önemlidir.

Her zamanki yaklaşım, mobil sürümünüzden masaüstü sürümüne bağlantı vermektir. Bu, uygulanması yeterince kolaydır, ancak device.js, bu işlevi device GET parametresiyle destekler.

Sonuçlandırılıyor

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

  1. Desteklenecek cihaz sınıfı grubu ve cihazları sınıflar halinde sınıflandırmak için kullanılacak kriterler seçin.
  2. MVC uygulamanızı, endişeleri güçlü bir şekilde ayırarak ve görünümleri kod tabanının geri kalanından bölerek oluşturun.
  3. İstemci tarafı cihaz sınıfı algılaması yapmak için device.js dosyasını kullanın.
  4. Hazır olduğunuzda komut dosyanızı ve stil sayfalarınızı her cihaz sınıfından birinde paketleyin.
  5. İstemci tarafı yönlendirme performansı sorunsa device.js'den ayrılıp sunucu tarafı UA algılamaya geçiş yapın.