# Site Footer

> Multi-column site footer with social icons, legal line and an oversized fading wordmark.

- Author: Atelier UI
- License: MIT
- Page: https://chromotion.dev/en/components/site-footer
- Site: Atelier UI (https://chromotion.dev)

## Install

```bash
npx shadcn@latest add https://chromotion.dev/r/site-footer.json
```

Stack: React + TypeScript + Tailwind CSS v4, shadcn/ui conventions. `cn` comes from `@/lib/utils`.

## Dependencies

No extra dependencies.

## Usage

```tsx title="components/site-footer-demo.tsx"
import { Hexagon, Mail, Rss } from "lucide-react"

import { SiteFooter } from "@/components/site-footer"

function GitHubIcon({ className }: { className?: string }) {
  return (
    <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden className={className}>
      <path d="M12 .5a11.5 11.5 0 0 0-3.64 22.41c.58.1.79-.25.79-.56v-2c-3.2.7-3.88-1.37-3.88-1.37-.52-1.33-1.28-1.69-1.28-1.69-1.04-.71.08-.7.08-.7 1.16.08 1.77 1.19 1.77 1.19 1.03 1.76 2.7 1.25 3.36.96.1-.75.4-1.25.73-1.54-2.56-.29-5.24-1.28-5.24-5.69 0-1.26.45-2.29 1.19-3.1-.12-.29-.52-1.46.11-3.05 0 0 .97-.31 3.17 1.18a11 11 0 0 1 5.77 0c2.2-1.49 3.17-1.18 3.17-1.18.63 1.59.23 2.76.11 3.05.74.81 1.19 1.84 1.19 3.1 0 4.42-2.69 5.39-5.25 5.68.41.36.78 1.06.78 2.14v3.17c0 .31.21.67.8.56A11.5 11.5 0 0 0 12 .5Z" />
    </svg>
  )
}

function XIcon({ className }: { className?: string }) {
  return (
    <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden className={className}>
      <path d="M18.24 2.25h3.31l-7.23 8.26 8.5 11.24h-6.66l-5.21-6.82-5.97 6.82H1.67l7.73-8.84L1.25 2.25h6.83l4.71 6.23 5.45-6.23Zm-1.16 17.52h1.83L7.08 4.13H5.12l11.96 15.64Z" />
    </svg>
  )
}

const columns = [
  {
    title: "Product",
    links: [
      { label: "Features", href: "#" },
      { label: "Pricing", href: "#" },
      { label: "Changelog", href: "#" },
      { label: "Roadmap", href: "#" },
    ],
  },
  {
    title: "Resources",
    links: [
      { label: "Docs", href: "#" },
      { label: "Guides", href: "#" },
      { label: "Templates", href: "#" },
    ],
  },
  {
    title: "Company",
    links: [
      { label: "About", href: "#" },
      { label: "Blog", href: "#" },
      { label: "Careers", href: "#" },
    ],
  },
  {
    title: "Support",
    links: [
      { label: "Help center", href: "#" },
      { label: "Status", href: "#" },
      { label: "Contact", href: "#" },
    ],
  },
]

export default function SiteFooterDemo() {
  return (
    <div className="flex min-h-svh flex-col justify-end">
      <SiteFooter
        brand={
          <span className="flex items-center gap-2">
            <Hexagon className="size-5 text-orange-500" /> Hexa
          </span>
        }
        tagline="The component workshop for teams who care about the details."
        columns={columns}
        socials={[
          { label: "GitHub", href: "#", icon: GitHubIcon },
          { label: "X", href: "#", icon: XIcon },
          { label: "RSS", href: "#", icon: Rss },
          { label: "Email", href: "#", icon: Mail },
        ]}
        legal="© 2026 Hexa Labs, Inc. All rights reserved."
        bottomLinks={[
          { label: "Privacy", href: "#" },
          { label: "Terms", href: "#" },
          { label: "Cookies", href: "#" },
        ]}
        wordmark="HEXA"
      />
    </div>
  )
}
```

## Source

```tsx title="components/site-footer.tsx"
import * as React from "react"

import { cn } from "@/lib/utils"

type Link = { label: string; href: string }

export type FooterColumn = { title: string; links: Link[] }
export type FooterSocial = Link & { icon: React.ComponentType<{ className?: string }> }

export interface SiteFooterProps extends React.ComponentProps<"footer"> {
  brand: React.ReactNode
  tagline?: React.ReactNode
  columns: FooterColumn[]
  socials?: FooterSocial[]
  /** Text in the bottom bar, usually the copyright */
  legal?: React.ReactNode
  bottomLinks?: Link[]
  /** Oversized brand wordmark behind the bottom bar */
  showWordmark?: boolean
  wordmark?: string
}

export function SiteFooter({
  brand,
  tagline,
  columns,
  socials = [],
  legal,
  bottomLinks = [],
  showWordmark = true,
  wordmark,
  className,
  ...props
}: SiteFooterProps) {
  return (
    <footer className={cn("relative overflow-hidden border-t bg-background", className)} {...props}>
      <div className="mx-auto grid max-w-6xl gap-12 px-6 pt-16 pb-10 lg:grid-cols-[1.2fr_2fr]">
        <div className="flex max-w-xs flex-col gap-4">
          <div className="text-lg font-semibold">{brand}</div>
          {tagline && <p className="text-sm leading-relaxed text-muted-foreground">{tagline}</p>}
          {socials.length > 0 && (
            <ul className="mt-2 flex gap-2">
              {socials.map(({ label, href, icon: Icon }) => (
                <li key={label}>
                  <a
                    href={href}
                    aria-label={label}
                    className="flex size-9 items-center justify-center rounded-full border text-muted-foreground transition-colors hover:bg-accent hover:text-foreground"
                  >
                    <Icon className="size-4" />
                  </a>
                </li>
              ))}
            </ul>
          )}
        </div>
        <nav className="grid grid-cols-2 gap-8 sm:grid-cols-4">
          {columns.map((column) => (
            <div key={column.title} className="flex flex-col gap-3">
              <h3 className="text-sm font-medium">{column.title}</h3>
              <ul className="flex flex-col gap-2.5">
                {column.links.map((link) => (
                  <li key={link.label}>
                    <a href={link.href} className="text-sm text-muted-foreground transition-colors hover:text-foreground">
                      {link.label}
                    </a>
                  </li>
                ))}
              </ul>
            </div>
          ))}
        </nav>
      </div>
      <div className="relative mx-auto flex max-w-6xl flex-col gap-3 border-t px-6 py-6 text-xs text-muted-foreground sm:flex-row sm:items-center sm:justify-between">
        <p>{legal}</p>
        {bottomLinks.length > 0 && (
          <ul className="flex flex-wrap gap-5">
            {bottomLinks.map((link) => (
              <li key={link.label}>
                <a href={link.href} className="transition-colors hover:text-foreground">
                  {link.label}
                </a>
              </li>
            ))}
          </ul>
        )}
      </div>
      {showWordmark && wordmark && (
        <p
          aria-hidden
          className="pointer-events-none -mb-[0.2em] bg-linear-to-b from-foreground/15 to-transparent bg-clip-text text-center text-[clamp(4rem,18vw,14rem)] leading-none font-bold tracking-tighter text-transparent select-none"
        >
          {wordmark}
        </p>
      )}
    </footer>
  )
}
```
