Dynamic HTML and Expressions
Using JavaScript expressions, loops, and conditionals inside an Astro template.
អាន 2 នាទី
Astro templates look like HTML, but curly braces let you drop into JavaScript anywhere a value is expected — much like JSX. This lesson covers the patterns you'll use constantly: interpolating values, looping over data, and rendering conditionally.
Interpolating values
Any variable or expression from the frontmatter can be embedded directly in the template:
---
const name = "Astro";
const version = 5;
---
<h1>Learning {name} {version}</h1>
<p>Two plus two is {2 + 2}.</p>Curly braces accept any expression — a value, a function call, arithmetic — but not statements like if or for. That constraint shapes the patterns below.
Looping with .map()
Since a for loop can't sit directly in a template, iteration uses array methods, exactly like JSX:
---
const languages = ["HTML", "CSS", "JavaScript", "Astro"];
---
<ul>
{languages.map((lang) => (
<li>{lang}</li>
))}
</ul>For arrays of objects, destructure inside the callback to keep things readable:
---
const posts = [
{ slug: "first-post", title: "My First Post" },
{ slug: "second-post", title: "Getting the Hang of It" },
];
---
<ul>
{posts.map(({ slug, title }) => (
<li><a href={`/blog/${slug}`}>{title}</a></li>
))}
</ul>Conditional rendering
Without if statements available inline, conditionals lean on the && operator and ternaries:
---
const isLoggedIn = true;
const cartCount = 0;
---
{isLoggedIn && <p>Welcome back!</p>}
{cartCount > 0 ? (
<p>You have {cartCount} items in your cart.</p>
) : (
<p>Your cart is empty.</p>
)}&& renders its right side only when the left side is truthy — nothing is rendered otherwise. Be careful with numbers here: {cartCount && <p>...</p>} would render a literal 0 on the page when cartCount is 0, since 0 is falsy but still a value React/Astro will print. The ternary avoids that pitfall and is usually the safer default for anything beyond a simple boolean check.
If a condition is more involved than a template can express cleanly, computing it in the frontmatter and referencing a single variable keeps the markup readable:
---
const hour = new Date().getHours();
const greeting = hour < 12 ? "Good morning" : hour < 18 ? "Good afternoon" : "Good evening";
---
<h1>{greeting}!</h1>Setting attributes dynamically
Curly braces work in attribute position too, and Astro drops boolean attributes automatically when the value is falsy:
---
const imageUrl = "/hero.jpg";
const isDisabled = false;
---
<img src={imageUrl} alt="Hero banner" />
<button disabled={isDisabled}>Submit</button>Because all of this — the loop, the conditional, the attribute — resolves to static HTML during rendering, none of the JavaScript that produced it is present in the page Astro sends to the browser. The visitor gets the result of the computation, not the code that computed it.