Login
Centered login form on a muted background. Uses Rizzo form components and design tokens. Copy and paste into your app.
This block is a login page: centered form card with optional brand link, email and password fields, submit button, and footer links (forgot password, sign up). Use it as a starting point for auth screens. Same BEM and tokens work in any framework.
Preview
Login form using design tokens and form-input classes.
Usage
Copy the snippet for your framework. Same BEM classes and structure work everywhere.
Usage
Full example for each framework (Astro, Vanilla, Svelte, Vue, React). Switch framework via View as or by clicking a Usage tab—both stay in sync.
Astro Vanilla Svelte Vue React
astro astro
---
// Astro: static form; add client:load for client-side validation if needed.
---
<div class="login-block">
<a href="/" class="login-block__brand" aria-label="Home">
<span class="login-block__brand-icon" aria-hidden="true">R</span>
Acme
</a>
<form class="login-block__form" action="#" method="post" aria-labelledby="login-heading">
<h2 id="login-heading" class="login-block__title">Sign in</h2>
<div class="form-group">
<label for="login-email" class="label">Email</label>
<input type="email" id="login-email" name="email" class="form-input" placeholder="you@example.com" autocomplete="email" />
</div>
<div class="form-group">
<label for="login-password" class="label">Password</label>
<input type="password" id="login-password" name="password" class="form-input" placeholder="••••••••" autocomplete="current-password" />
</div>
<button type="submit" class="btn btn-primary" style="width: 100%;">Sign in</button>
</form>
<p class="login-block__footer">
<a href="#">Forgot password?</a> · <a href="/signup">Create account</a>
</p>
</div> html html
<!-- Vanilla: ensure Rizzo CSS loaded. Same BEM. -->
<div class="login-block">
<a href="/" class="login-block__brand" aria-label="Home">
<span class="login-block__brand-icon" aria-hidden="true">R</span>
Acme
</a>
<form class="login-block__form" action="#" method="post" aria-labelledby="login-heading">
<h2 id="login-heading" class="login-block__title">Sign in</h2>
<div class="form-group">
<label for="login-email" class="label">Email</label>
<input type="email" id="login-email" name="email" class="form-input" placeholder="you@example.com" autocomplete="email" />
</div>
<div class="form-group">
<label for="login-password" class="label">Password</label>
<input type="password" id="login-password" name="password" class="form-input" placeholder="••••••••" autocomplete="current-password" />
</div>
<button type="submit" class="btn btn-primary" style="width: 100%;">Sign in</button>
</form>
<p class="login-block__footer">
<a href="#">Forgot password?</a> · <a href="/signup">Create account</a>
</p>
</div> svelte svelte
<script>
// Svelte: same BEM; bind inputs with bind:value for reactive form.
</script>
<div class="login-block">
<a href="/" class="login-block__brand" aria-label="Home">
<span class="login-block__brand-icon" aria-hidden="true">R</span>
Acme
</a>
<form class="login-block__form" action="#" method="post" aria-labelledby="login-heading">
<h2 id="login-heading" class="login-block__title">Sign in</h2>
<div class="form-group">
<label for="login-email" class="label">Email</label>
<input type="email" id="login-email" name="email" class="form-input" placeholder="you@example.com" autocomplete="email" />
</div>
<div class="form-group">
<label for="login-password" class="label">Password</label>
<input type="password" id="login-password" name="password" class="form-input" placeholder="••••••••" autocomplete="current-password" />
</div>
<button type="submit" class="btn btn-primary" style="width: 100%;">Sign in</button>
</form>
<p class="login-block__footer">
<a href="#">Forgot password?</a> · <a href="/signup">Create account</a>
</p>
</div> vue vue
<script setup>
// Vue: same BEM; use v-model for inputs.
</script>
<template>
<div class="login-block">
<a href="/" class="login-block__brand" aria-label="Home">
<span class="login-block__brand-icon" aria-hidden="true">R</span>
Acme
</a>
<form class="login-block__form" action="#" method="post" aria-labelledby="login-heading">
<h2 id="login-heading" class="login-block__title">Sign in</h2>
<div class="form-group">
<label for="login-email" class="label">Email</label>
<input type="email" id="login-email" name="email" class="form-input" placeholder="you@example.com" autocomplete="email" />
</div>
<div class="form-group">
<label for="login-password" class="label">Password</label>
<input type="password" id="login-password" name="password" class="form-input" placeholder="••••••••" autocomplete="current-password" />
</div>
<button type="submit" class="btn btn-primary" style="width: 100%;">Sign in</button>
</form>
<p class="login-block__footer">
<a href="#">Forgot password?</a> · <a href="/signup">Create account</a>
</p>
</div>
</template> tsx tsx
export function LoginBlock() {
return (
<div className="login-block">
<a href="/" className="login-block__brand" aria-label="Home">
<span className="login-block__brand-icon" aria-hidden="true">R</span>
Acme
</a>
<form className="login-block__form" action="#" method="post" aria-labelledby="login-heading">
<h2 id="login-heading" className="login-block__title">Sign in</h2>
<div className="form-group">
<label htmlFor="login-email" className="label">Email</label>
<input type="email" id="login-email" name="email" className="form-input" placeholder="you@example.com" autoComplete="email" />
</div>
<div className="form-group">
<label htmlFor="login-password" className="label">Password</label>
<input type="password" id="login-password" name="password" className="form-input" placeholder="••••••••" autoComplete="current-password" />
</div>
<button type="submit" className="btn btn-primary" style={{ width: '100%' }}>Sign in</button>
</form>
<p className="login-block__footer">
<a href="#">Forgot password?</a> · <a href="/signup">Create account</a>
</p>
</div>
);
} Components used
- Rizzo form classes (
form-input,label,form-group) - Button —
btn btn-primaryfor submit - Design tokens for spacing, radius, and colors