{"id":10617,"date":"2026-08-07T13:46:31","date_gmt":"2026-08-07T18:46:31","guid":{"rendered":"https:\/\/master.dev\/blog\/?p=10617"},"modified":"2026-08-07T13:46:33","modified_gmt":"2026-08-07T18:46:33","slug":"view-transitions-careful-not-to-make-stuff-unclickable","status":"publish","type":"post","link":"https:\/\/master.dev\/blog\/view-transitions-careful-not-to-make-stuff-unclickable\/","title":{"rendered":"View Transitions: Careful Not To Make Stuff Unclickable"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Just a little Public Service Announcement here. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s say you&#8217;re doing a View Transition in the form of using the <code>.startViewTransition()<\/code> method. Maybe you&#8217;re <a href=\"https:\/\/codepen.io\/editor\/team\/CodePenTemplates\/pen\/019cb5ec-807e-727a-b18a-5eb41b0fc901\">showing an image bigger<\/a> or sorting a table or <a href=\"https:\/\/codepen.io\/editor\/chriscoyier\/pen\/019779ce-914a-726c-99ba-6416c013d117\">moving some list items around<\/a> or something.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you don&#8217;t deal with it specifically, it&#8217;s likely you&#8217;re <strong>blocking interactivity on the rest of the page.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s a very basic demo. There is an <code>alert()<\/code> button you can click to see an alert. Click that and see. Then run the View Transition and try to click that button.<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_019fbe0b-75d4-7c3d-b614-9969f22eb640\" src=\"\/\/codepen.io\/editor\/anon\/embed\/019fbe0b-75d4-7c3d-b614-9969f22eb640?height=550&amp;theme-id=1&amp;slug-hash=019fbe0b-75d4-7c3d-b614-9969f22eb640&amp;default-tab=result\" height=\"550\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed 019fbe0b-75d4-7c3d-b614-9969f22eb640\" title=\"CodePen Embed 019fbe0b-75d4-7c3d-b614-9969f22eb640\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">See how you can&#8217;t click the alert button while the View Transition is running?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Because of the long 10s duration in that example, it should give you enough time to open DevTools and take a peek. You should be able to see the <a href=\"https:\/\/master.dev\/blog\/demystifying-the-view-transition-pseudo-tree\/\">View Transition Pseudo Tree<\/a> there. And if you hover over the top one, the <code>::view-transition<\/code>, you&#8217;ll see it cover the entire viewport in light blue, telling you the dimensions of it cover the entire viewport.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"594\" src=\"https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/08\/CleanShot-2026-08-07-at-11.09.15%402x.png?resize=1024%2C594&#038;ssl=1\" alt=\"\" class=\"wp-image-10626\" srcset=\"https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/08\/CleanShot-2026-08-07-at-11.09.15%402x.png?resize=1024%2C594&amp;ssl=1 1024w, https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/08\/CleanShot-2026-08-07-at-11.09.15%402x.png?resize=300%2C174&amp;ssl=1 300w, https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/08\/CleanShot-2026-08-07-at-11.09.15%402x.png?resize=768%2C446&amp;ssl=1 768w, https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/08\/CleanShot-2026-08-07-at-11.09.15%402x.png?resize=1536%2C892&amp;ssl=1 1536w, https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/08\/CleanShot-2026-08-07-at-11.09.15%402x.png?resize=2048%2C1189&amp;ssl=1 2048w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">So now you&#8217;ve got this big, giant, invisible element covering the entire viewport for the entire length of the transition. <strong>That&#8217;s what stops the interactivity<\/strong>, like clicking.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Solution<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Two-parter here. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">One, the <code>:root<\/code> element has a <code>view-transition-name<\/code> by default, so it&#8217;s going to take part in the overall View Transition even if it doesn&#8217;t really do anything. I think this is a default so that entire pages can cross-fade in multi-page View Transitions. But we don&#8217;t need that. So if we remove the name, it won&#8217;t be one of the snap-shotted elements taking up space. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Two, the <code>::view-transition<\/code> element is also that big giant viewport-covering element, and what we need to do there is make sure you can click through it.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-pseudo\">:root<\/span> {\n  <span class=\"hljs-attribute\">view-transition-name<\/span>: none;\n}\n<span class=\"hljs-selector-pseudo\">::view-transition<\/span> { \n  <span class=\"hljs-attribute\">pointer-events<\/span>: none;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">The snap-shotted (for lack of a better term) elements you actually see transitioning on a page are essentially on the &#8220;top layer&#8221; while the View Transition is happening. So they&#8217;ll soak up clicks while they are there. Not sure why that&#8217;s the default, but that&#8217;s what we got. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Another Newer Solution<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Another solution here is the &#8220;scope down&#8221; the View Transition. We don&#8217;t <em>have<\/em> to call <code>document.startViewTransition()<\/code> (like, on the <code>document<\/code>) although that definitely has the best browser support. Instead, we can call that method on the element that has the elements inside it that we care to transition. Like&#8230;<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">const<\/span> parent = <span class=\"hljs-built_in\">document<\/span>.querySelector(<span class=\"hljs-string\">\"#parent\"<\/span>);\nmove.addEventListener(<span class=\"hljs-string\">\"click\"<\/span>, () =&gt; {\n  parent.startViewTransition(<span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n    thing.classList.toggle(<span class=\"hljs-string\">\"moved\"<\/span>);\n  })\n});<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/developer.chrome.com\/blog\/scoped-view-transitions-feedback\">Scoped view transitions<\/a> are just a good idea, allowing for things like keeping elements in a hidden overflow area and such (because the pseudo-element tree stays within that parent element). We also benefit here as, without doing any other CSS manipulation, interactive elements aren&#8217;t affected. You still might wanna do the CSS stuff, though, if you want to retain interactivity <em>within<\/em> the scoped area.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>View Transitions block interactivity (like clicks) while they are running. Maybe you don&#8217;t want to do that. <\/p>\n","protected":false},"author":1,"featured_media":10625,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[1],"tags":[7,3,182,101],"class_list":["post-10617","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog-post","tag-css","tag-javascript","tag-pointer-events","tag-view-transitions"],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/master.dev\/blog\/wp-content\/uploads\/2026\/08\/clickable.jpg?fit=2000%2C1200&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/master.dev\/blog\/wp-json\/wp\/v2\/posts\/10617","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/master.dev\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/master.dev\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/master.dev\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/master.dev\/blog\/wp-json\/wp\/v2\/comments?post=10617"}],"version-history":[{"count":5,"href":"https:\/\/master.dev\/blog\/wp-json\/wp\/v2\/posts\/10617\/revisions"}],"predecessor-version":[{"id":10629,"href":"https:\/\/master.dev\/blog\/wp-json\/wp\/v2\/posts\/10617\/revisions\/10629"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/master.dev\/blog\/wp-json\/wp\/v2\/media\/10625"}],"wp:attachment":[{"href":"https:\/\/master.dev\/blog\/wp-json\/wp\/v2\/media?parent=10617"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/master.dev\/blog\/wp-json\/wp\/v2\/categories?post=10617"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/master.dev\/blog\/wp-json\/wp\/v2\/tags?post=10617"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}