Skip to content

Single-File Components

In React a “component” is a JavaScript file containing a function that returns JSX, usually paired with a separate CSS file or CSS-in-JS setup. In Svelte a component is a single .svelte file that puts all three concerns — logic, markup, and styles — in one place. The structure will feel instantly familiar if you have ever written plain HTML.

A .svelte file has exactly three optional sections, in any order (convention is script → markup → style):

<script>
// Component logic — reactive state, props, functions
</script>
<!-- Markup — the template, like JSX but real HTML -->
<style>
/* Scoped CSS — automatically applies only to this component */
</style>

Only the markup section is required. A valid Svelte component can be a single <p>Hello</p> with no <script> or <style> at all.

React
// UserCard.jsx
import styles from './UserCard.module.css';
export default function UserCard({ name, role }) {
return (
<article className={styles.card}>
<h2 className={styles.name}>{name}</h2>
<p className={styles.role}>{role}</p>
</article>
);
}
Svelte
<!-- UserCard.svelte -->
<script>
let { name, role } = $props();
</script>
<article class="card">
<h2 class="name">{name}</h2>
<p class="role">{role}</p>
</article>
<style>
.card { border: 1px solid #ccc; border-radius: 8px; padding: 1rem; }
.name { margin: 0; font-size: 1.25rem; }
.role { margin: 0; color: #666; }
</style>

Notice the differences:

  • No separate UserCard.module.css file — styles are in the same file.
  • className becomes class (real HTML attribute).
  • Props are declared with $props() instead of function arguments.
  • No export default — the file itself is the export.
  • No JSX return — the markup is just… there.
Which section of a .svelte file is required?
How do you write a CSS class attribute in Svelte?
In Svelte, how do you declare component props?
Why does a Svelte component not need "export default"?