Kueri media memang bagus, tetapi…
Kueri media sangat berguna, anugerah bagi developer situs yang ingin melakukan penyesuaian kecil pada stylesheet mereka untuk memberikan pengalaman yang lebih baik bagi pengguna di perangkat dengan berbagai ukuran. Pada dasarnya, kueri media memungkinkan Anda menyesuaikan CSS situs Anda, bergantung pada ukuran layar. Sebelum Anda mempelajari artikel ini, pelajari lebih lanjut desain responsif dan lihat beberapa contoh penggunaan kueri media yang bagus di sini: mediaqueri.es.
Seperti yang ditunjukkan Brad Frost dalam artikel sebelumnya, mengubah tampilan hanyalah salah satu dari banyak hal yang perlu dipertimbangkan saat membangun untuk web seluler. Jika satu-satunya hal yang Anda lakukan saat membangun situs seluler adalah menyesuaikan tata letak dengan kueri media, maka kita akan berada dalam situasi berikut:
- Semua perangkat mendapatkan JavaScript, CSS, dan aset (gambar, video) yang sama, sehingga waktu pemuatan lebih lama dari yang diperlukan.
- Semua perangkat mendapatkan DOM awal yang sama, yang berpotensi memaksa developer menulis CSS yang terlalu rumit.
- Kurang fleksibel untuk menentukan interaksi kustom yang disesuaikan dengan setiap perangkat.
Aplikasi web memerlukan lebih dari kueri media
Jangan salah paham. Saya tidak membenci desain responsif melalui kueri media, dan tentu saja berpikir bahwa desain responsif memiliki tempat di dunia. Selain itu, beberapa masalah yang disebutkan di atas dapat diselesaikan dengan pendekatan seperti gambar responsif, pemuatan skrip dinamis, dll. Namun, pada titik tertentu, Anda mungkin melakukan terlalu banyak penyesuaian inkremental, dan mungkin lebih baik menyajikan versi yang berbeda.
Seiring meningkatnya kompleksitas UI yang Anda buat, dan Anda cenderung menggunakan aplikasi web satu halaman, Anda akan ingin melakukan lebih banyak hal untuk menyesuaikan UI untuk setiap jenis perangkat. Artikel ini akan mengajarkan cara melakukan penyesuaian ini dengan upaya minimal. Pendekatan umumnya melibatkan pengklasifikasian perangkat pengunjung Anda ke dalam kelas perangkat yang tepat, dan menyajikan versi yang sesuai ke perangkat tersebut, sekaligus memaksimalkan penggunaan kembali kode antar-versi.
Kelas perangkat apa yang Anda targetkan?
Ada banyak perangkat yang terhubung ke internet, dan hampir semuanya memiliki browser. Kompleksitasnya terletak pada keragaman perangkat: laptop Mac, workstation Windows, iPhone, iPad, ponsel Android dengan input sentuh, roda scroll, keyboard, input suara, perangkat dengan sensitivitas tekanan, smartwatch, pemanggang roti dan kulkas, serta banyak lagi. Beberapa perangkat ini ada di mana-mana, sementara yang lain sangat langka.
Untuk menciptakan pengalaman pengguna yang baik, Anda harus mengetahui siapa pengguna Anda dan perangkat yang mereka gunakan. Jika Anda membuat antarmuka pengguna untuk pengguna desktop dengan mouse dan keyboard, lalu memberikannya kepada pengguna smartphone, antarmuka Anda akan menimbulkan frustrasi karena didesain untuk ukuran layar dan modalitas input yang berbeda.
Ada dua ujung ekstrem dalam spektrum pendekatan:
Buat satu versi yang berfungsi di semua perangkat. UX akan terpengaruh sebagai akibatnya, karena perangkat yang berbeda memiliki pertimbangan desain yang berbeda.
Bangun versi untuk setiap perangkat yang ingin Anda dukung. Hal ini akan memakan waktu selamanya, karena Anda akan membuat terlalu banyak versi aplikasi. Selain itu, saat smartphone baru berikutnya tiba (yang terjadi kira-kira setiap minggu), Anda akan dipaksa untuk membuat versi lain.
Ada pertukaran mendasar di sini: semakin banyak kategori perangkat yang Anda miliki, semakin baik pengalaman pengguna yang dapat Anda berikan, tetapi semakin banyak pekerjaan yang diperlukan untuk mendesain, menerapkan, dan memelihara.
Membuat versi terpisah untuk setiap class perangkat yang Anda putuskan mungkin merupakan ide yang baik untuk alasan performa atau jika versi yang ingin Anda sajikan ke class perangkat yang berbeda sangat bervariasi. Jika tidak, desain web responsif adalah pendekatan yang sangat wajar.
Solusi potensial
Berikut komprominya: mengklasifikasikan perangkat ke dalam kategori, dan mendesain pengalaman terbaik untuk setiap kategori. Kategori yang Anda pilih bergantung pada produk dan target pengguna Anda. Berikut adalah contoh klasifikasi yang mencakup perangkat populer yang kompatibel dengan web yang ada saat ini.
- layar kecil + sentuh (sebagian besar ponsel)
- layar besar + sentuh (sebagian besar tablet)
- layar besar + keyboard/mouse (sebagian besar desktop/laptop)
Ini hanyalah salah satu dari banyak kemungkinan perincian, tetapi salah satu yang sangat masuk akal pada saat penulisan. Daftar di atas tidak mencantumkan perangkat seluler tanpa layar sentuh (misalnya, ponsel fitur, beberapa e-reader khusus). Namun, sebagian besar situs ini telah menginstal software pembaca layar atau navigasi keyboard, yang akan berfungsi dengan baik jika Anda membangun situs dengan mempertimbangkan aksesibilitas.
Contoh aplikasi web khusus faktor bentuk
Ada banyak contoh properti web yang menayangkan versi yang sama sekali berbeda untuk berbagai faktor bentuk. Google Penelusuran melakukannya, begitu juga Facebook. Pertimbangan untuk hal ini mencakup performa (mengambil aset, merender halaman) dan pengalaman pengguna yang lebih umum.
Di dunia aplikasi native, banyak developer memilih untuk menyesuaikan pengalaman mereka dengan class perangkat. Misalnya, Flipboard untuk iPad memiliki UI yang sangat berbeda dibandingkan dengan Flipboard di iPhone. Versi tablet dioptimalkan untuk penggunaan dua tangan dan membalik horizontal, sedangkan versi ponsel ditujukan untuk interaksi satu tangan dan membalik vertikal. Banyak aplikasi iOS lainnya juga menyediakan versi ponsel dan tablet yang sangat berbeda, seperti Things (daftar tugas), dan Showyou (video sosial), yang ditampilkan di bawah:
Pendekatan #1: Deteksi sisi server
Di server, kita memiliki pemahaman yang jauh lebih terbatas tentang perangkat yang sedang kita tangani. Petunjuk yang mungkin paling berguna adalah string agen pengguna, yang diberikan melalui header Agen Pengguna pada setiap permintaan. Oleh karena itu, pendekatan sniffing UA yang sama akan berfungsi di sini. Faktanya, project DeviceAtlas dan WURFL sudah melakukannya (dan memberikan banyak informasi tambahan tentang perangkat).
Sayangnya, setiap opsi ini memiliki tantangannya sendiri. WURFL sangat besar, berisi 20 MB XML, yang berpotensi menimbulkan overhead sisi server yang signifikan untuk setiap permintaan. Ada project yang memisahkan XML karena alasan performa. DeviceAtlas bukan open source, dan memerlukan lisensi berbayar untuk digunakan.
Ada juga alternatif gratis yang lebih sederhana, seperti project Detect Mobile Browsers. Tentu saja, kelemahannya adalah deteksi perangkat pasti akan kurang komprehensif. Selain itu, ChromeOS hanya membedakan perangkat seluler dan non-seluler, serta hanya menyediakan dukungan tablet terbatas melalui serangkaian penyesuaian ad-hoc.
Pendekatan #2: Deteksi sisi klien
Kita dapat mempelajari banyak hal tentang browser dan perangkat pengguna dengan menggunakan deteksi fitur. Hal utama yang perlu kita tentukan adalah apakah perangkat memiliki kemampuan sentuh, dan apakah layarnya besar atau kecil.
Kita perlu menarik garis di suatu tempat untuk membedakan perangkat sentuh kecil dan besar. Bagaimana dengan kasus ekstrem seperti Galaxy Note 5 inci? Grafik berikut menunjukkan sejumlah perangkat Android dan iOS populer yang ditumpuk (dengan resolusi layar yang sesuai). Tanda bintang menunjukkan bahwa perangkat memiliki atau dapat memiliki kepadatan ganda. Meskipun kepadatan piksel dapat digandakan, CSS tetap melaporkan ukuran yang sama.
Sedikit penjelasan tentang piksel di CSS: Piksel CSS di web seluler tidak sama dengan piksel layar. Perangkat retina iOS memperkenalkan praktik menggandakan kepadatan piksel (misalnya, iPhone 3GS vs 4, iPad 2 vs 3). UA Mobile Safari retina masih melaporkan lebar perangkat yang sama untuk menghindari kerusakan web. Sebagai perangkat lain (misalnya Android) mendapatkan layar beresolusi lebih tinggi, mereka menggunakan trik lebar perangkat yang sama.
Namun, yang mempersulit keputusan ini adalah pentingnya mempertimbangkan mode potret dan lanskap. Kita tidak ingin memuat ulang halaman atau memuat skrip tambahan setiap kali kita mengubah orientasi perangkat, meskipun kita mungkin ingin merender halaman secara berbeda.
Dalam diagram berikut, persegi mewakili dimensi maksimum setiap perangkat, sebagai hasil dari tumpang-tindih garis potret dan lanskap (serta melengkapi persegi):
Dengan menetapkan nilai minimum ke 650px, kami mengklasifikasikan iPhone, Galaxy Nexus sebagai
sentuhan kecil, dan iPad, Galaxy Tab sebagai "tablet". Galaxy Note androgini dalam kasus ini diklasifikasikan sebagai "ponsel", dan akan mendapatkan tata letak ponsel.
Jadi, strategi yang wajar mungkin terlihat seperti ini:
if (hasTouch) {
if (isSmall) {
device = PHONE;
} else {
device = TABLET;
}
} else {
device = DESKTOP;
}
Lihat contoh minimal pendekatan deteksi fitur yang sedang digunakan.
Pendekatan alternatif di sini adalah menggunakan deteksi UA untuk mendeteksi jenis perangkat. Pada dasarnya, Anda membuat serangkaian heuristik dan mencocokkannya dengan
navigator.userAgent pengguna Anda. Kode semu terlihat seperti ini:
var ua = navigator.userAgent;
for (var re in RULES) {
if (ua.match(re)) {
device = RULES[re];
return;
}
}
Lihat contoh pendekatan deteksi UA yang sedang digunakan.
Catatan tentang pemuatan sisi klien
Jika Anda melakukan deteksi UA di server, Anda dapat memutuskan CSS, JavaScript, dan DOM mana yang akan ditayangkan saat Anda mendapatkan permintaan baru. Namun, jika Anda melakukan deteksi sisi klien, situasinya akan lebih rumit. Anda memiliki beberapa opsi:
- Mengalihkan ke URL khusus jenis perangkat yang berisi versi untuk jenis perangkat ini.
- Memuat aset khusus jenis perangkat secara dinamis.
Pendekatan pertama cukup mudah, memerlukan pengalihan seperti
window.location.href = '/tablet'. Namun, lokasi tersebut kini akan memiliki
informasi jenis perangkat ini yang ditambahkan ke dalamnya, jadi Anda mungkin ingin menggunakan
History API untuk membersihkan URL Anda. Sayangnya, pendekatan ini melibatkan pengalihan, yang dapat berjalan lambat, terutama di perangkat seluler.
Pendekatan kedua jauh lebih rumit untuk diterapkan. Anda memerlukan
mekanisme untuk memuat CSS dan JS secara dinamis, dan (bergantung pada browser), Anda
mungkin tidak dapat melakukan hal-hal seperti menyesuaikan <meta viewport>. Selain itu,
karena tidak ada pengalihan, Anda akan tetap menggunakan HTML asli yang
ditayangkan. Tentu saja, Anda dapat memanipulasinya dengan JavaScript, tetapi hal ini mungkin lambat dan/atau tidak elegan, bergantung pada aplikasi Anda.
Memutuskan klien atau server
Berikut adalah konsekuensi antara pendekatan tersebut:
Klien pro:
- Lebih siap untuk masa depan karena didasarkan pada ukuran/kemampuan layar, bukan UA.
- Tidak perlu terus-menerus memperbarui daftar UA.
Server pro:
- Kontrol penuh atas versi yang akan ditayangkan ke perangkat tertentu.
- Performa yang lebih baik: tidak perlu pengalihan klien atau pemuatan dinamis.
Saya lebih suka memulai dengan device.js dan deteksi sisi klien. Seiring perkembangan aplikasi, jika Anda mendapati pengalihan sisi klien menjadi kerugian performa yang signifikan, Anda dapat dengan mudah menghapus skrip device.js, dan menerapkan deteksi UA di server.
Memperkenalkan device.js
Device.js adalah titik awal untuk melakukan deteksi perangkat berbasis kueri media semantik tanpa memerlukan konfigurasi sisi server khusus, sehingga menghemat waktu dan upaya yang diperlukan untuk melakukan parsing string agen pengguna.
Idenya adalah Anda memberikan markup yang kompatibel dengan mesin telusur (link
rel=alternate) di bagian atas <head> yang menunjukkan versi situs yang ingin Anda berikan.
<link rel="alternate" href="http://foo.com" id="desktop"
media="only screen and (touch-enabled: 0)">
Selanjutnya, Anda dapat melakukan deteksi UA sisi server dan menangani pengalihan versi sendiri, atau menggunakan skrip device.js untuk melakukan pengalihan sisi klien berbasis fitur.
Untuk mengetahui informasi selengkapnya, lihat halaman project device.js, dan juga aplikasi palsu yang menggunakan device.js untuk pengalihan sisi klien.
Rekomendasi: MVC dengan tampilan khusus faktor bentuk
Sekarang, Anda mungkin berpikir bahwa saya menyuruh Anda membuat tiga aplikasi yang benar-benar terpisah, satu untuk setiap jenis perangkat. Tidak! Berbagi kode adalah kuncinya.
Semoga Anda telah menggunakan framework seperti MVC, seperti Backbone, Ember, dll. Jika sudah, Anda pasti memahami prinsip pemisahan tugas, khususnya bahwa UI (lapisan tampilan) harus dipisahkan dari logika (lapisan model). Jika Anda baru menggunakan MVC, mulai dengan beberapa referensi tentang MVC ini, dan MVC di JavaScript.
Artikel lintas perangkat cocok dengan framework MVC yang ada. Anda dapat dengan mudah memindahkan tampilan ke dalam file terpisah, membuat tampilan kustom untuk setiap jenis perangkat. Kemudian, Anda dapat menayangkan kode yang sama ke semua perangkat, kecuali lapisan tampilan.
Project Anda mungkin memiliki struktur berikut (tentu saja, Anda bebas memilih struktur yang paling sesuai dengan aplikasi Anda):
models/ (model bersama) item.js item-collection.js
controllers/ (pengontrol bersama) item-controller.js
versions/ (stuff khusus perangkat) tablet/ desktop/ phone/ (kode khusus ponsel) style.css index.html views/ item.js item-list.js
Struktur semacam ini memungkinkan Anda mengontrol sepenuhnya aset yang dimuat setiap versi, karena Anda memiliki HTML, CSS, dan JavaScript kustom untuk setiap perangkat. Hal ini sangat efektif, dan dapat menghasilkan cara pengembangan yang paling ramping dan berperforma tinggi untuk web lintas perangkat, tanpa mengandalkan trik seperti gambar adaptif.
Setelah menjalankan alat build favorit, Anda akan menggabungkan dan meminifikasi semua JavaScript dan CSS ke dalam satu file agar pemuatan lebih cepat, dengan HTML produksi Anda akan terlihat seperti berikut (untuk ponsel, menggunakan device.js):
<!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>
Perhatikan bahwa kueri media (touch-enabled: 0) tidak standar (hanya diterapkan di Firefox di balik awalan vendor moz), tetapi ditangani dengan benar (berkat Modernizr.touch) oleh device.js.
Penggantian versi
Deteksi perangkat terkadang salah, dan dalam beberapa kasus, pengguna mungkin lebih suka melihat tata letak tablet di ponsel mereka (mungkin mereka menggunakan Galaxy Note), jadi penting untuk memberi pengguna pilihan versi situs yang akan digunakan jika mereka ingin mengganti secara manual.
Pendekatan yang biasa dilakukan adalah menyediakan link ke versi desktop dari
versi seluler Anda. Hal ini cukup mudah diterapkan, tetapi device.js mendukung
fungsi ini dengan parameter GET device.
Mengakhiri
Singkatnya, saat membuat UI halaman tunggal lintas perangkat yang tidak sesuai dengan desain responsif, lakukan hal berikut:
- Pilih sekumpulan class perangkat yang akan didukung, dan kriteria untuk mengklasifikasikan perangkat ke dalam class.
- Bangun aplikasi MVC Anda dengan pemisahan masalah yang kuat, yang memisahkan tampilan dari codebase lainnya.
- Gunakan device.js untuk melakukan deteksi class perangkat sisi klien.
- Setelah siap, kemas skrip dan stylesheet Anda menjadi satu untuk setiap class perangkat.
- Jika performa pengalihan sisi klien menjadi masalah, hentikan penggunaan device.js dan beralihlah ke deteksi UA sisi server.