Astro UI
Footer Columns.
Brand and tagline beside link columns, with a ruled legal line beneath.
Site chromeSectionNo dependencies Original, MIT
Style
Using Claude Code? Give it the agent prompt and skip these steps.
-
Import the foundation once
foundation.css holds the tokens every component reads.
--- // src/layouts/Layout.astro import "../styles/foundation.css"; --- -
Use it
--- import FooterColumns from "../components/viewership/footer-columns/FooterColumns.astro"; --- <FooterColumns />
Props 5
| Prop | Type | Default | Description |
|---|---|---|---|
brand | string | · | Brand name, set as text unless the logo slot is used. |
tagline | string | · | One line under the brand. |
columns | { title: string; links: { label: string; href: string }[] }[] | · | Link columns. |
legal | string | · | Copyright or legal line. |
slot: logo | slot | · | Replaces the text brand. |
Source 1 file
---
/**
* FooterColumns: brand and tagline beside link columns, legal line beneath.
*
* @example
* <FooterColumns brand="Northwind" tagline="Gear for the long way round."
* columns={[{ title: "Shop", links: [{ label: "Packs", href: "/packs" }] }]} legal="© 2026 Northwind" />
*/
interface FooterLink {
label: string;
href: string;
}
interface Column {
title: string;
links: FooterLink[];
}
interface Props {
brand: string;
tagline?: string;
columns: Column[];
legal?: string;
class?: string;
}
const { brand, tagline, columns, legal, class: className } = Astro.props;
---
<footer class:list={["vs-footer-columns", className]}>
<div class="vs-footer-columns__inner">
<div class="vs-footer-columns__top">
<div>
<a class="vs-footer-columns__brand" href="/">
<slot name="logo">{brand}</slot>
</a>
{tagline && <p class="vs-footer-columns__tagline">{tagline}</p>}
</div>
<nav class="vs-footer-columns__cols" aria-label="Footer">
{
columns.map((c) => (
<div>
<h2 class="vs-footer-columns__col-title">{c.title}</h2>
<ul>
{c.links.map((l) => (
<li>
<a href={l.href}>{l.label}</a>
</li>
))}
</ul>
</div>
))
}
</nav>
</div>
{legal && <p class="vs-footer-columns__legal">{legal}</p>}
</div>
</footer>
<style>
.vs-footer-columns {
container-type: inline-size;
background: var(--vs-page);
color: var(--vs-ink);
font-family: var(--vs-font-sans);
font-stretch: var(--vs-font-stretch);
border-top: calc(var(--vs-border-w) + 1px) solid var(--vs-ink);
}
.vs-footer-columns__inner {
max-width: var(--vs-container);
margin-inline: auto;
padding: clamp(40px, 7cqi, 80px) var(--vs-gutter) 28px;
}
.vs-footer-columns a {
color: inherit;
text-decoration: none;
}
.vs-footer-columns a:focus-visible {
outline: none;
box-shadow: var(--vs-focus-ring);
}
.vs-footer-columns__top {
display: grid;
gap: 40px;
}
.vs-footer-columns__brand {
display: inline-block;
font-family: var(--vs-font-display, var(--vs-font-sans));
font-size: 1.5rem;
font-weight: var(--vs-display-weight);
letter-spacing: var(--vs-display-tracking);
text-transform: var(--vs-display-transform);
}
.vs-footer-columns__tagline {
max-width: 22rem;
margin: 12px 0 0;
font-size: 0.9375rem;
line-height: 1.5;
color: var(--vs-ink-2);
}
.vs-footer-columns__cols {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 32px 24px;
}
.vs-footer-columns__col-title {
margin: 0 0 14px;
font-size: 0.8125rem;
font-weight: 600;
color: var(--vs-ink-3);
}
.vs-footer-columns ul {
display: grid;
gap: 10px;
margin: 0;
padding: 0;
list-style: none;
font-size: 0.9375rem;
}
.vs-footer-columns ul a:hover {
text-decoration: underline;
text-underline-offset: 4px;
}
.vs-footer-columns__legal {
margin: 48px 0 0;
padding-top: 20px;
border-top: var(--vs-border-w) solid var(--vs-line-strong);
font-size: 0.8125rem;
color: var(--vs-ink-3);
}
@container (min-width: 760px) {
.vs-footer-columns__top {
grid-template-columns: minmax(0, 4fr) minmax(0, 8fr);
gap: 64px;
}
.vs-footer-columns__cols {
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
}
}
</style> Original, MIT.