İki farklı doküman arasında görüntüleme geçişi gerçekleştiğinde buna dokümanlar arası görüntüleme geçişi adı verilir. Bu durum genellikle çok sayfalı uygulamalarda (MPA) geçerlidir. Dokümanlar arası görünüm geçişleri, Chrome 126 sürümünden Chrome'da desteklenir.
Tarayıcı Desteği
- .
- .
- .
- .
Belgeler arası görünüm geçişleri, aynı doküman görüntüleme geçişleriyle tamamen aynı yapı taşlarını ve ilkeleri temel alır. Bu geçişlerin yapılması planlı olarak gerçekleştirilir:
- Tarayıcı, hem eski hem de yeni sayfada benzersiz bir
view-transition-name
değerine sahip öğelerin anlık görüntülerini alır. - Oluşturma işlemi atlanırken DOM güncellenir.
- Son olarak, geçişler CSS animasyonları tarafından desteklenir.
Aynı doküman görüntüleme geçişleriyle karşılaştırıldığında farklı olan, dokümanlar arası görünüm geçişlerinde bir görüntüleme geçişi başlatmak için document.startViewTransition
çağrısına gerek olmamasıdır. Bunun yerine, belgeler arası görüntüleme geçişi tetikleyicisi, bir sayfadan diğerine yapılan aynı kaynak gezinmedir. Bu işlem, genellikle web sitenizdeki bir kullanıcının bir bağlantıyı tıkladığında gerçekleştirilir.
Diğer bir deyişle, iki doküman arasında görünüm geçişi başlatmak için çağrılacak bir API yoktur. Ancak karşılanması gereken iki koşul vardır:
- Her iki dokümanın da aynı kaynakta bulunması gerekir.
- Görüntüleme geçişine izin vermek için her iki sayfanın da etkinleştirilmesi gerekir.
Bu koşulların her ikisi de bu belgenin ilerleyen bölümlerinde açıklanmaktadır.
Belgeler arası görünüm geçişleri, aynı kaynak gezinmelerle sınırlıdır
Belgeler arası görünüm geçişleri yalnızca aynı kaynak gezinmeleriyle sınırlıdır. Katılımcı her iki sayfanın kaynağı aynıysa gezinmenin aynı kaynak olduğu kabul edilir.
Bir sayfanın kaynağı, web.dev'de ayrıntılarıyla açıklandığı üzere kullanılan şema, ana makine adı ve bağlantı noktasının birleşimidir.
Örneğin, aynı kaynaklar olduğu için developer.chrome.com
ürününden developer.chrome.com/blog
ürününe giderken belgeler arası bir görünüm geçişiniz olabilir.
Kaynaklar arası ve aynı site olduğundan developer.chrome.com
sitesinden www.chrome.com
sitesine giderken bu geçişi yapamazsınız.
Belgeler arası görünüm geçişleri isteğe bağlıdır
İki doküman arasında belgeler arası görüntüleme geçişi için, her iki katılımcı sayfanın da buna izin vermesi gerekir. Bu işlem, CSS'de @view-transition
kuralı ile yapılır.
@view-transition
üt kuralında navigation
tanımlayıcıyı auto
olarak ayarlayarak belgeler arası, aynı kaynaklı gezinmeler için görüntüleme geçişlerini etkinleştirin.
@view-transition {
navigation: auto;
}
navigation
açıklayıcıyı auto
olarak ayarladığınızda, aşağıdaki NavigationType'larda görüntüleme geçişlerinin yapılmasına izin vermiş olursunuz:
traverse
- Etkinleştirme işlemi kullanıcı tarafından tarayıcı kullanıcı arayüzü mekanizmaları ile başlatılmadıysa
push
veyareplace
.
auto
dışında tutulan gezinmeler, örneğin, URL adres çubuğunu kullanarak gezinme veya bir yer işaretini tıklayarak gezinmenin yanı sıra kullanıcı veya komut dosyası tarafından başlatılan yeniden yükleme biçimindedir.
Gezinme işlemi çok uzun sürerse (Chrome'da dört saniyeden uzun sürerse) görüntüleme geçişi TimeoutError
DOMException
ile atlanır.
Belgeler arası görüntüleme geçişleri demosu
Stack Navigator demosu oluşturmak için görünüm geçişlerinin kullanıldığı aşağıdaki demoya göz atın. Burada document.startViewTransition()
için çağrı yok. Bir sayfadan diğerine gidildiğinde görünüm geçişleri tetiklenir.
Belgeler arası görünüm geçişlerini özelleştirme
Belgeler arası görünüm geçişlerini özelleştirmek için kullanabileceğiniz bazı web platformu özellikleri vardır.
Bu özellikler, View Transition API spesifikasyonunun bir parçası değildir ancak onunla birlikte kullanılmak üzere tasarlanmıştır.
pageswap
ve pagereveal
etkinlikleri
Belgeler arası görünüm geçişlerini özelleştirmenizi sağlamak için HTML spesifikasyonu kullanabileceğiniz iki yeni etkinlik içeriyor: pageswap
ve pagereveal
.
Bu iki etkinlik, bir görüntüleme geçişi gerçekleşmek üzere olup olmadığına bakılmaksızın, aynı kaynaktan belgeler arası her gezinme için tetiklenir. İki sayfa arasında bir görünüm geçişi gerçekleşmek üzereyse bu etkinliklerde viewTransition
özelliğini kullanarak ViewTransition
nesnesine erişebilirsiniz.
pageswap
etkinliği, bir sayfanın son karesi oluşturulmadan önce tetiklenir. Bunu, eski anlık görüntüler alınmadan hemen önce, giden sayfada bazı son dakika değişiklikleri yapmak için kullanabilirsiniz.pagereveal
etkinliği, başlatıldıktan veya yeniden etkinleştirildikten sonra ancak ilk oluşturma fırsatından önce bir sayfada tetiklenir. Bu sayede, yeni anlık görüntüler alınmadan önce yeni sayfayı özelleştirebilirsiniz.
Örneğin, görünüm geçişini gerçekten çalışmadan önce özelleştirmek amacıyla bazı view-transition-name
değerlerini hızlı bir şekilde ayarlamak veya değiştirmek ya da sessionStorage
ürünündeki verileri yazıp okuyarak bir dokümandan diğerine veri aktarmak için bu etkinlikleri kullanabilirsiniz.
let lastClickX, lastClickY;
document.addEventListener('click', (event) => {
if (event.target.tagName.toLowerCase() === 'a') return;
lastClickX = event.clientX;
lastClickY = event.clientY;
});
// Write position to storage on old page
window.addEventListener('pageswap', (event) => {
if (event.viewTransition && lastClick) {
sessionStorage.setItem('lastClickX', lastClickX);
sessionStorage.setItem('lastClickY', lastClickY);
}
});
// Read position from storage on new page
window.addEventListener('pagereveal', (event) => {
if (event.viewTransition) {
lastClickX = sessionStorage.getItem('lastClickX');
lastClickY = sessionStorage.getItem('lastClickY');
}
});
İsterseniz her iki etkinlikte de geçişi atlamaya karar verebilirsiniz.
window.addEventListener("pagereveal", async (e) => {
if (e.viewTransition) {
if (goodReasonToSkipTheViewTransition()) {
e.viewTransition.skipTransition();
}
}
}
pageswap
ve pagereveal
içindeki ViewTransition
nesnesi, iki farklı nesnedir. Ayrıca çeşitli işlemleri farklı şekilde ele alırlar:
pageswap
: Doküman gizlendikten sonra eskiViewTransition
nesnesi atlanır. Bu durumdaviewTransition.ready
işlemi reddeder veviewTransition.finished
işlemi sonlandırır.pagereveal
:updateCallBack
taahhüdü şu anda zaten gerçekleştirildi.viewTransition.ready
veviewTransition.finished
taahhütlerini kullanabilirsiniz.
Navigasyon etkinleştirme bilgileri
Hem pageswap
hem de pagereveal
etkinliklerinde, eski ve yeni sayfaların URL'lerine göre işlem yapabilirsiniz.
Örneğin, MPA Stack Navigator'da kullanılacak animasyon türü, gezinme yoluna bağlıdır:
- Genel bakış sayfasından ayrıntılar sayfasına giderken yeni içeriğin sağdan sola kaydırılması gerekir.
- Ayrıntılar sayfasından genel bakış sayfasına giderken eski içeriğin soldan sağa doğru kaydırılması gerekir.
Bunu yapmak için, pageswap
söz konusu olduğunda gerçekleşmek üzere olan veya pagereveal
durumunda gerçekleşmiş olan navigasyon hakkında bilgilere ihtiyacınız vardır.
Bunun için tarayıcılar artık aynı kaynak gezinmeyle ilgili bilgi içeren NavigationActivation
nesnelerini gösterebilir. Bu nesne, kullanılan gezinme türünü, geçerli ve son hedef geçmişi girişlerini Gezinme API'sindeki navigation.entries()
içinde bulunduğu şekliyle gösterir.
Etkinleştirilmiş bir sayfada bu nesneye navigation.activation
üzerinden erişebilirsiniz. pageswap
etkinliğinde buna e.activation
üzerinden erişebilirsiniz.
Görünüm geçişine katılması gereken öğelerde view-transition-name
değerlerini ayarlamak için pageswap
ve pagereveal
etkinliklerinde NavigationActivation
bilgilerinin kullanıldığı bu Profil demosuna göz atın.
Bu şekilde, listedeki her bir öğeyi önceden view-transition-name
ile süslemeniz gerekmez. Bunun yerine, bu tam zamanında JavaScript kullanılarak, yalnızca gerektiğinde öğelerde gerçekleştirilir.
Kod şu şekildedir:
// OLD PAGE LOGIC
window.addEventListener('pageswap', async (e) => {
if (e.viewTransition) {
const targetUrl = new URL(e.activation.entry.url);
// Navigating to a profile page
if (isProfilePage(targetUrl)) {
const profile = extractProfileNameFromUrl(targetUrl);
// Set view-transition-name values on the clicked row
document.querySelector(`#${profile} span`).style.viewTransitionName = 'name';
document.querySelector(`#${profile} img`).style.viewTransitionName = 'avatar';
// Remove view-transition-names after snapshots have been taken
// (this to deal with BFCache)
await e.viewTransition.finished;
document.querySelector(`#${profile} span`).style.viewTransitionName = 'none';
document.querySelector(`#${profile} img`).style.viewTransitionName = 'none';
}
}
});
// NEW PAGE LOGIC
window.addEventListener('pagereveal', async (e) => {
if (e.viewTransition) {
const fromURL = new URL(navigation.activation.from.url);
const currentURL = new URL(navigation.activation.entry.url);
// Navigating from a profile page back to the homepage
if (isProfilePage(fromURL) && isHomePage(currentURL)) {
const profile = extractProfileNameFromUrl(currentURL);
// Set view-transition-name values on the elements in the list
document.querySelector(`#${profile} span`).style.viewTransitionName = 'name';
document.querySelector(`#${profile} img`).style.viewTransitionName = 'avatar';
// Remove names after snapshots have been taken
// so that we're ready for the next navigation
await e.viewTransition.ready;
document.querySelector(`#${profile} span`).style.viewTransitionName = 'none';
document.querySelector(`#${profile} img`).style.viewTransitionName = 'none';
}
}
});
Kod, görünüm geçişi çalıştırıldıktan sonra view-transition-name
değerlerini kaldırarak kendisinden sonra da temizlenir. Bu şekilde, sayfa art arda gezinme için hazır olur ve geçmiş gezinmesini de işleyebilir.
Bu konuda yardımcı olmak için, geçici olarak view-transition-name
öğelerini ayarlayan bu yardımcı program işlevini kullanın.
const setTemporaryViewTransitionNames = async (entries, vtPromise) => {
for (const [$el, name] of entries) {
$el.style.viewTransitionName = name;
}
await vtPromise;
for (const [$el, name] of entries) {
$el.style.viewTransitionName = '';
}
}
Önceki kod artık aşağıdaki şekilde basitleştirilebilir:
// OLD PAGE LOGIC
window.addEventListener('pageswap', async (e) => {
if (e.viewTransition) {
const targetUrl = new URL(e.activation.entry.url);
// Navigating to a profile page
if (isProfilePage(targetUrl)) {
const profile = extractProfileNameFromUrl(targetUrl);
// Set view-transition-name values on the clicked row
// Clean up after the page got replaced
setTemporaryViewTransitionNames([
[document.querySelector(`#${profile} span`), 'name'],
[document.querySelector(`#${profile} img`), 'avatar'],
], e.viewTransition.finished);
}
}
});
// NEW PAGE LOGIC
window.addEventListener('pagereveal', async (e) => {
if (e.viewTransition) {
const fromURL = new URL(navigation.activation.from.url);
const currentURL = new URL(navigation.activation.entry.url);
// Navigating from a profile page back to the homepage
if (isProfilePage(fromURL) && isHomePage(currentURL)) {
const profile = extractProfileNameFromUrl(currentURL);
// Set view-transition-name values on the elements in the list
// Clean up after the snapshots have been taken
setTemporaryViewTransitionNames([
[document.querySelector(`#${profile} span`), 'name'],
[document.querySelector(`#${profile} img`), 'avatar'],
], e.viewTransition.ready);
}
}
});
Oluşturma engelleme işleviyle içeriğin yüklenmesini bekleyin
Tarayıcı Desteği
- .
- .
- .
- .
Bazı durumlarda, belirli bir öğe yeni DOM'de mevcut olana kadar bir sayfanın ilk oluşturulmasını bekletmek isteyebilirsiniz. Bu yöntem, yanıp sönmenin önüne geçer ve animasyon uyguladığınız durumun sabit olduğundan emin olur.
<head>
içinde, aşağıdaki meta etiketi kullanarak sayfa ilk kez oluşturulmadan önce mevcut olması gereken bir veya daha fazla öğe kimliği tanımlayın.
<link rel="expect" blocking="render" href="#section1">
Bu meta etiket, içeriğin yüklenmesi gerektiği değil, öğenin DOM'de mevcut olması gerektiği anlamına gelir. Örneğin, resimlerde DOM ağacında belirtilen id
ile birlikte <img>
etiketinin sadece olması, koşulun doğru olarak değerlendirilmesi için yeterlidir. Resmin kendisi hâlâ yükleniyor olabilir.
Oluşturmayı engellemeye başlamadan önce, artımlı oluşturmanın web'in temel bir yönü olduğunu unutmayın. Bu nedenle, oluşturmayı engellemeyi seçerken dikkatli olun. Oluşturmayı engellemenin etkisi, tek tek örnekler ele alınarak değerlendirilmelidir. Varsayılan olarak Core Web Vitals etkisini ölçerek kullanıcılarınız üzerindeki etkisini etkin bir şekilde ölçemiyorsanız blocking=render
kullanmaktan kaçının.
Belgeler arası görünüm geçişlerinde geçiş türlerini görüntüleme
Belgeler arası görünüm geçişleri, animasyonları ve hangi öğelerin yakalanacağını özelleştirmek için görünüm geçiş türlerini de destekler.
Örneğin, sayfalara ayırmada sonraki veya önceki sayfaya giderken, dizideki daha üst veya daha alt bir sayfaya mı gittiğinize bağlı olarak farklı animasyonlar kullanmak isteyebilirsiniz.
Bu türleri önceden ayarlamak için @view-transition
kuralında türleri ekleyin:
@view-transition {
navigation: auto;
types: slide, forwards;
}
Türleri anında ayarlamak için pageswap
ve pagereveal
etkinliklerini kullanarak e.viewTransition.types
değerini değiştirin.
window.addEventListener("pagereveal", async (e) => {
if (e.viewTransition) {
const transitionType = determineTransitionType(navigation.activation.from, navigation.activation.entry);
e.viewTransition.types.add(transitionType);
}
});
Türler, eski sayfadaki ViewTransition
nesnesinden yeni sayfanın ViewTransition
nesnesine otomatik olarak taşınmaz. Animasyonların beklendiği gibi çalışması için en azından yeni sayfada kullanılacak türleri belirlemeniz gerekir.
Bu türlere yanıt vermek için :active-view-transition-type()
sözde sınıf seçiciyi aynı belge görüntüleme geçişleriyle aynı şekilde kullanın.
/* Determine what gets captured when the type is forwards or backwards */
html:active-view-transition-type(forwards, backwards) {
:root {
view-transition-name: none;
}
article {
view-transition-name: content;
}
.pagination {
view-transition-name: pagination;
}
}
/* Animation styles for forwards type only */
html:active-view-transition-type(forwards) {
&::view-transition-old(content) {
animation-name: slide-out-to-left;
}
&::view-transition-new(content) {
animation-name: slide-in-from-right;
}
}
/* Animation styles for backwards type only */
html:active-view-transition-type(backwards) {
&::view-transition-old(content) {
animation-name: slide-out-to-right;
}
&::view-transition-new(content) {
animation-name: slide-in-from-left;
}
}
/* Animation styles for reload type only */
html:active-view-transition-type(reload) {
&::view-transition-old(root) {
animation-name: fade-out, scale-down;
}
&::view-transition-new(root) {
animation-delay: 0.25s;
animation-name: fade-in, scale-up;
}
}
Türler yalnızca aktif görüntüleme geçişine uygulandığından, görünüm geçişi tamamlandığında türler otomatik olarak temizlenir. Bu nedenle, türler BFCache gibi özelliklerle sorunsuz çalışır.
Demo
Aşağıdaki sayfalandırma demosunda sayfa içerikleri, ziyaret ettiğiniz sayfa numarasına göre ileri veya geri kaydırılır.
Kullanılacak geçiş türü, pagereveal
ve pageswap
etkinliklerinde URL'lere ve URL'lerden verilere bakılarak belirlenir.
const determineTransitionType = (fromNavigationEntry, toNavigationEntry) => {
const currentURL = new URL(fromNavigationEntry.url);
const destinationURL = new URL(toNavigationEntry.url);
const currentPathname = currentURL.pathname;
const destinationPathname = destinationURL.pathname;
if (currentPathname === destinationPathname) {
return "reload";
} else {
const currentPageIndex = extractPageIndexFromPath(currentPathname);
const destinationPageIndex = extractPageIndexFromPath(destinationPathname);
if (currentPageIndex > destinationPageIndex) {
return 'backwards';
}
if (currentPageIndex < destinationPageIndex) {
return 'forwards';
}
return 'unknown';
}
};
Geri bildirim
Geliştirici geri bildirimleri bizim için çok değerli. Paylaşmak için öneriler ve sorularla GitHub'da CSS Çalışma Grubu'na bir sorun bildirin. Sorununuzun önüne [css-view-transitions]
ekleyin.
Bir hatayla karşılaşırsanız bunun yerine Chromium hatası bildirin.