Skip to main content

Overview

The Footer component is a minimal, responsive footer displaying attribution text and dynamic copyright year. It provides a clean closing to the page layout.

Source Location

/src/components/Footer.astro

Features

  • Dynamic copyright year (auto-updates)
  • Responsive two-column layout (stacks on mobile)
  • Top border separator
  • Internationalized text
  • Dark mode support

Props

No props required. Uses translation system for text content.

Code Example

import Footer from '../components/Footer.astro';

<Footer />

Full Source Code

---
import { getLangFromUrl, useTranslations } from '../i18n/utils';

const lang = getLangFromUrl(Astro.url);
const t = useTranslations(lang);
---

<footer class="relative py-8 border-t border-slate-200/50 dark:border-slate-800/50">
  <div class="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
    <div class="flex flex-col md:flex-row items-center justify-between gap-4">
      <p class="text-slate-500 dark:text-slate-400 text-sm">
        {t('footer.text')}
      </p>
      <p class="text-slate-500 dark:text-slate-400 text-sm">
        &copy; {new Date().getFullYear()} Kevin Palma. {t('footer.rights')}
      </p>
    </div>
  </div>
</footer>

Translation Keys

Left-side attribution or tagline text
Rights reserved text (e.g., “All rights reserved.”)

Structure

Layout

<div class="flex flex-col md:flex-row items-center justify-between gap-4">
  <p><!-- Attribution --></p>
  <p><!-- Copyright --></p>
</div>
  • Mobile: Stacked vertically (flex-col)
  • Desktop: Horizontal row (md:flex-row)
  • Alignment: Centered on mobile, space-between on desktop
  • Gap: 16px between elements
&copy; {new Date().getFullYear()} Kevin Palma. {t('footer.rights')}
Output example:
© 2026 Kevin Palma. All rights reserved.
The copyright year updates automatically using new Date().getFullYear(), so you never need to manually update it.

Styling Details

<footer class="relative py-8 border-t border-slate-200/50 dark:border-slate-800/50">
  • Padding: 32px vertical (py-8)
  • Border: Top border with 50% opacity
  • Dark mode: Darker border color

Text Styling

<p class="text-slate-500 dark:text-slate-400 text-sm">
  • Color: Medium gray (slate-500)
  • Dark mode: Lighter gray (slate-400)
  • Size: Small text (text-sm = 14px)

Container Width

<div class="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
  • Max width: 1152px (6xl)
  • Centered: mx-auto
  • Responsive padding: 16px → 24px → 32px

Responsive Behavior

BreakpointLayoutAlignment
Mobile (< 768px)Vertical stackCenter
Desktop (≥ 768px)Horizontal rowSpace between

Accessibility

  • Semantic HTML: Uses <footer> element
  • Color contrast: Meets WCAG AA standards
  • Readable text: Small but legible font size
  • No interactive elements: Pure informational content

Customization

Add navigation or social links:
<div class="flex flex-col md:flex-row items-center justify-between gap-4">
  <p class="text-slate-500 dark:text-slate-400 text-sm">
    {t('footer.text')}
  </p>
  
  <!-- Social links -->
  <div class="flex items-center gap-4">
    <a href="https://linkedin.com/in/..." class="text-slate-500 hover:text-primary-600 transition-colors">
      LinkedIn
    </a>
    <a href="https://github.com/..." class="text-slate-500 hover:text-primary-600 transition-colors">
      GitHub
    </a>
  </div>
  
  <p class="text-slate-500 dark:text-slate-400 text-sm">
    &copy; {new Date().getFullYear()} Kevin Palma. {t('footer.rights')}
  </p>
</div>
Stack all elements:
<div class="flex flex-col items-center gap-2 text-center">
  <p class="text-slate-500 dark:text-slate-400 text-sm">
    {t('footer.text')}
  </p>
  <p class="text-slate-500 dark:text-slate-400 text-sm">
    &copy; {new Date().getFullYear()} Kevin Palma. {t('footer.rights')}
  </p>
  <p class="text-slate-400 dark:text-slate-500 text-xs">
    Built with Astro & Tailwind CSS
  </p>
</div>

Custom Name

Replace hardcoded name with translation:
&copy; {new Date().getFullYear()} {t('footer.name')}. {t('footer.rights')}
Add to translations:
footer: {
  name: 'Kevin Palma',
  text: 'Made with ❤️ in Argentina',
  rights: 'All rights reserved.',
}

Removing Border

<!-- No border -->
<footer class="relative py-8">

<!-- Thicker border -->
<footer class="relative py-8 border-t-2 border-slate-300 dark:border-slate-700">

Integration Example

Typically used in the main layout:
---
import Navbar from '../components/Navbar.astro';
import Footer from '../components/Footer.astro';
---

<html>
  <body>
    <Navbar />
    
    <main>
      <slot />
    </main>
    
    <Footer />
  </body>
</html>

Performance

  • Minimal HTML (2 paragraphs)
  • CSS-only styling
  • No JavaScript
  • No external resources
  • Negligible render cost
  • Navbar - Top navigation complement
  • Contact - Often placed just above footer

Build docs developers (and LLMs) love