Skip to content
    Style: Wireframe

    Blocks · Navigation

    Site footer

    Brand, link columns and a legal row; on the page or as an inverted band that closes it.

    85% of the 2,073 sites in The UI Index have a footer (1,762 sites).

    Used in UI Pro: Footer

    Both previews render the same markup; the HTML tab below is that markup without a framework.

    Install

    React
    npx shadcn@latest add https://www.themes.dev/ui/r/site-footer.json
    Astro
    npx shadcn@latest add https://www.themes.dev/ui/r/astro/site-footer.json

    Or copy the files below into your project. They need clsx, tailwind-merge and the components they import, and the themes.dev UI theme. The HTML needs only the compiled CSS.

    site-footer.classes.ts
    /** The site footer (ported from the themes' sections/footer): brand and a line about the product, link columns,
     *  and a legal row. columns sits on the page's ground with space above; band is an inverted ground (class
     *  inverted from the theme), the page's closing bookend. Links are 32px targets. */
    export const siteFooter = {
      root: '@container bg-background px-6 pt-16 pb-10 text-foreground',
      band: 'inverted',
      inner: 'mx-auto flex max-w-6xl flex-col gap-12',
      top: 'grid gap-12 @3xl:grid-cols-[1.2fr_2fr]',
      brand: 'flex flex-col gap-3',
      brandName: 'text-[15px] font-semibold tracking-[-0.02em]',
      tagline: 'max-w-xs text-sm text-pretty text-muted-foreground',
      // Three columns at every width: two would leave the third group alone on its row.
      groups: 'grid grid-cols-3 gap-4 @md:gap-6 @lg:gap-8 [&>*]:min-w-0',
      group: 'flex flex-col gap-2',
      groupTitle: 'text-sm font-medium',
      groupList: 'm-0 flex list-none flex-col p-0',
      link: '-mx-1 inline-flex min-h-8 items-center rounded-sm px-1 text-sm text-muted-foreground transition-colors hover:text-foreground hover:underline hover:underline-offset-4 active:text-foreground/70',
      legal: 'flex flex-col gap-3 border-t pt-6 text-sm text-muted-foreground @xl:flex-row @xl:items-center @xl:justify-between',
      legalList: 'm-0 flex list-none flex-wrap gap-x-5 p-0',
    };
    
    export type FooterGroup = { title: string; links: { label: string; href: string }[] };
    export type FooterContent = {
      brand: string;
      tagline?: string;
      groups: FooterGroup[];
      legal: { label: string; href: string }[];
      /** The small print, e.g. "© 2026 Northwind". */
      note: string;
      variant?: 'columns' | 'band';
    };
    site-footer.tsx
    import { cn } from '@/lib/utils';
    import { siteFooter as c, type FooterContent } from './site-footer.classes';
    
    export type SiteFooterProps = FooterContent & { className?: string };
    
    /** The site footer: brand, link columns and a legal row; band puts it on an inverted ground. */
    export function SiteFooter({ brand, tagline, groups, legal, note, variant = 'columns', className }: SiteFooterProps) {
      return (
        <footer className={cn(c.root, variant === 'band' && c.band, className)}>
          <div className={c.inner}>
            <div className={c.top}>
              <div className={c.brand}>
                <p className={c.brandName}>{brand}</p>
                {tagline && <p className={c.tagline}>{tagline}</p>}
              </div>
              <div className={c.groups}>
                {groups.map((g) => (
                  <nav key={g.title} aria-label={g.title} className={c.group}>
                    <p className={c.groupTitle}>{g.title}</p>
                    <ul className={c.groupList}>
                      {g.links.map((l) => (
                        <li key={l.href + l.label}><a href={l.href} className={c.link}>{l.label}</a></li>
                      ))}
                    </ul>
                  </nav>
                ))}
              </div>
            </div>
            <div className={c.legal}>
              <p>{note}</p>
              <ul className={c.legalList} aria-label="Legal">
                {legal.map((l) => <li key={l.href + l.label}><a href={l.href} className={c.link}>{l.label}</a></li>)}
              </ul>
            </div>
          </div>
        </footer>
      );
    }