Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 3

Svelte 5 Component Fundamentals

Recommended resources

Hello! In our last session, we set up your SvelteKit project and integrated TailwindCSS, creating the perfect foundation for us to start building. You now have a blank canvas and the styling tools ready to go.

Today, we'll begin painting on that canvas. This lesson is all about understanding the fundamental building block of any Svelte application: the component. We're going to build your first Svelte 5 component from scratch, focusing on its three core parts: the markup for structure, the script for logic, and the style for appearance. Coming from a React background, you'll find some concepts familiar, but Svelte's approach of combining these elements into a single, intuitive file might feel like a refreshing change from JSX.

By the end of this lesson, you'll have created and rendered your first reusable UI element, grasping the elegant and powerful structure of a .svelte file.

The Anatomy of a Svelte Component

At its heart, a Svelte component is a single file with a .svelte extension that encapsulates everything needed to render a piece of your user interface. It neatly organizes HTML, JavaScript, and CSS together.

A Svelte component is created by combining JavaScript for logic, HTML for structure, and CSS for styling, all within a single `.svelte` file.

These three sections work in harmony but have distinct roles. A great way to get a quick overview of this structure is by reading a short section from a Contentful tutorial on Svelte.

Svelte tutorial: Building an app using Svelte 5 | Contentful

This article provides a clear breakdown of the three main sections of a Svelte component.

Please read the section titled Svelte component structure. Pay close attention to the descriptions of the <script> tag, the HTML section, and the <style> tag.

As the article highlights, this single-file approach has a major advantage: styles are scoped by default. This means the CSS you write in one component won't accidentally leak out and affect others, a common source of bugs in large applications.


Let's Build: Your First Component

Theory is useful, but as you've emphasized, practice is key. Let's build a simple ProfileCard component.

First, create a new folder inside src/lib called components. It's a common convention to organize reusable components here. Inside src/lib/components/, create a new file named ProfileCard.svelte.

1. The Markup (HTML)

Start by adding the basic structure for our card directly into ProfileCard.svelte. This is just plain HTML.

<div>
  <img src="https://i.pravatar.cc/150" alt="A random user avatar" />
  <h2>User Name</h2>
  <p>This is a short bio about the user. They are interested in learning new technologies and building cool things.</p>
</div>

2. The Script (JavaScript)

Now, let's make this component's content dynamic. Add a <script> block at the top of your ProfileCard.svelte file. Inside, we'll define some variables. This is standard JavaScript.

<script>
  let name = 'Alex Doe';
  let bio = 'Svelte enthusiast and future app developer. Enjoys clean code and fast websites.';
  let avatarUrl = 'https://i.pravatar.cc/150?u=alexdoe';
</script>

Next, use these variables in your markup. Svelte uses curly braces {} to embed JavaScript expressions in HTML, a syntax that should feel very familiar from your time with JSX.

Update your markup section to look like this:

<div>
  <img src={avatarUrl} alt="User avatar" />
  <h2>{name}</h2>
  <p>{bio}</p>
</div>

3. The Style (Scoped CSS)

Our card is functional but plain. Let's add some style. Add a <style> block at the bottom of ProfileCard.svelte. The styles you add here will only apply to the markup within this file.

<style>
  div {
    border: 1px solid #e2e8f0;
    border-radius: 8px;
    padding: 1.5rem;
    max-width: 320px;
    text-align: center;
    box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
  }

  img {
    border-radius: 50%;
    width: 100px;
    height: 100px;
    margin-bottom: 1rem;
  }

  h2 {
    font-size: 1.25rem;
    font-weight: 600;
    margin-bottom: 0.5rem;
  }
</style>

Your complete ProfileCard.svelte file should now look like this:

<script>
  let name = 'Alex Doe';
  let bio = 'Svelte enthusiast and future app developer. Enjoys clean code and fast websites.';
  let avatarUrl = 'https://i.pravatar.cc/150?u=alexdoe';
</script>

<div>
  <img src={avatarUrl} alt="User avatar" />
  <h2>{name}</h2>
  <p>{bio}</p>
</div>

<style>
  div {
    border: 1px solid #e2e8f0;
    border-radius: 8px;
    padding: 1.5rem;
    max-width: 320px;
    text-align: center;
    box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
  }

  img {
    border-radius: 50%;
    width: 100px;
    height: 100px;
    margin-bottom: 1rem;
  }

  h2 {
    font-size: 1.25rem;
    font-weight: 600;
    margin-bottom: 0.5rem;
  }
</style>

To understand exactly how Svelte scopes these styles, the following video provides an excellent explanation. It shows that the compiler adds unique classes to your elements behind the scenes.

Svelte 5 Basics - Complete Svelte 5 Course for Beginners

Watch this segment to see a demonstration of how Svelte's scoped styling works and prevents CSS from "leaking."

Focus on the explanation starting from scoped CSS, where the presenter demonstrates that styles are confined to the component. Then, watch the part where he reveals how it works by inspecting the compiled output.


Using Your Component

You've built a component, but it's not visible anywhere yet. Let's render it on our main page.

Open src/routes/+page.svelte. This is the main page of your application.

  1. Clear the existing content.
  2. Add a <script> block to import your new component. We use the $lib alias, a SvelteKit feature that points to the src/lib directory.
  3. Render the component in the markup, just like a custom HTML element. The convention is to use a PascalCase name.

Your +page.svelte file should now look like this:

<script>
  import ProfileCard from '$lib/components/ProfileCard.svelte';
</script>

<h1>Welcome to My Svelte App</h1>
<ProfileCard />

If you run npm run dev and open your browser, you should see your ProfileCard component rendered on the page! The process of importing and using a component is demonstrated well in the first part of the Syntax video we looked at. Feel free to watch it if you want to see this flow in action again.


Conclusion

Congratulations! You've just built your first Svelte 5 component. You've seen how a single .svelte file can elegantly combine structure (HTML), logic (JavaScript), and presentation (CSS) into a cohesive, reusable unit.

Key Takeaways:

  • A Svelte component is a .svelte file containing <script>, markup, and <style> sections.
  • JavaScript variables are embedded in HTML using {curly_braces}, similar to JSX.
  • CSS within a component's <style> tag is scoped by default, preventing style conflicts between components.
  • Components are imported into other files and rendered using an HTML-like tag.

Our profile card is functional, but we wrote our own CSS. In the next lesson, we will put the TailwindCSS setup from our previous lesson to work, replacing our manual styles with powerful utility classes to achieve the same—and even better—results much faster.