Sayfa Geçişlerinde Kullanıcı Akışını İyileştirme

Yayınlanan: 2022-03-10
Kısa özet ↬ Bir kullanıcının deneyimi kesintiye uğradığında, ayrılma şansı artar. Bir sayfadan diğerine geçmek, içeriğin olmadığı beyaz bir flaşın gösterilmesi, yüklenmesinin çok uzun sürmesi veya başka bir şekilde kullanıcıyı yeni sayfa açılmadan önce bulunduğu bağlamın dışına çıkarması nedeniyle bu kesintiye neden olur.

Sayfalar arasındaki geçişler, kullanıcının bağlamını koruyarak (hatta geliştirerek), dikkatlerini koruyarak ve görsel süreklilik ve olumlu geri bildirim sağlayarak deneyimi iyileştirebilir. Aynı zamanda, sayfa geçişleri estetik açıdan hoş ve eğlenceli olabilir ve iyi yapıldığında markalaşmayı güçlendirebilir.

Page Transitions

Bu yazıda, adım adım sayfalar arasında bir geçiş oluşturacağız. Ayrıca bu tekniğin artıları ve eksileri ve sınırlarının nasıl zorlanacağı hakkında konuşacağız.

Örnekler

Birçok mobil uygulama, görünümler arasındaki geçişleri iyi bir şekilde kullanır. Google'ın materyal tasarım yönergelerini izleyen aşağıdaki örnekte, animasyonun sayfalar arasındaki hiyerarşik ve uzamsal ilişkileri nasıl aktardığını görüyoruz.

Neden aynı yaklaşımı web sitelerimizde kullanmıyoruz? Kullanıcının sayfa her değiştiğinde ışınlanıyormuş gibi hissetmesine neden razıyız?

Atlamadan sonra daha fazlası! Aşağıdan okumaya devam edin ↓

Web Sayfaları Arasında Geçiş Nasıl Yapılır?

SPA Çerçeveleri

Ellerimizi kirletmeden önce, tek sayfalık uygulama (SPA) çerçeveleri hakkında bir şeyler söylemeliyim. Bir SPA çerçevesi (AngularJS, Backbone.js veya Ember gibi) kullanıyorsanız, tüm yönlendirme zaten JavaScript tarafından işlendiğinden sayfalar arasında geçişler oluşturmak çok daha kolay olacaktır. Seçtiğiniz çerçeveyi kullanarak sayfaları nasıl değiştireceğinizi görmek için lütfen ilgili belgelere bakın, çünkü muhtemelen bazı iyi örnekler ve öğreticiler vardır.

Yanlış yön

Sayfalar arasında bir geçiş yaratmaya yönelik ilk denemem aşağı yukarı şuna benziyordu:

 document.addEventListener('DOMContentLoaded', function() { // Animate in }); document.addEventListener('beforeunload', function() { // Animate out });

Konsept basittir: Kullanıcı sayfadan ayrıldığında bir animasyon ve yeni sayfa yüklendiğinde başka bir animasyon kullanın.

Ancak kısa süre sonra bu çözümün bazı sınırlamaları olduğunu öğrendim:

  • Bir sonraki sayfanın yüklenmesinin ne kadar süreceğini bilmiyoruz, bu nedenle animasyon akıcı görünmeyebilir.
  • Önceki ve sonraki sayfalardaki içeriği birleştiren geçişler oluşturamayız.

Aslında akıcı ve yumuşak bir geçiş elde etmenin tek yolu, sayfa değiştirme süreci üzerinde tam kontrole sahip olmak ve bu nedenle sayfayı hiç değiştirmemektir . Bu nedenle, soruna yaklaşımımızı değiştirmeliyiz.

Doğru yol

Sayfalar arasında basit bir çapraz geçiş geçişinin doğru şekilde oluşturulmasıyla ilgili adımlara bakalım. Web sitemizi bir tür tek sayfalık web sitesine dönüştürecek olan pushState AJAX (veya PJAX) navigasyonu adı verilen bir şeyi içerir.

Bu teknik sadece yumuşak ve hoş geçişler sağlamakla kalmaz, aynı zamanda bu makalenin ilerleyen kısımlarında ayrıntılı olarak ele alacağımız diğer avantajlardan da faydalanacağız.

Varsayılan Bağlantı Davranışını Önleyin

İlk adım, tüm bağlantıların kullanması için bir click olay dinleyicisi oluşturmak, tarayıcının varsayılan davranışını gerçekleştirmesini engellemek ve sayfa değişikliklerini işleme şeklini özelleştirmek.

 // Note, we are purposely binding our listener on the document object // so that we can intercept any anchors added in future. document.addEventListener('click', function(e) { var el = e.target; // Go up in the nodelist until we find a node with .href (HTMLAnchorElement) while (el && !el.href) { el = el.parentNode; } if (el) { e.preventDefault(); return; } });

Her belirli düğüme eklemek yerine bir ana öğeye olay dinleyicisi eklemeye yönelik bu yönteme olay delegasyonu denir ve HTML DOM API'sinin olay köpüren doğası nedeniyle mümkündür.

Sayfayı Getir

Sayfayı değiştirmeye çalıştığında tarayıcıyı durdurduğumuza göre, Fetch API'sini kullanarak o sayfayı manuel olarak getirebiliriz. URL'si verildiğinde bir sayfanın HTML içeriğini getiren aşağıdaki fonksiyona bakalım.

 function loadPage(url) { return fetch(url, { method: 'GET' }).then(function(response) { return response.text(); }); }

Fetch API'yi desteklemeyen tarayıcılar için çoklu dolgu eklemeyi veya eski moda XMLHttpRequest kullanmayı düşünün.

Geçerli URL'yi Değiştir

HTML5, web sitelerinin herhangi bir sayfa yüklemeden tarayıcı geçmişine erişmesine ve bunları değiştirmesine olanak tanıyan pushState adlı harika bir API'ye sahiptir. Aşağıda, mevcut URL'yi bir sonraki sayfanın URL'si olacak şekilde değiştirmek için kullanıyoruz. Bunun, önceden bildirilmiş bağlantı tıklama olayı işleyicimizin bir modifikasyonu olduğunu unutmayın.

 if (el) { e.preventDefault(); history.pushState(null, null, el.href); changePage(); return; }

Fark etmiş olabileceğiniz gibi, birazdan ayrıntılı olarak inceleyeceğimiz changePage adlı bir işleve de bir çağrı ekledik. Aynı işlev, tarayıcının etkin geçmiş girişi değiştiğinde (bir kullanıcı tarayıcısının geri düğmesine tıkladığında olduğu gibi) tetiklenen popstate olayında da çağrılır:

 window.addEventListener('popstate', changePage);

Tüm bunlarla, temelde aktif ve pasif modlara sahip olduğumuz çok ilkel bir yönlendirme sistemi oluşturuyoruz.

Aktif modumuz, bir kullanıcı bir bağlantıya tıkladığında ve pushState kullanarak URL'yi değiştirdiğimizde kullanımdayken, URL değiştiğinde ve popstate olayı tarafından bilgilendirildiğinde pasif mod kullanımdadır. Her iki durumda da, yeni URL'yi okumak ve ilgili sayfayı yüklemekle ilgilenen changePage arayacağız.

Yeni İçeriği Ayrıştırma ve Ekleme

Genellikle, gezinilen sayfalarda header ve footer gibi ortak öğeler bulunur. Tüm sayfalarımızda (aslında Smashing Magazine'in yapısı olan) aşağıdaki DOM yapısını kullandığımızı varsayalım:

canlandırın!

Kullanıcı bir bağlantıyı tıkladığında, changePage işlevi o sayfanın HTML'sini getirir , ardından cc kapsayıcısını çıkarır ve onu main öğeye ekler . Bu noktada sayfamızda ilki bir önceki sayfaya, ikincisi bir sonraki sayfaya ait olmak üzere iki adet cc konteynerimiz bulunmaktadır.

Bir sonraki işlev olan animate , iki kapsayıcıyı üst üste bindirerek, eskisini soldurarak, yenisinde solarak ve eski kabı kaldırarak çapraz soldurmayı halleder. Bu örnekte, solma animasyonunu oluşturmak için Web Animasyonları API'sini kullanıyorum, ancak elbette istediğiniz herhangi bir tekniği veya kitaplığı kullanabilirsiniz.

 function animate(oldContent, newContent) { oldContent.style.position = 'absolute'; var fadeOut = oldContent.animate({ opacity: [1, 0] }, 1000); var fadeIn = newContent.animate({ opacity: [0, 1] }, 1000); fadeIn.onfinish = function() { oldContent.parentNode.removeChild(oldContent); }; }

Son kod GitHub'da mevcuttur.

Ve bunlar, web sayfalarını değiştirmenin temelleri!

Uyarılar ve Sınırlamalar

Az önce yarattığımız küçük örnek mükemmel olmaktan çok uzak. Aslında, hala birkaç şeyi hesaba katmadık:

  • Doğru bağlantıları etkilediğimizden emin olun.
    Bir bağlantının davranışını değiştirmeden önce, değiştirilmesi gerektiğinden emin olmak için bir kontrol eklemeliyiz. Örneğin, target="_blank" (sayfayı yeni bir sekmede açar) içeren tüm bağlantıları, harici etki alanlarına giden tüm bağlantıları ve Control/Command + click (aynı zamanda sayfayı şurada açar) gibi bazı diğer özel durumları yok saymalıyız. yeni bir sekme).
  • Ana içerik kabının dışındaki öğeleri güncelleyin.
    Şu anda sayfa değiştiğinde, cc kapsayıcısının dışındaki tüm öğeler aynı kalır. Bununla birlikte, belgenin title , active sınıfa sahip menü öğesi ve web sitesine bağlı olarak potansiyel olarak diğerleri dahil olmak üzere bu öğelerden bazılarının (şimdi yalnızca manuel olarak yapılabilir) değiştirilmesi gerekecektir.
  • JavaScript'in yaşam döngüsünü yönetin.
    Sayfamız artık tarayıcının sayfaları değiştirmediği bir SPA gibi davranıyor. Bu nedenle, JavaScript yaşam döngüsüyle manuel olarak ilgilenmemiz gerekiyor - örneğin, belirli olayları bağlama ve çözme, eklentileri yeniden değerlendirme ve çoklu dolgular ve üçüncü taraf kodu dahil etme.

Tarayıcı Desteği

Uyguladığımız bu gezinme modu için tek gereksinim, tüm modern tarayıcılarda bulunan pushState . Bu teknik , tamamen aşamalı bir geliştirme olarak çalışır . Sayfalar hala normal şekilde sunuluyor ve erişilebilir durumda ve JavaScript devre dışı bırakıldığında web sitesi normal şekilde çalışmaya devam edecek.

Bir SPA çerçevesi kullanıyorsanız, navigasyonu hızlı tutmak için bunun yerine PJAX navigasyonunu kullanmayı düşünün. Bunu yaparken, eski destek kazanır ve daha SEO dostu bir web sitesi oluşturursunuz.

Daha da ileri gitmek

Belirli yönlerini optimize ederek bu tekniğin sınırlarını zorlamaya devam edebiliriz. Sonraki birkaç püf noktası, gezinmeyi hızlandıracak ve kullanıcının deneyimini önemli ölçüde artıracaktır.

Önbellek Kullanma

loadPage biraz değiştirerek, daha önce ziyaret edilmiş sayfaların yeniden yüklenmemesini sağlayan basit bir önbellek ekleyebiliriz.

 var cache = {}; function loadPage(url) { if (cache[url]) { return new Promise(function(resolve) { resolve(cache[url]); }); } return fetch(url, { method: 'GET' }).then(function(response) { cache[url] = response.text(); return cache[url]; }); }

Tahmin edebileceğiniz gibi, Önbellek API'si veya başka bir istemci tarafı kalıcı depolama önbelleği (IndexedDB gibi) ile daha kalıcı bir önbellek kullanabiliriz.

Mevcut Sayfayı Canlandırma

Çapraz geçiş efektimiz, geçiş tamamlanmadan bir sonraki sayfanın yüklenmesini ve hazır olmasını gerektirir. Başka bir efektle, kullanıcı bağlantıyı tıklatır tıklamaz eski sayfayı canlandırmaya başlamak isteyebiliriz, bu da kullanıcıya anında geri bildirim sağlar, algılanan performansa büyük bir yardım sağlar.

Vaatleri kullanarak, bu tür bir durumla başa çıkmak çok kolay hale gelir. .all yöntemi, bağımsız değişkenler olarak dahil edilen tüm vaatler çözülür çözülmez çözülen yeni bir söz oluşturur.

 // As soon as animateOut() and loadPage() are resolved… Promise.all[animateOut(), loadPage(url)] .then(function(values) { …

Sonraki Sayfayı Önceden Getirme

Tarayıcının yeni sayfadaki herhangi bir komut dosyasını veya stili ayrıştırması ve değerlendirmesi gerekmediğinden, yalnızca PJAX gezinmesi kullanıldığında, sayfa değişiklikleri genellikle varsayılan gezinmeden neredeyse iki kat daha hızlıdır .

Ancak, kullanıcı bağlantının üzerine geldiğinde veya bağlantıya dokunmaya başladığında sonraki sayfayı önceden yüklemeye başlayarak daha da ileri gidebiliriz.

Gördüğünüz gibi, kullanıcının üzerine gelip tıklamasında genellikle 200 ila 300 milisaniyelik bir gecikme vardır. Bu ölü zamandır ve genellikle bir sonraki sayfayı yüklemek için yeterlidir.

Bununla birlikte, akıllıca önceden alın çünkü kolayca bir darboğaz haline gelebilir. Örneğin, uzun bir bağlantı listeniz varsa ve kullanıcı bu listede geziniyorsa, bağlantılar farenin altından geçtiği için bu teknik tüm sayfaları önceden getirecektir.

Önceden alıp almamaya karar verirken tespit edebileceğimiz ve hesaba katabileceğimiz bir diğer faktör de kullanıcının bağlantı hızıdır. (Belki bu gelecekte Network Information API ile mümkün olacaktır.)

Kısmi Çıkış

loadPage fonksiyonumuzda, HTML belgesinin tamamını getiriyoruz, ancak aslında sadece cc konteynerine ihtiyacımız var. Sunucu tarafı bir dil kullanıyorsak, isteğin belirli bir özel AJAX çağrısından gelip gelmediğini tespit edebilir ve eğer öyleyse, yalnızca ihtiyaç duyduğu kapsayıcıyı çıktısını alabiliriz. Headers API kullanarak, getirme isteğimize özel bir HTTP başlığı gönderebiliriz.

 function loadPage(url) { var myHeaders = new Headers(); myHeaders.append('x-pjax', 'yes'); return fetch(url, { method: 'GET', headers: myHeaders, }).then(function(response) { return response.text(); }); }

Ardından, sunucu tarafında (bu durumda PHP kullanarak), yalnızca gerekli kapsayıcıyı çıkarmadan önce özel başlığımızın var olup olmadığını tespit edebiliriz:

 if (isset($_SERVER['HTTP_X_PJAX'])) { // Output just the container }

Bu, HTTP mesajının boyutunu küçültecek ve ayrıca sunucu tarafı yükünü azaltacaktır.

Toplama

Bu tekniği birkaç projede uyguladıktan sonra, yeniden kullanılabilir bir kütüphanenin son derece yararlı olacağını fark ettim. Her seferinde uygulamamda bana zaman kazandıracak ve geçiş efektlerine odaklanmam için beni özgürleştirecekti.

Böylece, tüm bu karmaşıklığı soyutlayan ve geliştiricilerin kullanması için güzel, temiz ve basit bir API sağlayan küçük bir kitaplık (4 KB küçültülmüş ve gZip'd) olan Barba.js doğdu. Ayrıca görünümleri hesaba katar ve yeniden kullanılabilir geçişler, önbelleğe alma, önceden getirme ve olaylarla birlikte gelir. Açık kaynak kodludur ve GitHub'da mevcuttur.

Çözüm

Şimdi, çapraz geçiş efektinin nasıl oluşturulacağını ve web sitemizi etkin bir şekilde bir SPA'ya dönüştürmek için PJAX navigasyonunu kullanmanın artılarını ve eksilerini gördük. Geçişin sağladığı faydaların yanı sıra, yeni sayfaların yüklenmesini hızlandırmak için basit önbelleğe alma ve önceden getirme mekanizmalarının nasıl uygulanacağını da gördük.

Bu makalenin tamamı, kişisel deneyimime ve üzerinde çalıştığım projelerde sayfa geçişlerini uygulamaktan öğrendiklerime dayanmaktadır. Herhangi bir sorunuz varsa, yorum bırakmaktan veya Twitter'da bana ulaşmaktan çekinmeyin - bilgilerim aşağıda!

SmashingMag'de Daha Fazla Okuma :

  • Kullanıcı Deneyimi Tasarımında Akıllı Geçişler
  • Çok Cihazlı Bir Dünyaya Geçişte Tasarım
  • Web Teknolojileri ile Yerli Bir Deneyim Sağlamak