HTML5 sitenizi mobil hale getirme

Eric Bidelman

Giriş

Mobil web için geliştirme yapmak bu günlerde en çok tartışılan konulardan biridir. Bu yıl ilk defa, akıllı telefonlar, PC'leri sattı. Giderek daha fazla kullanıcı web'de gezinmek için mobil cihaz kullanıyor. Bu da bunun, geliştiricilerin sitelerini mobil tarayıcılar için optimize etmesi için kritik bir öneme sahip olduğu anlamına geliyor.

"Mobil" savaş alanı, çok sayıda geliştirici için hâlâ keşfedilmeyi bekleyen bir alan. Çoğu kişi, mobil kullanıcıları tamamen ihmal eden eski sitelere sahiptir. Bunun yerine, site öncelikli olarak masaüstüne göz atmak için tasarlanmıştır ve mobil tarayıcılarda düşüşü kötüdür. Bu site (html5rocks.com) da istisna değildir. Lansmanda, sitenin mobil sürümü üzerine çok az çaba sarf ettik.

Mobil uyumlu bir html5rocks.com oluşturma

Alıştırma olarak, html5rocks (mevcut bir HTML5 sitesi) alıp bunu mobil uyumlu bir sürümle genişletmenin ilginç olacağını düşündüm. Asıl endişem, akıllı telefonları hedeflemek için gereken minimum iş miktarıydı. Çalışmamın amacı tamamen yeni bir mobil site oluşturmak ve iki kod tabanı sürdürmek değildi. Bu süreç sonsuza kadar sürer ve zaman kaybına yol açardı. Sitenin yapısını (işaretleme) önceden tanımlamıştık. Bir görünüm ve hissettik (CSS). Temel işlev (JS) buradaydı. Önemli nokta, birçok sitenin aynı gemide olması.

Bu makalede, Android ve iOS cihazlar için optimize edilmiş HTML5rocks'ın mobil sürümünü nasıl oluşturduğumuz ele alınmaktadır. Farkı görmek için html5rocks.com'u bu işletim sistemlerinden birini destekleyen bir cihaza yüklemeniz yeterlidir. m.html5rocks.com veya bu tür diğer aldatıcı içeriklere yapılan yönlendirmeler yoktur. HTML5rocks'ı olduğu gibi elde edersiniz... Üstelik, mobil cihazlarda iyi görünen ve iyi çalışan bir şeye ek olarak.

Masaüstü html5rocks.com Mobil html5rocks.com
Masaüstünde (sol) ve mobilde (sağ) html5rocks.com

CSS Medya Sorguları

HTML4 ve CSS2, bir süredir medyaya bağlı stil sayfalarını destekliyor. Örneğin:

<link rel="stylesheet" media="print" href="printer.css">

yazdırma cihazlarını hedefler ve yazdırıldığında sayfa içeriği için özel stil sağlar. CSS3, medya türleri fikrini bir adım ileriye taşır ve medya sorgularıyla işlevlerini geliştirir. Medya sorguları, stil sayfalarının daha hassas bir şekilde etiketlenmesine olanak tanıyarak medya türlerinin kullanışlılığını artırır. Bu, içeriğin kendisinin değiştirilmesine gerek kalmadan belirli bir dizi çıkış cihazına göre özelleştirilmesine olanak tanır. Değişiklik gerektiren mevcut bir düzen için kulağa harika geliyor.

Ekran genişliği, cihaz genişliği, yön vb. hedeflemek için harici stil sayfalarınızın media özelliğinde medya sorgularını kullanabilirsiniz. Tam liste için W3C medya sorgusu spesifikasyonuna bakın.

Ekran boyutlarını hedefleme

Aşağıdaki örnekte phone.css, tarayıcının "avuç içi" olarak kabul ettiği veya ekran genişliği 320 pikselden küçük olan cihazlar için geçerlidir.

 <link rel='stylesheet'
  media='handheld, only screen and (max-device-width: 320px)' href='phone.css'>

Medya sorgularının önüne "only" anahtar kelimesi eklemek, CSS3 uyumlu olmayan tarayıcıların kuralı yoksaymasına neden olur.

Aşağıdakiler 641 piksel ile 800 piksel arasındaki ekran boyutlarını hedefler:

 <link rel='stylesheet'
  media='only screen and (min-width: 641px) and (max-width: 800px)' href='ipad.css'>

Medya sorguları, satır içi <style> etiketleri içinde de görünebilir. Aşağıdakiler dikey yöndeki all medya türünü hedeflemektedir:

 <style>
  @media only all and (orientation: portrait) { ... }
 </style>

media="handheld"

Bir dakika durup media="handheld" konusunu konuşmamız gerekiyor. Gerçek şu ki Android ve iOS, media="handheld" uygulamasını yoksayar. İddia, kullanıcıların media="screen"'i hedefleyen stil sayfaları tarafından sağlanan ileri teknoloji içeriği gözden kaçıracağı ve geliştiricilerin daha düşük kaliteli bir media="handheld" sürümünü kullanma olasılıklarının daha düşük olduğu yönündedir. Bu nedenle, "tam web" sloganlarının bir parçası olarak, çoğu modern akıllı telefon tarayıcısı, el tipi stil sayfalarını görmezden gelmektedir.

Bu özelliğin mobil cihazları hedeflemek için kullanılması ideal olurdu, ancak çeşitli tarayıcılar bunu farklı şekillerde uygulamıştır:

  • Bazıları yalnızca el tipi stil sayfasını okur.
  • Bazıları, avuç içi stil sayfası varsa yalnızca el tipi stil sayfasını okur, aksi takdirde varsayılan olarak ekran stil sayfasını kullanır.
  • Bazıları hem avuç içi stil sayfasını hem de ekran stil sayfasını okur.
  • Bazıları yalnızca ekran stil sayfasını okur.

Opera Mini, media="handheld" uygulamasını yoksaymaz. Windows Mobile'ın media="handheld" tanımasını sağlamanın püf noktası, ekran stil sayfasında medya özelliği değerini büyük harfle yazmaktır:

 <!-- media="handheld" trick for Windows Mobile -->
 <link rel="stylesheet" href="screen.css" media="Screen">
 <link rel="stylesheet" href="mobile.css" media="handheld">

HTML5rocks medya sorgularını nasıl kullanır?

Medya sorguları, ağırlıklı olarak mobil HTML5rocks'ta kullanılır. Django şablon işaretlememizde önemli değişiklikler yapmak zorunda kalmadan düzeni değiştirmemizi sağladılar. Gerçek bir cankurtaran oldular. Ayrıca, farklı tarayıcılardan destekliyorlar da oldukça iyi.

Her sayfanın <head> bölümünde aşağıdaki stil sayfalarını görürsünüz:

 <link rel='stylesheet'
  media='all' href='/static/css/base.min.css' />
 <link rel='stylesheet'
  media='only screen and (max-width: 800px)' href='/static/css/mobile.min.css' />

base.css her zaman html5rocks.com'un ana görünümünü ve tarzını tanımlamıştı, ancak şimdi 800 pikselin altındaki ekran genişlikleri için yeni stiller (mobile.css) uyguluyoruz. Medya sorgusu akıllı telefonları (~320 piksel) ve iPad'i (~768 piksel) kapsar. Bunun sonucunda, mobil cihazlarda daha iyi görünmesi için base.css ürünündeki stilleri aşamalı olarak geçersiz kılıyoruz (yalnızca gerektiğinde).

mobile.css uygulamasının uyguladığı stil değişikliklerinden bazıları:

  • Site genelindeki ekstra boşlukları/dolguyu azaltır. Küçük ekranlar, alanın paha biçilmez olduğu anlamına gelir!
  • :hover eyaleti kaldırır. Dokunmatik cihazlarda hiç görülmezler.
  • Düzeni tek sütunlu olacak şekilde ayarlar. Bu konuda daha sonra bilgi vereceğiz.
  • Sitenin ana kapsayıcı div öğesinin çevresindeki box-shadow öğesini kaldırır. Büyük kutu gölgeleri, sayfa performansını düşürür.
  • Ana sayfadaki her bölümün sıralamasını değiştirmek için box-ordinal-group CSS esnek kutu modeli kullanıldı. "LEARN BY MAJOR HTML5 FEATURE GROUP" ifadesinin ana sayfada "EĞİTİCİLER" bölümünden önce, mobil sürümde ise bu bölümden sonra geldiğini fark edeceksiniz. Bu sıralama mobil cihazlar için daha anlamlıydı ve işaretleme değişiklikleri gerektirmiyordu. CSS flexbox FTW!
  • opacity değişikliği kaldırır. Alfa değerlerinin değiştirilmesi, mobil cihazlarda performansın artmasını sağlar.

Mobil meta etiketler

Mobil WebKit, kullanıcılara belirli cihazlarda daha iyi bir göz atma deneyimi sağlayan birkaç özelliği destekler.

Görüntü alanı ayarları

İlk meta ayar (ve en sık kullanacağınız) görüntü alanı özelliğidir. Bir görüntü alanı ayarlamak, tarayıcıya içeriğin cihaz ekranına nasıl sığması gerektiğini söyler ve tarayıcıya, sitenin mobil cihazlar için optimize edildiğini bildirir. Örneğin:

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

tarayıcıya görüntü alanını, başlangıç ölçeğiyle cihazın genişliğine ayarlamasını belirtir. Bu örnekte, web siteleri için istenebilecek, ancak web uygulaması için cazip olmayacak olan yakınlaştırma da yapılabilir. user-scalable=no ile yakınlaştırmayı engelleyebilir veya ölçeklendirmeyi belirli bir düzeye sınırlayabiliriz:

 <meta name=viewport
  content="width=device-width, initial-scale=1.0, minimum-scale=0.5 maximum-scale=1.0">

Android, geliştiricilerin sitenin hangi ekran çözünürlüğü için geliştirildiğini belirtmesine olanak tanıyarak görüntü alanı meta etiketini genişletir:

 <meta name="viewport" content="target-densitydpi=device-dpi">

target-densitydpi için olası değerler device-dpi, high-dpi, medium-dpi, low-dpi şeklindedir.

Web sayfanızı farklı ekran yoğunlukları için değiştirmek isterseniz JavaScript'te -webkit-device-pixel-ratio CSS medya sorgusunu ve/veya window.devicePixelRatio özelliğini kullanın, ardından target-densitydpi meta özelliğini device-dpi olarak ayarlayın. Bu işlem, Android'in web sayfanızda ölçeklendirme yapmasını durdurur ve CSS ile JavaScript aracılığıyla her yoğunluk için gerekli ayarlamaları yapmanıza olanak tanır.

Cihaz çözünürlüklerini hedefleme hakkında daha fazla bilgi için Android'in Web Görünümü dokümanlarına bakın.

Tam ekran modunda göz atma

iOS-sfic olan iki meta değer daha vardır. apple-mobile-web-app-capable ve apple-mobile-web-app-status-bar-style, sayfa içeriğini uygulama benzeri tam ekran modunda oluşturur ve durum çubuğunu yarı şeffaf yapar:

 <meta name="apple-mobile-web-app-capable" content="yes">
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">

Kullanılabilir tüm meta seçenekler hakkında daha fazla bilgi için Safari referans dokümanlarına bakın.

Ana ekran simgeleri

iOS ve Android cihazlar da bağlantılar için rel="apple-touch-icon" (iOS) ve rel="apple-touch-icon-precomposed" (Android) öğelerini kabul eder. Bunlar, kullanıcı sitenize yer işareti koyduğunda ana ekranında uygulama benzeri göz alıcı bir simge oluşturur:

 <link rel="apple-touch-icon"
      href="/static/images/identity/HTML5_Badge_64.png" />
 <link rel="apple-touch-icon-precomposed"
      href="/static/images/identity/HTML5_Badge_64.png" />

HTML5rocks mobil meta etiketleri nasıl kullanır?

Her şeyi bir araya getirirsek html5rocks'ın <head> bölümünden bir snippet'i burada görebilirsiniz:

 <head>
  ...
   <meta name="viewport"
        content="width=device-width, initial-scale=1.0, minimum-scale=1.0" />

   <link rel="apple-touch-icon"
        href="/static/images/identity/HTML5_Badge_64.png" />
   <link rel="apple-touch-icon-precomposed"
        href="/static/images/identity/HTML5_Badge_64.png" />
  ...
 </head>

Dikey düzen

Küçük ekranlarda, dikey olarak kaydırma yapmak yatay yönde ilerlemekten çok daha kolaydır. İçeriği tek sütunda tutmak için mobil cihazlarda dikey düzen tercih edilir. HTML5rocks için böyle bir düzen oluşturmak üzere CSS3 medya sorgularını kullandık. Yine, işaretlemeyi değiştirmeden yapalım.

Eğiticiler dizini. Eğitim. HTML5 Özelliği sayfası. Yazar profilleri sayfası.
Site genelinde tek sütunlu dikey düzen.

Mobil optimizasyonlar

Yaptığımız optimizasyonların çoğu, daha önce yapılması gereken şeylerdi. Bunlar; ağ isteklerinin sayısını azaltma, JS/CSS sıkıştırma, gzip oluşturma (App Engine'de ücretsiz olarak sunulur) ve DOM manipülasyonlarını en aza indirme gibi işlemlerdir. Bu teknikler yaygın en iyi uygulamalardır, ancak bir siteyi aceleye getirmek için zaman zaman göz ardı edilir.

Adres çubuğunu otomatik gizle

Mobil tarayıcılar, masaüstü muadillerinin ekran alanından yoksundur. İşleri kötüleştirmek için, farklı platformlarda bazen ekranın üst kısmında büyük bir "adres çubuğu" olur (sayfanın yüklenmesi bittikten sonra bile).

Bununla başa çıkmanın kolay bir yolu, sayfayı JavaScript kullanarak kaydırmaktır. Bunu bir piksel kullanarak yapmak bile can sıkıcı adres çubuğunun çözülmesini sağlar. HTML5rocks'ta adres çubuğunu zorunlu olarak gizlemek için window nesnesine bir onload etkinlik işleyicisi ekledim ve sayfayı bir piksel dikey olarak kaydırdım:

Adres çubuğu.
Çirkin adres çubuğu ekrandaki alanı kaplar.
  // Hides mobile browser's address bar when page is done loading.
  window.addEventListener('load', function(e) {
    setTimeout(function() { window.scrollTo(0, 1); }, 1);
  }, false);

Masaüstünde gerekli olmadığı için bu işleyiciyi de is_mobile şablon değişkenimiz olarak sarmaladık.

Ağ isteklerini azaltın, bant genişliğinden tasarruf edin

HTTP isteklerinin sayısını azaltmanın performansı önemli ölçüde iyileştirebileceği bilinen bir gerçektir. Mobil cihazlar, tarayıcının yapabileceği eşzamanlı bağlantı sayısını daha da sınırlandırır. Böylece mobil siteler, bu gereksiz isteklerin azaltılmasından daha da fazla yararlanır. Dahası, telefonlarda bant genişliği genellikle sınırlı olduğundan her baytın kırpılması kritik öneme sahiptir. Kullanıcılara para harcıyor olabilirsiniz.

Ağ isteklerini en aza indirmek ve html5rocks'ta bant genişliğini azaltmak için benimsediğimiz yaklaşımlardan bazılarını aşağıda görebilirsiniz:

  • iframe'leri kaldırın - iframe'ler yavaştır! Gecikme süresinin büyük bir kısmı eğitim sayfalarındaki üçüncü taraf paylaşım widget'larından (Buzz, Google Friend Connect, Twitter, Facebook) kaynaklandı. Bu API'ler <script> etiketleri aracılığıyla eklenir ve sayfanın hızını azaltan iframe'ler oluşturur. Widget'lar mobil cihazlar için kaldırıldı.

  • display:none - Belirli durumlarda, mobil profile uymadığı takdirde işaretlemeyi gizledik. Ana sayfanın üst kısmındaki dört yuvarlak kutu buna iyi bir örnektir:

Ana sayfada kutu düğmeleri.
Ana sayfada kutu düğmeleri.

Bunlar mobil sitede yer almamaktadır. Kapsayıcı display:none ile gizlenmiş olsa da tarayıcının her simge için istek göndermeye devam ettiğini unutmamak önemlidir. Bu nedenle, bu düğmeleri gizlemek tek başına yeterli olmuyordu. Bu sadece bant genişliğinin boşa harcanmasıyla sonuçlanabilir, aynı zamanda kullanıcılar boşa yapılan bant genişliğinin meyvelerini bile göremez! Çözüm, HTML bölümlerini koşullu olarak hariç tutmak için Django şablonumuzda bir "is_mobile" boole değeri oluşturmaktı. Kullanıcı, siteyi akıllı bir cihazda görüntülerken düğmeler dışarıda bırakılır.

  • Uygulama Önbelleği: Bu bize çevrimdışı destek sağlamakla kalmaz, aynı zamanda daha hızlı bir başlatma sağlar.

  • CSS/JS sıkıştırma: Özellikle hem CSS hem de JS'yi işlediğinden Closure derleyici yerine YUI sıkıştırıcısını kullanıyoruz. Karşılaştığımız sorunlardan biri, satır içi medya sorgularının (stil sayfasında görünen medya sorguları) YUI kompresör 2.4.2'de çubuklanmasıydı (bu soruna bakın). YUI Sıkıştırıcı 2.4.4+ kullanılması sorunu çözdü.

  • Mümkün olduğunda CSS resim sprite görseller kullanıldı.

  • Resim sıkıştırma için pngcrush kullanıldı.

  • Küçük resimler için dataURI'lar kullanıldı. Base64 kodlaması, resme yaklaşık%30+ boyut ekler ancak ağ isteğini kaydeder.

  • Google Özel Arama'yı google.load() ile dinamik olarak yüklemek yerine tek bir komut dosyası etiketi kullanarak otomatik olarak yükledi. Kullanıcılar ekstra istekte bulunur.

<script src="//www.google.com/jsapi?autoload={"modules":[{"name":"search","version":"1"}]}"> </script>
  • Kodlarımız, hiç kullanılmamış olsalar bile kolayca yazıcımız ve Modernizr her sayfaya eklenmişti. Modernizr çok iyi, ama her yüklemede bir sürü test yapıyor. Bu testlerden bazıları DOM'da maliyetli değişiklikler yapar ve sayfa yüklemesini yavaşlatır. Şimdi bu kitaplıkları sadece gerçekten ihtiyaç duyuldukları sayfalara ekliyoruz. -2 istek :)

Ek performans ince ayarları:

  • Tüm JS'ler sayfanın alt kısmına taşındı (mümkünse).
  • Satır içi <style> etiketleri kaldırıldı.
  • Önbelleğe alınan DOM aramaları ve küçültülmüş DOM değişiklikleri: DOM'a her dokunduğunuzda tarayıcı bir yeniden düzenleme gerçekleştirir. Yeniden düzenleme, mobil cihazlarda daha da maliyetli hale gelir.
  • Kötüye kullanılan istemci tarafı kodu sunucuya aktarıldı. Özellikle, geçerli sayfanın gezinme stilini ayarlama kontrolü: js var lis = document.querySelectorAll('header nav li'); var i = lis.length; while (i--) { var a = lis[i].querySelector('a'); var section = a.getAttribute("data-section"); if (new RegExp(section).test(document.location.href)) { a.className = 'current'; } }
  • Sabit genişliğe sahip öğeler, değişken width:100% veya width:auto ile değiştirildi.

Uygulama Önbelleği

html5rocks'ın mobil sürümü, ilk yükü hızlandırmak ve kullanıcıların içeriği çevrimdışı olarak okumasına olanak tanımak için Uygulama Önbelleği'ni kullanır.

AppCache'i sitenize uygularken, manifest dosyanızı önbelleğe almamanız çok önemlidir (manifest dosyasının kendisinde açıkça veya dolaylı olarak yoğun önbellek kontrol başlıklarıyla). Manifest'iniz tarayıcı tarafından önbelleğe alınırsa hata ayıklamak tam bir kabus olur. iOS ve Android bu dosyayı önbelleğe alma konusunda oldukça başarılı olsa da önbelleğin temizlenmesi için masaüstü tarayıcılar gibi kullanışlı bir yöntem sunmamaktadır.

Sitemiz için söz konusu önbelleğe alma işlemini önlemek için öncelikle App Engine'i, manifest dosyalarını hiçbir zaman önbelleğe almayacak şekilde ayarladık:

- url: /(.*\.(appcache|manifest))
  static_files: \1
  mime_type: text/cache-manifest
  upload: (.*\.(appcache|manifest))
  expiration: "0s"

İkinci olarak, yeni bir manifestin indirilmesi tamamlandığında kullanıcıyı bilgilendirmek için JS API'yi kullandık. Kullanıcıdan sayfayı yenilemesi istenir:

window.applicationCache.addEventListener('updateready', function(e) {
  if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
    window.applicationCache.swapCache();
    if (confirm('A new version of this site is available. Load it?')) {
      window.location.reload();
    }
  }
}, false);

Ağ trafiğinden tasarruf etmek için manifest dosyanızı basit tutun. Yani sitenizdeki her sayfayı tek tek belirtmeyin. Önemli resimleri, CSS ve JavaScript dosyalarını listeleyin. Yapmak isteyeceğiniz son şey, mobil tarayıcıyı her appcache güncellemesinde çok sayıda öğe indirmeye zorlamaktır. Bunun yerine, kullanıcı ziyaret ettiğinde tarayıcının dolaylı olarak bir HTML sayfasını önbelleğe alacağını (ve bir <html manifest="..."> özelliği içerdiğini) unutmayın.