DEV Community

Cover image for Build your interface in Astro: Components 🧩
Domenico Tenace
Domenico Tenace

Posted on • Originally published at domenicotenace.dev

Build your interface in Astro: Components 🧩

Overview

Every frontend framework is based on the concept of Components: Vue, Angular, React use this powerful feature to build complete applications.
Astro is no exception, and in this article we will see what Components is and how to use it in an Astro project.
Let's start! πŸ€™


What are Astro Components?

Astro Components are reusable pieces of code and they are HTML-only templating components with no client-side runtime.
The extension of these files is .astro.
Astro components are extremely flexible because you can use them in different ways:

  • It can contain some reusable UI on the page like footer or navbar.
  • It may contain a collection of common <meta> tags that make SEO easy to work with.
  • It can even contain an entire page layout.

It is important to know that Astro Components do not render on the client, it's possible include JavaScript code inside of your component frontmatter, and all of it will be stripped from the final page sent to your use's browsers.

The Structure

An Astro Component is made up of two main parts: script and the template.

---
// Component Script (JavaScript or Typescript code)
---
<!-- Component Template (HTML + JS Expressions) -->
Enter fullscreen mode Exit fullscreen mode

You can use the script to write any JavaScript code that you need to render your template, for example:

  • importing other Astro components
  • importing other framework components, like Vue
  • importing data, like a JSON file
  • fetching content from an API or database

import SomeAstroComponent from '../components/SomeAstroComponent.astro';
import SomeReactComponent from '../components/SomeVueComponent.vue';
import someData from '../data/data.json';

const { title } = Astro.props;

const data = await fetch('example/posts').then(r => r.json());
Enter fullscreen mode Exit fullscreen mode

This approach is highly secure because at build time, the JavaScript code will not end up in the end user's browser.

Instead the template determines the HTML output of your component: if you write plain HTML here, your component will render that HTML in any Astro page it is imported and used.
Astro’s component template syntax also supports JavaScript expressions, <style> and <script> tags, imported components, and special Astro directives.
Data and values defined in the component script can be used in the component template to produce dynamically-created HTML, like Vue or React.

---
// Your component script here!
import Banner from '../components/Banner.astro';
import VueCardComponent from '../components/VueCardComponent.vue';
const myFavoriteFruits = [/* ... */];
const { title } = Astro.props;
---

<Banner />
<h1>Hello, Astro!</h1>

 <p>{title}</p>

<VueCardComponent client:visible />

<ul>
  {myFavoriteFruits.map((data) => <li>{data.name}</li>)}
</ul>

<p class:list={["add", "dynamic", {classNames: true}]} />
Enter fullscreen mode Exit fullscreen mode

Props

An Astro component can define and accept props. These props then become available to the component template for rendering HTML. Props are available on the Astro.props global in your script.

Declaration:

---
 const { greeting, name } = Astro.props;
---
<h2>{greeting}, {name}!</h2>
Enter fullscreen mode Exit fullscreen mode

Usage:

<GreetingHeadline greeting="Hello" name="World" />
Enter fullscreen mode Exit fullscreen mode

It's possible define your props with TypeScript with a Props type interface. Astro will automatically pick up the Props interface in your frontmatter and give type warnings/errors.

---
interface Props {
  name: string;
  greeting?: string;
}

const { greeting = "Hello", name } = Astro.props;
---
<h2>{greeting}, {name}!</h2>
Enter fullscreen mode Exit fullscreen mode

Slots

The <slot /> element is a placeholder for external HTML content, allowing you to inject child elements from other files into your component template.

By default, all child elements passed to a component will be rendered in its <slot />.
For example:

---
import Header from './Header.astro';
import Logo from './Logo.astro';
import Footer from './Footer.astro';

const { title } = Astro.props;
---
<div id="content-wrapper">
  <Header />
  <Logo />
  <h1>{title}</h1>
  <slot />  
  <Footer />
</div>

Enter fullscreen mode Exit fullscreen mode
---
import Wrapper from '../components/Wrapper.astro';
---
<Wrapper title="John's Page">
  <h2>All about John</h2>
  <p>Here is some stuff about John.</p>
</Wrapper>
Enter fullscreen mode Exit fullscreen mode

Named Slots

An Astro component can also have named slots. This allows you to pass only HTML elements with the corresponding slot name so you can place different elements in as many places.

---
import Header from './Header.astro';
import Logo from './Logo.astro';
import Footer from './Footer.astro';

const { title } = Astro.props;
---
<div id="content-wrapper">
  <Header />
  <slot name="after-header" />  
  <Logo />
  <h1>{title}</h1>
  <slot /> 
  <Footer />
  <slot name="after-footer" />
</div>
Enter fullscreen mode Exit fullscreen mode

To inject HTML content into a particular slot, use the slot attribute on any child element to specify the name of the slot, in this way:

---
import Wrapper from '../components/Wrapper.astro';
---
<Wrapper title="Fred's Page">
  <img src="https://myphoto/john.jpg" slot="after-header" />
  <h2>All about John</h2>
  <p>Here is some stuff about John.</p>
  <p slot="after-footer">Copyright 2024</p>
</Wrapper>
Enter fullscreen mode Exit fullscreen mode

HTML Components, it's possible

Astro supports importing and using .html files as components. You may want to use HTML components if you’re reusing code from an existing site built without a framework, or if you want to ensure that your component has no dynamic features.

HTML components must contain only valid HTML, and therefore lack key Astro component features:

  • They don’t support frontmatter, server-side imports, or dynamic expressions.
  • Any <script> tags are left unbundled, treated as if they had is:inline.
  • They can only reference assets that are in the public/ folder.

Conclusion

Astro Components are fundamental for build your UI. Their encapsulation of functionality, reusability, and ease of integration make them a powerful tool for building scalable and maintainable website.
Happy coding!✨


HiπŸ‘‹πŸ»
My name is Domenico, software developer passionate of Vue.js framework, I write article about it for share my knowledge and experience.
Don't forget to visit my Linktree to discover my projects 🫰🏻

Linktree: https://linktr.ee/domenicotenace

Follow me on dev.to for other articles πŸ‘‡πŸ»

Top comments (0)