[{"data":1,"prerenderedAt":1017},["ShallowReactive",2],{"content:\u002Fframework-performance\u002Fastro-and-sveltekit-performance\u002Fchoosing-astro-client-directives":3,"surroundings:\u002Fframework-performance\u002Fastro-and-sveltekit-performance\u002Fchoosing-astro-client-directives":1008},{"id":4,"title":5,"body":6,"description":988,"extension":989,"meta":990,"navigation":1001,"path":1002,"seo":1003,"stem":1006,"__hash__":1007},"content\u002Fframework-performance\u002Fastro-and-sveltekit-performance\u002Fchoosing-astro-client-directives\u002Findex.md","Choosing Astro Client Directives",{"type":7,"value":8,"toc":969},"minimark",[9,14,39,42,137,142,172,176,182,188,194,200,204,209,279,283,289,293,299,303,330,498,502,505,509,524,528,543,674,724,728,738,742,750,754,780,784,796,802,811,821,825,835,844,853,865,874,883,892,904,916,929,933,955,959,962,965],[10,11,13],"h1",{"id":12},"how-to-choose-astro-client-directives","How to Choose Astro Client Directives",[15,16,17,18,23,24,28,29,33,34,38],"p",{},"This guide is part of ",[19,20,22],"a",{"href":21},"\u002Fframework-performance\u002Fastro-and-sveltekit-performance\u002F","Astro & SvelteKit Performance",", within ",[19,25,27],{"href":26},"\u002Fframework-performance\u002F","Framework Performance",". In Astro, a UI framework component rendered without a directive is static HTML: it renders on the server and ships no JavaScript. Adding a ",[30,31,32],"code",{},"client:*"," directive turns it into an island that loads its code and hydrates in the browser. The directive decides ",[35,36,37],"strong",{},"when",": immediately on page load, when the browser is idle, when the island becomes visible, when a media query matches, or only on the client without server rendering.",[15,40,41],{},"The choice matters because every island hydrated at load competes with the browser's other work during the most sensitive window for TBT and early INP. Most islands do not need to be interactive in the first second. Choosing the latest directive that still meets user expectations keeps the main thread free when it matters most.",[15,43,44],{},[45,46,52,53,52,60,52,64,52,67,52,76,52,82,52,89,52,97,52,102,52,106,52,112,52,116,52,120,52,127,52,131,52],"svg",{"viewBox":47,"width":48,"role":49,"ariaLabel":50,"style":51},"0 0 760 189","100%","img","Bar chart of when island hydration starts after navigation for client load, idle and visible directives on a typical article page.","height:auto;max-width:760px;display:block;margin:1.75rem auto;font-family:inherit;color:var(--fp-svg-ink)"," ",[54,55],"rect",{"className":56,"x":58,"y":58,"width":48,"height":48,"fill":59},[57],"svg-canvas","0","#ffffff",[61,62,63],"title",{},"When islands hydrate under each directive",[65,66,50],"desc",{},[54,68],{"x":69,"y":69,"width":70,"height":71,"rx":72,"fill":73,"stroke":74,"style":75},"1","758","187","10","none","currentColor","stroke-opacity:0.18",[77,78,63],"text",{"x":79,"y":80,"fill":74,"style":81},"28.0","34.0","font-size:16px;font-weight:700",[77,83,88],{"x":84,"y":85,"fill":74,"style":86,"textAnchor":87},"177.7","70.0","font-size:13px","end","client:load",[54,90],{"x":91,"y":92,"width":93,"height":94,"rx":95,"fill":73,"stroke":74,"style":96},"189.7","56.0","68.3","19","3","fill-opacity:0.7;stroke-opacity:0.35",[77,98,101],{"x":99,"y":85,"fill":74,"style":100},"264.1","font-size:12px;font-weight:600","600ms",[77,103,105],{"x":84,"y":104,"fill":74,"style":86,"textAnchor":87},"101.0","client:idle",[54,107],{"x":91,"y":108,"width":109,"height":94,"rx":95,"fill":110,"stroke":110,"style":111},"87.0","205.0","#0466c8","fill-opacity:0.55;stroke-opacity:0.9",[77,113,115],{"x":114,"y":104,"fill":74,"style":100},"400.7","1800ms",[77,117,119],{"x":84,"y":118,"fill":74,"style":86,"textAnchor":87},"132.0","client:visible (on scroll)",[54,121],{"x":91,"y":122,"width":123,"height":94,"rx":95,"fill":124,"stroke":125,"style":126},"118.0","478.3","#ffc300","#b8860b","fill-opacity:0.7;stroke-opacity:0.9",[77,128,130],{"x":129,"y":118,"fill":74,"style":100},"674.0","4200ms",[77,132,136],{"x":79,"y":133,"fill":134,"style":135},"167.0","#51617a","font-size:12.5px","client:visible only hydrates if the user scrolls to the island.",[138,139,141],"h2",{"id":140},"rapid-diagnosis","Rapid Diagnosis",[143,144,145,154,160,166],"ul",{},[146,147,148,153],"li",{},[35,149,150,151],{},"Search for ",[30,152,88],{}," across components and pages; each is an eager island.",[146,155,156,159],{},[35,157,158],{},"Record a load trace"," with CPU throttling; note hydration tasks after load.",[146,161,162,165],{},[35,163,164],{},"List islands above and below the fold"," on key templates.",[146,167,168,171],{},[35,169,170],{},"Check island frameworks",": multiple frameworks mean multiple runtimes.",[138,173,175],{"id":174},"root-cause-analysis","Root Cause Analysis",[15,177,178,181],{},[35,179,180],{},"1. client:load by default."," Developers add it because it \"just works\".",[15,183,184,187],{},[35,185,186],{},"2. Below-the-fold islands hydrating eagerly."," Work for content users may never reach.",[15,189,190,193],{},[35,191,192],{},"3. client:only overuse."," Empty space until JavaScript runs.",[15,195,196,199],{},[35,197,198],{},"4. Heavy islands."," Large dependencies hydrate regardless of directive.",[138,201,203],{"id":202},"step-by-step-resolution","Step-by-Step Resolution",[205,206,208],"h3",{"id":207},"_1-default-to-clientvisible-below-the-fold","1. Default to client:visible below the fold",[210,211,216],"pre",{"className":212,"code":213,"language":214,"meta":215,"style":215},"language-html shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast","\u003CTestimonials client:visible \u002F>\n\u003CPricingCalculator client:visible={{ rootMargin: '200px' }} \u002F>\n\u003C!-- trade-off: a root margin starts hydration slightly before the island is on\n     screen, hiding the delay on normal scrolling at the cost of earlier work. -->\n","html","",[30,217,218,238,266,273],{"__ignoreMap":215},[219,220,223,227,231,235],"span",{"class":221,"line":222},"line",1,[219,224,226],{"class":225},"saISM","\u003C",[219,228,230],{"class":229},"si8lv","Testimonials",[219,232,234],{"class":233},"sPXB4"," client:visible",[219,236,237],{"class":225}," \u002F>\n",[219,239,241,243,246,248,251,255,258,261,264],{"class":221,"line":240},2,[219,242,226],{"class":225},[219,244,245],{"class":229},"PricingCalculator",[219,247,234],{"class":233},[219,249,250],{"class":225},"=",[219,252,254],{"class":253},"sZ8jY","{{",[219,256,257],{"class":233}," rootMargin:",[219,259,260],{"class":229}," '200px'",[219,262,263],{"class":233}," }}",[219,265,237],{"class":225},[219,267,269],{"class":221,"line":268},3,[219,270,272],{"class":271},"sjfSM","\u003C!-- trade-off: a root margin starts hydration slightly before the island is on\n",[219,274,276],{"class":221,"line":275},4,[219,277,278],{"class":271},"     screen, hiding the delay on normal scrolling at the cost of earlier work. -->\n",[205,280,282],{"id":281},"_2-use-clientidle-for-soon-needed-widgets","2. Use client:idle for soon-needed widgets",[15,284,285,286,288],{},"Search boxes in the header, cookie preference panels and chat launchers often work well with ",[30,287,105],{},", hydrating shortly after load without competing with it.",[205,290,292],{"id":291},"_3-reserve-clientload-for-immediate-interactivity","3. Reserve client:load for immediate interactivity",[15,294,295,296,298],{},"Above-the-fold controls that users interact with right away (a primary form, a product configurator at the top) justify ",[30,297,88],{},".",[205,300,302],{"id":301},"_4-use-clientmedia-for-responsive-only-interactivity","4. Use client:media for responsive-only interactivity",[210,304,306],{"className":212,"code":305,"language":214,"meta":215,"style":215},"\u003CMobileMenu client:media=\"(max-width: 768px)\" \u002F>\n\u003C!-- Desktop users never download or hydrate the mobile menu. -->\n",[30,307,308,325],{"__ignoreMap":215},[219,309,310,312,315,318,320,323],{"class":221,"line":222},[219,311,226],{"class":225},[219,313,314],{"class":229},"MobileMenu",[219,316,317],{"class":233}," client:media",[219,319,250],{"class":225},[219,321,322],{"class":253},"\"(max-width: 768px)\"",[219,324,237],{"class":225},[219,326,327],{"class":221,"line":240},[219,328,329],{"class":271},"\u003C!-- Desktop users never download or hydrate the mobile menu. -->\n",[15,331,332],{},[45,333,52,336,52,339,52,342,52,344,52,361,52,364,52,366,52,372,52,379,52,383,52,387,52,391,52,399,52,405,52,409,52,414,52,418,52,422,52,425,52,428,52,431,52,434,52,438,52,441,52,444,52,448,52,451,52,454,52,457,52,460,52,464,52,467,52,470,52,474,52,476,52,478,52,481,52,484,52,488,52,491,52,494,52],{"viewBox":334,"width":48,"role":49,"ariaLabel":335,"style":51},"0 0 760 413","Decision sequence for selecting an Astro client directive for an island.",[54,337],{"className":338,"x":58,"y":58,"width":48,"height":48,"fill":59},[57],[61,340,341],{},"Choosing a client directive",[65,343,335],{},[345,346,347],"defs",{},[348,349,356],"marker",{"id":350,"viewBox":351,"refX":352,"refY":353,"markerWidth":354,"markerHeight":354,"orient":355},"fae3df5151","0 0 10 10","9","5","7","auto-start-reverse",[357,358],"path",{"d":359,"fill":74,"style":360},"M0 0 L10 5 L0 10 z","fill-opacity:0.7",[54,362],{"x":69,"y":69,"width":70,"height":363,"rx":72,"fill":73,"stroke":74,"style":75},"411",[77,365,341],{"x":79,"y":80,"fill":74,"style":81},[54,367],{"x":79,"y":92,"width":368,"height":369,"rx":370,"fill":74,"stroke":74,"style":371},"320.0","52.0","6","fill-opacity:0.06;stroke-opacity:0.4",[77,373,378],{"x":374,"y":375,"fill":74,"style":376,"textAnchor":377},"188.0","78.0","font-size:13px;font-weight:700","middle","Does it need to be interactive immediately, above",[77,380,382],{"x":374,"y":381,"fill":74,"style":376,"textAnchor":377},"95.0","the fold?",[54,384],{"x":385,"y":92,"width":368,"height":369,"rx":370,"fill":73,"stroke":74,"style":386},"412.0","stroke-opacity:0.35",[77,388,88],{"x":389,"y":390,"fill":74,"style":135,"textAnchor":377},"572.0","86.5",[221,392],{"x1":393,"y1":394,"x2":395,"y2":394,"stroke":74,"strokeWidth":396,"style":397,"markerEnd":398},"348.0","82.0","410.0","1.5","stroke-opacity:0.6","url(#fae3df5151)",[77,400,404],{"x":401,"y":402,"fill":110,"style":403,"textAnchor":377},"380.0","75.0","font-size:11.5px;font-weight:700","yes",[221,406],{"x1":374,"y1":407,"x2":374,"y2":408,"stroke":74,"strokeWidth":396,"style":397,"markerEnd":398},"108.0","142.0",[77,410,413],{"x":411,"y":412,"fill":134,"style":403},"196.0","130.0","no",[54,415],{"x":79,"y":416,"width":368,"height":417,"rx":370,"fill":74,"stroke":74,"style":371},"144.0","35.0",[77,419,421],{"x":374,"y":420,"fill":74,"style":376,"textAnchor":377},"166.0","Is it only interactive at some screen sizes?",[54,423],{"x":385,"y":416,"width":368,"height":417,"rx":370,"fill":110,"stroke":110,"style":424},"fill-opacity:0.14;stroke-opacity:0.9",[77,426,427],{"x":389,"y":420,"fill":74,"style":135,"textAnchor":377},"client:media",[221,429],{"x1":393,"y1":430,"x2":395,"y2":430,"stroke":74,"strokeWidth":396,"style":397,"markerEnd":398},"161.5",[77,432,404],{"x":401,"y":433,"fill":110,"style":403,"textAnchor":377},"154.5",[221,435],{"x1":374,"y1":436,"x2":374,"y2":437,"stroke":74,"strokeWidth":396,"style":397,"markerEnd":398},"179.0","213.0",[77,439,413],{"x":411,"y":440,"fill":134,"style":403},"201.0",[54,442],{"x":79,"y":443,"width":368,"height":417,"rx":370,"fill":74,"stroke":74,"style":371},"215.0",[77,445,447],{"x":374,"y":446,"fill":74,"style":376,"textAnchor":377},"237.0","Is it below the fold?",[54,449],{"x":385,"y":443,"width":368,"height":417,"rx":370,"fill":124,"stroke":125,"style":450},"fill-opacity:0.24;stroke-opacity:0.9",[77,452,453],{"x":389,"y":446,"fill":74,"style":135,"textAnchor":377},"client:visible",[221,455],{"x1":393,"y1":456,"x2":395,"y2":456,"stroke":74,"strokeWidth":396,"style":397,"markerEnd":398},"232.5",[77,458,404],{"x":401,"y":459,"fill":110,"style":403,"textAnchor":377},"225.5",[221,461],{"x1":374,"y1":462,"x2":374,"y2":463,"stroke":74,"strokeWidth":396,"style":397,"markerEnd":398},"250.0","284.0",[77,465,413],{"x":411,"y":466,"fill":134,"style":403},"272.0",[54,468],{"x":79,"y":469,"width":368,"height":417,"rx":370,"fill":74,"stroke":74,"style":371},"286.0",[77,471,473],{"x":374,"y":472,"fill":74,"style":376,"textAnchor":377},"308.0","Is it needed soon but not instantly?",[54,475],{"x":385,"y":469,"width":368,"height":417,"rx":370,"fill":110,"stroke":110,"style":424},[77,477,105],{"x":389,"y":472,"fill":74,"style":135,"textAnchor":377},[221,479],{"x1":393,"y1":480,"x2":395,"y2":480,"stroke":74,"strokeWidth":396,"style":397,"markerEnd":398},"303.5",[77,482,404],{"x":401,"y":483,"fill":110,"style":403,"textAnchor":377},"296.5",[221,485],{"x1":374,"y1":486,"x2":374,"y2":487,"stroke":74,"strokeWidth":396,"style":397,"markerEnd":398},"321.0","355.0",[77,489,413],{"x":411,"y":490,"fill":134,"style":403},"343.0",[54,492],{"x":79,"y":493,"width":368,"height":80,"rx":370,"fill":124,"stroke":125,"style":450},"357.0",[77,495,497],{"x":374,"y":496,"fill":74,"style":135,"textAnchor":377},"378.5","No directive — render as static HTML",[138,499,501],{"id":500},"verification","Verification",[15,503,504],{},"Record a load trace after changes: hydration tasks at load should shrink to only the eager islands. Scroll through the page and confirm islands hydrate and work before users interact. In the field, compare TBT-related metrics and early INP.",[138,506,508],{"id":507},"worked-example-a-developer-blog","Worked Example: A Developer Blog",[15,510,511,512,514,515,517,518,520,521,523],{},"A developer blog built in Astro used ",[30,513,88],{}," for five islands on every post: a theme toggle, a table of contents with scroll spy, a code copy button, a newsletter form and a comments widget (React with a heavy markdown dependency). Posts shipped 160KB of JavaScript, all hydrating at load; INP p75 was 210ms. The team replaced the theme toggle and copy buttons with small vanilla scripts (no framework), set the table of contents to ",[30,516,105],{},", the newsletter form to ",[30,519,453],{},", and the comments widget to ",[30,522,453],{}," with a \"load comments\" button. JavaScript at load dropped to 9KB, and INP p75 to 70ms.",[138,525,527],{"id":526},"when-not-to-use-an-island-at-all","When Not to Use an Island at All",[15,529,530,531,534,535,538,539,542],{},"Many interactive behaviours do not need a framework component. Copy-to-clipboard buttons, theme toggles, disclosure widgets (use ",[30,532,533],{},"details","\u002F",[30,536,537],{},"summary","), simple tabs and image lightboxes can be implemented with a few lines of vanilla JavaScript in an Astro ",[30,540,541],{},"\u003Cscript>"," tag, which Astro bundles and deduplicates. They are smaller than any framework runtime and run without hydration. Reserve islands for genuinely stateful UI.",[210,544,546],{"className":212,"code":545,"language":214,"meta":215,"style":215},"\u003Cbutton class=\"copy\" data-code=\"npm install astro\">Copy\u003C\u002Fbutton>\n\u003Cscript>\n  document.querySelectorAll('button.copy').forEach((b) =>\n    b.addEventListener('click', () => navigator.clipboard.writeText(b.dataset.code)));\n\u003C\u002Fscript>\n\u003C!-- trade-off: vanilla scripts lack component state management; fine for simple\n     behaviours, but complex UI is clearer as an island. -->\n",[30,547,548,580,589,624,652,662,668],{"__ignoreMap":215},[219,549,550,552,556,559,561,564,567,569,572,575,577],{"class":221,"line":222},[219,551,226],{"class":225},[219,553,555],{"class":554},"sZBmE","button",[219,557,558],{"class":233}," class",[219,560,250],{"class":225},[219,562,563],{"class":253},"\"copy\"",[219,565,566],{"class":233}," data-code",[219,568,250],{"class":225},[219,570,571],{"class":253},"\"npm install astro\"",[219,573,574],{"class":225},">Copy\u003C\u002F",[219,576,555],{"class":554},[219,578,579],{"class":225},">\n",[219,581,582,584,587],{"class":221,"line":240},[219,583,226],{"class":225},[219,585,586],{"class":554},"script",[219,588,579],{"class":225},[219,590,591,594,598,601,604,607,610,613,617,620],{"class":221,"line":268},[219,592,593],{"class":225},"  document.",[219,595,597],{"class":596},"smZ65","querySelectorAll",[219,599,600],{"class":225},"(",[219,602,603],{"class":253},"'button.copy'",[219,605,606],{"class":225},").",[219,608,609],{"class":596},"forEach",[219,611,612],{"class":225},"((",[219,614,616],{"class":615},"sQw3B","b",[219,618,619],{"class":225},") ",[219,621,623],{"class":622},"sPARh","=>\n",[219,625,626,629,632,634,637,640,643,646,649],{"class":221,"line":275},[219,627,628],{"class":225},"    b.",[219,630,631],{"class":596},"addEventListener",[219,633,600],{"class":225},[219,635,636],{"class":253},"'click'",[219,638,639],{"class":225},", () ",[219,641,642],{"class":622},"=>",[219,644,645],{"class":225}," navigator.clipboard.",[219,647,648],{"class":596},"writeText",[219,650,651],{"class":225},"(b.dataset.code)));\n",[219,653,655,658,660],{"class":221,"line":654},5,[219,656,657],{"class":225},"\u003C\u002F",[219,659,586],{"class":554},[219,661,579],{"class":225},[219,663,665],{"class":221,"line":664},6,[219,666,667],{"class":271},"\u003C!-- trade-off: vanilla scripts lack component state management; fine for simple\n",[219,669,671],{"class":221,"line":670},7,[219,672,673],{"class":271},"     behaviours, but complex UI is clearer as an island. -->\n",[15,675,676],{},[45,677,52,680,52,683,52,686,52,688,52,691,52,693,52,697,52,701,52,704,52,707,52,710,52,714,52,717,52,720,52],{"viewBox":678,"width":48,"role":49,"ariaLabel":679,"style":51},"0 0 760 163","Bar chart of JavaScript loaded at page load for a blog post before and after changing directives and replacing simple islands.",[54,681],{"className":682,"x":58,"y":58,"width":48,"height":48,"fill":59},[57],[61,684,685],{},"JavaScript at load on blog posts",[65,687,679],{},[54,689],{"x":69,"y":69,"width":70,"height":690,"rx":72,"fill":73,"stroke":74,"style":75},"161",[77,692,685],{"x":79,"y":80,"fill":74,"style":81},[77,694,696],{"x":695,"y":85,"fill":74,"style":86,"textAnchor":87},"196.2","5 islands with client:load",[54,698],{"x":699,"y":92,"width":700,"height":94,"rx":95,"fill":73,"stroke":74,"style":96},"208.2","459.8",[77,702,703],{"x":129,"y":85,"fill":74,"style":100},"160KB",[77,705,706],{"x":695,"y":104,"fill":74,"style":86,"textAnchor":87},"Directives changed",[54,708],{"x":699,"y":108,"width":709,"height":94,"rx":95,"fill":110,"stroke":110,"style":111},"120.7",[77,711,713],{"x":712,"y":104,"fill":74,"style":100},"334.9","42KB",[77,715,716],{"x":695,"y":118,"fill":74,"style":86,"textAnchor":87},"+ vanilla scripts for simple UI",[54,718],{"x":699,"y":122,"width":719,"height":94,"rx":95,"fill":124,"stroke":125,"style":126},"25.9",[77,721,723],{"x":722,"y":118,"fill":74,"style":100},"240.1","9KB",[138,725,727],{"id":726},"auditing-islands-on-an-existing-site","Auditing Islands on an Existing Site",[15,729,730,731,734,735,737],{},"On an existing Astro site, list every island with its directive and framework, page by page. A quick search for ",[30,732,733],{},"client:"," in the source gives the list; the build output and the Network panel show the chunk each island loads. For each island, ask three questions: does it need to be interactive at all (or could it be static HTML or a small script), when does the user first need it, and how large is its code including dependencies? Changing directives is usually a one-line edit per island, so an audit like this can cut JavaScript at load dramatically in an afternoon. Re-run it periodically, since new islands tend to arrive with ",[30,736,88],{}," copied from examples.",[138,739,741],{"id":740},"measuring-the-effect-of-directive-changes","Measuring the Effect of Directive Changes",[15,743,744,745,747,748,298],{},"Compare a throttled lab trace of the page before and after: the hydration work at load should shrink, and later hydration tasks should appear only when islands become visible or the browser is idle. In the field, INP for early interactions and TBT-related signals should improve. Also check that the islands still respond promptly when users reach them; if interactions immediately after scrolling feel delayed, add a root margin to ",[30,746,453],{}," or switch that island to ",[30,749,105],{},[138,751,753],{"id":752},"common-mistakes","Common Mistakes",[143,755,756,762,768,774],{},[146,757,758,761],{},[35,759,760],{},"client:load on everything."," Defeats the islands model.",[146,763,764,767],{},[35,765,766],{},"client:only for content."," Empty space and slower content; CLS risk.",[146,769,770,773],{},[35,771,772],{},"Frameworks for trivial behaviour."," Shipping a runtime for a copy button.",[146,775,776,779],{},[35,777,778],{},"Ignoring dependency size."," A visible-hydrated island with a 200KB dependency still costs 200KB when scrolled to.",[138,781,783],{"id":782},"edge-cases","Edge Cases",[15,785,786,789,790,792,793,795],{},[35,787,788],{},"Interactions before hydration."," A ",[30,791,453],{}," island that users interact with very quickly may not be ready; use ",[30,794,105],{}," or a root margin.",[15,797,798,801],{},[35,799,800],{},"Shared state between islands."," Islands are independent; share state with lightweight stores (such as nanostores) rather than a framework context.",[15,803,804,807,808,298],{},[35,805,806],{},"View transitions."," With Astro's client router, islands can persist across navigations using ",[30,809,810],{},"transition:persist",[15,812,813,816,817,820],{},[35,814,815],{},"Server islands."," Astro's ",[30,818,819],{},"server:defer"," renders slow, personalised server components after the main page, which complements client directives.",[138,822,824],{"id":823},"faq","FAQ",[533,826,829,832],{"className":827},[828],"faq-item",[537,830,831],{},"What is the default if I omit a client directive?",[15,833,834],{},"The component renders to static HTML on the server and ships no JavaScript.",[533,836,838,841],{"className":837},[828],[537,839,840],{},"When should I use client:only?",[15,842,843],{},"Only for components that cannot render on the server, such as those relying on browser APIs during render. Reserve space to avoid layout shifts.",[533,845,847,850],{"className":846},[828],[537,848,849],{},"Does client:visible hurt usability?",[15,851,852],{},"Rarely, if hydration starts slightly before the island appears. Use a root margin for islands users interact with immediately after scrolling.",[533,854,856,859],{"className":855},[828],[537,857,858],{},"Is client:idle reliable on slow devices?",[15,860,861,862,864],{},"It waits for the browser to be idle, which can take longer on busy pages. Use a timeout or ",[30,863,453],{}," for important widgets.",[533,866,868,871],{"className":867},[828],[537,869,870],{},"Can I pass large data to islands?",[15,872,873],{},"Props are serialised into the HTML. Pass small data or IDs, and fetch the rest in the island when it hydrates.",[533,875,877,880],{"className":876},[828],[537,878,879],{},"Do islands share a framework runtime?",[15,881,882],{},"Islands of the same framework on a page share the runtime chunk. Different frameworks each load their own.",[533,884,886,889],{"className":885},[828],[537,887,888],{},"How many islands is too many?",[15,890,891],{},"There is no fixed limit; what matters is how much JavaScript hydrates at load. Many small, lazily hydrated islands are fine.",[533,893,895,898],{"className":894},[828],[537,896,897],{},"What are server islands?",[15,899,900,901,903],{},"Components rendered on the server after the main page using ",[30,902,819],{},", letting cached static pages include slower, personalised parts.",[533,905,907,910],{"className":906},[828],[537,908,909],{},"Can I change a directive conditionally?",[15,911,912,913,915],{},"Directives are static in the template, but you can render different components or pass a prop to choose behaviour; for responsive cases, ",[30,914,427],{}," covers most needs.",[533,917,919,922],{"className":918},[828],[537,920,921],{},"Do directives affect server rendering?",[15,923,924,925,928],{},"No, except ",[30,926,927],{},"client:only",". All other directives server-render the island's HTML; they only control when JavaScript loads.",[138,930,932],{"id":931},"related","Related",[143,934,935,941,948],{},[146,936,937,940],{},[19,938,939],{"href":21},"Astro & SvelteKit performance"," — the topic overview.",[146,942,943,947],{},[19,944,946],{"href":945},"\u002Fframework-performance\u002Fvue-and-nuxt-performance\u002Flazy-hydration-in-nuxt\u002F","Lazy hydration in Nuxt"," — the same idea in Nuxt.",[146,949,950,954],{},[19,951,953],{"href":952},"\u002Fframework-performance\u002Fastro-and-sveltekit-performance\u002Fastro-vs-nextjs-for-content-site-performance\u002F","Astro vs Next.js for content-site performance"," — framework choice.",[586,956,958],{"type":957},"application\u002Fld+json","\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"HowTo\",\n  \"name\": \"How to Choose Astro Client Directives\",\n  \"description\": \"A practical guide to Astro's client directives — what each does, when to use it, and how the choice affects TBT, INP and user experience.\",\n  \"step\": [\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 1,\n      \"name\": \"Default to client:visible below the fold\",\n      \"text\": \"Default to client:visible below the fold\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 2,\n      \"name\": \"Use client:idle for soon-needed widgets\",\n      \"text\": \"Search boxes in the header, cookie preference panels and chat launchers often work well with client:idle, hydrating shortly after load without competing with it.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 3,\n      \"name\": \"Reserve client:load for immediate interactivity\",\n      \"text\": \"Above-the-fold controls that users interact with right away (a primary form, a product configurator at the top) justify client:load.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 4,\n      \"name\": \"Use client:media for responsive-only interactivity\",\n      \"text\": \"Use client:media for responsive-only interactivity\"\n    }\n  ]\n}\n",[586,960,961],{"type":957},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"TechArticle\",\n  \"headline\": \"How to Choose Astro Client Directives\",\n  \"description\": \"A practical guide to Astro's client directives — what each does, when to use it, and how the choice affects TBT, INP and user experience.\",\n  \"datePublished\": \"2026-10-06\",\n  \"dateModified\": \"2026-10-06\",\n  \"author\": {\n    \"@type\": \"Organization\",\n    \"name\": \"frontend-performance.com\"\n  },\n  \"publisher\": {\n    \"@type\": \"Organization\",\n    \"name\": \"frontend-performance.com\"\n  },\n  \"mainEntityOfPage\": {\n    \"@type\": \"WebPage\",\n    \"@id\": \"https:\u002F\u002Ffrontend-performance.com\u002Fframework-performance\u002Fastro-and-sveltekit-performance\u002Fchoosing-astro-client-directives\u002F\"\n  }\n}\n",[586,963,964],{"type":957},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"BreadcrumbList\",\n  \"itemListElement\": [\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 1,\n      \"name\": \"Home\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 2,\n      \"name\": \"Framework Performance\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fframework-performance\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 3,\n      \"name\": \"Astro & SvelteKit Performance\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fframework-performance\u002Fastro-and-sveltekit-performance\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 4,\n      \"name\": \"Choosing Astro Client Directives\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fframework-performance\u002Fastro-and-sveltekit-performance\u002Fchoosing-astro-client-directives\u002F\"\n    }\n  ]\n}\n",[966,967,968],"style",{},"html pre.shiki code .saISM, html code.shiki .saISM{--shiki-default:#0E1116;--shiki-dark:#F0F3F6;--shiki-light:#0E1116}html pre.shiki code .si8lv, html code.shiki .si8lv{--shiki-default:#6E011A;--shiki-default-font-style:italic;--shiki-dark:#FFB1AF;--shiki-dark-font-style:italic;--shiki-light:#6E011A;--shiki-light-font-style:italic}html pre.shiki code .sPXB4, html code.shiki .sPXB4{--shiki-default:#023B95;--shiki-dark:#91CBFF;--shiki-light:#023B95}html pre.shiki code .sZ8jY, html code.shiki .sZ8jY{--shiki-default:#032563;--shiki-dark:#ADDCFF;--shiki-light:#032563}html pre.shiki code .sjfSM, html code.shiki .sjfSM{--shiki-default:#66707B;--shiki-dark:#BDC4CC;--shiki-light:#66707B}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html pre.shiki code .sZBmE, html code.shiki .sZBmE{--shiki-default:#024C1A;--shiki-dark:#72F088;--shiki-light:#024C1A}html pre.shiki code .smZ65, html code.shiki .smZ65{--shiki-default:#622CBC;--shiki-dark:#DBB7FF;--shiki-light:#622CBC}html pre.shiki code .sQw3B, html code.shiki .sQw3B{--shiki-default:#702C00;--shiki-dark:#FFB757;--shiki-light:#702C00}html pre.shiki code .sPARh, html code.shiki .sPARh{--shiki-default:#A0111F;--shiki-dark:#FF9492;--shiki-light:#A0111F}",{"title":215,"searchDepth":240,"depth":240,"links":970},[971,972,973,979,980,981,982,983,984,985,986,987],{"id":140,"depth":240,"text":141},{"id":174,"depth":240,"text":175},{"id":202,"depth":240,"text":203,"children":974},[975,976,977,978],{"id":207,"depth":268,"text":208},{"id":281,"depth":268,"text":282},{"id":291,"depth":268,"text":292},{"id":301,"depth":268,"text":302},{"id":500,"depth":240,"text":501},{"id":507,"depth":240,"text":508},{"id":526,"depth":240,"text":527},{"id":726,"depth":240,"text":727},{"id":740,"depth":240,"text":741},{"id":752,"depth":240,"text":753},{"id":782,"depth":240,"text":783},{"id":823,"depth":240,"text":824},{"id":931,"depth":240,"text":932},"A practical guide to Astro's client directives — what each does, when to use it, and how the choice affects TBT, INP and user experience.","md",{"slug":991,"type":992,"breadcrumb":993,"datePublished":1000,"dateModified":1000},"choosing-astro-client-directives","article",[994,996,997,998],{"name":995,"url":534},"Home",{"name":27,"url":26},{"name":22,"url":21},{"name":5,"url":999},"\u002Fframework-performance\u002Fastro-and-sveltekit-performance\u002Fchoosing-astro-client-directives\u002F","2026-10-06",true,"\u002Fframework-performance\u002Fastro-and-sveltekit-performance\u002Fchoosing-astro-client-directives",{"title":1004,"description":1005},"Choosing Astro Client Directives for Faster Islands","Pick client:load, client:idle, client:visible, client:media or client:only for each Astro island to minimise JavaScript work at load without breaking interactivity.","framework-performance\u002Fastro-and-sveltekit-performance\u002Fchoosing-astro-client-directives\u002Findex","Lx1ipfZXUuKs4qqj_jwlIzgVVXdRU8WX1IaNowV-zso",[1009,1013],{"title":1010,"path":1011,"stem":1012},"Astro vs Next.js for Content-Site Performance","\u002Fframework-performance\u002Fastro-and-sveltekit-performance\u002Fastro-vs-nextjs-for-content-site-performance","framework-performance\u002Fastro-and-sveltekit-performance\u002Fastro-vs-nextjs-for-content-site-performance\u002Findex",{"title":1014,"path":1015,"stem":1016},"SvelteKit Preloading and Load Functions","\u002Fframework-performance\u002Fastro-and-sveltekit-performance\u002Fsveltekit-preloading-and-load-functions","framework-performance\u002Fastro-and-sveltekit-performance\u002Fsveltekit-preloading-and-load-functions\u002Findex",1791308078953]