Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/wp-content/themes/twentyfifteen/css/view-transitions.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@view-transition {
navigation: auto;
}
15 changes: 15 additions & 0 deletions src/wp-content/themes/twentyfifteen/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,21 @@ function twentyfifteen_scripts() {
'collapse' => '<span class="screen-reader-text">' . __( 'collapse child menu', 'twentyfifteen' ) . '</span>',
)
);

wp_enqueue_style(
'twentyfifteen-view-transitions',
get_template_directory_uri() . '/css/view-transitions.css',
array(),
'20250115'
);

// This script must be loaded prior to rendering, i.e. not in the footer and not deferred or async.
wp_enqueue_script(
'twentyfifteen-view-transitions',
get_template_directory_uri() . '/js/view-transitions.js',
array(),
'20250115'
);
}
add_action( 'wp_enqueue_scripts', 'twentyfifteen_scripts' );

Expand Down
87 changes: 87 additions & 0 deletions src/wp-content/themes/twentyfifteen/js/view-transitions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
if ( !! window.navigation && 'CSSViewTransitionRule' in window ) {
const setTemporaryViewTransitionNames = async ( entries, vtPromise ) => {
for ( const [ element, name ] of entries ) {
if ( ! element ) {
continue;
}
element.style.viewTransitionName = name;
}

await vtPromise;

for ( const [ element, _ ] of entries ) {
if ( ! element ) {
continue;
}
element.style.viewTransitionName = '';
}
};

window.addEventListener( 'pageswap', ( e ) => {
if ( e.viewTransition ) {
if ( document.body.classList.contains( 'single' ) ) {
const article = document.querySelectorAll( 'article.post' );
if ( article.length !== 1 ) {
return;
}

setTemporaryViewTransitionNames( [
[ article[ 0 ].querySelector( '.entry-title' ), 'post-title' ],
[ article[ 0 ].querySelector( '.post-thumbnail' ), 'post-thumbnail' ],
], e.viewTransition.finished );
} else if ( document.body.classList.contains( 'home' ) || document.body.classList.contains( 'archive' ) ) {
const articleLink = document.querySelector( 'article.post a[href="' + e.activation.entry.url + '"]' );
if ( ! articleLink ) {
return;
}
Comment on lines +33 to +36
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bramus I debugged the issue further and got as far as figuring out that it, for some reason, comes down to this:

  • When you click on the link to an article without a featured image from the home page, the articleLink variable here will be empty - at least this is how it shows when I add a console.log( articleLink ); below.
  • This causes the early return to trigger.

I still don't understand why that's happening, for two reasons:

  1. If I manually run this exact document.querySelector( ... ) call in the console using the URL of that post in question, I do get a result, which is the a element in the post title. That's what I would expect. But for some reason, during the view transition it returns nothing.
  2. The early return here is triggered if articleLink is empty. But that shouldn't cause the browser to infinitely get stuck on loading the page right? Or is there any "cleanup" to do if a view transition is "aborted" with an early return like this?


const article = articleLink.closest( 'article.post' );
if ( ! article ) {
return;
}

setTemporaryViewTransitionNames( [
[ article.querySelector( '.entry-title' ), 'post-title' ],
[ article.querySelector( '.post-thumbnail' ), 'post-thumbnail' ],
], e.viewTransition.finished );
}
}
} );

window.addEventListener( 'pagereveal', ( e ) => {
if ( ! window.navigation.activation.from ) {
return;
}

if ( e.viewTransition ) {
if ( document.body.classList.contains( 'single' ) ) {
const article = document.querySelectorAll( 'article.post' );
if ( article.length !== 1 ) {
return;
}

setTemporaryViewTransitionNames( [
[ article[ 0 ].querySelector( '.entry-title' ), 'post-title' ],
[ article[ 0 ].querySelector( '.post-thumbnail' ), 'post-thumbnail' ],
], e.viewTransition.ready );
} else if ( document.body.classList.contains( 'home' ) || document.body.classList.contains( 'archive' ) ) {
const articleLink = document.querySelector( 'article.post a[href="' + window.navigation.activation.from.url + '"]' );
if ( ! articleLink ) {
return;
}

const article = articleLink.closest( 'article.post' );
if ( ! article ) {
return;
}

setTemporaryViewTransitionNames( [
[ article.querySelector( '.entry-title' ), 'post-title' ],
[ article.querySelector( '.post-thumbnail' ), 'post-thumbnail' ],
], e.viewTransition.ready );
}
}
} );
} else {
window.console.warn( 'View transitions not loaded as the browser is lacking support.' );
}
Loading