Responsive Design
Gymlium websites are accessed on everything from large desktop monitors to mobile phones. Your template must look and function well at all screen sizes.
Mobile-first approach
Build your styles starting from the smallest screen and layer on complexity for larger viewports. This approach produces cleaner CSS and better mobile experiences.
/* Base styles — mobile first */
.grid {
display: grid;
grid-template-columns: 1fr;
gap: 1rem;
}
/* Tablet */
@media (min-width: 768px) {
.grid {
grid-template-columns: repeat(2, 1fr);
gap: 1.5rem;
}
}
/* Desktop */
@media (min-width: 1024px) {
.grid {
grid-template-columns: repeat(3, 1fr);
}
}
/* Large desktop */
@media (min-width: 1280px) {
.grid {
max-width: 1200px;
margin: 0 auto;
}
}Standard breakpoints
Use these breakpoints consistently across your template:
| Breakpoint | Min-width | Target |
|---|---|---|
sm | 640px | Large phones (landscape) |
md | 768px | Tablets |
lg | 1024px | Laptops / small desktops |
xl | 1280px | Desktops |
These match Tailwind’s default breakpoints. If you’re using Tailwind utilities, the prefixes work the same way: sm:, md:, lg:, xl:.
Header: hamburger menu pattern
On mobile screens, collapse the navigation into a hamburger menu. This is the most common and expected pattern.
import { useState } from 'react'
import styles from './Header.module.css'
import { useApp } from '@/hooks/useApp'
export function Header() {
const [menuOpen, setMenuOpen] = useState(false)
const { t, localePath } = useApp()
return (
<header className={styles.header}>
<a href={localePath('/')} className={styles.logo}>
{/* logo */}
</a>
{/* Desktop navigation — hidden on mobile */}
<nav className={styles.desktopNav}>
<a href={localePath('/')}>{t('home')}</a>
<a href={localePath('/about')}>{t('about')}</a>
</nav>
{/* Hamburger button — visible on mobile only */}
<button
className={styles.hamburger}
onClick={() => setMenuOpen(!menuOpen)}
aria-label={t('toggleMenu')}
aria-expanded={menuOpen}
>
<span className={styles.bar} />
<span className={styles.bar} />
<span className={styles.bar} />
</button>
{/* Mobile menu overlay */}
{menuOpen && (
<div className={styles.overlay} onClick={() => setMenuOpen(false)}>
<nav
className={styles.mobileNav}
onClick={e => e.stopPropagation()}
>
<a href={localePath('/')}>{t('home')}</a>
<a href={localePath('/about')}>{t('about')}</a>
</nav>
</div>
)}
</header>
)
}/* Header.module.css */
.desktopNav {
display: none;
}
.hamburger {
display: flex;
flex-direction: column;
gap: 4px;
background: none;
border: none;
cursor: pointer;
padding: 8px;
}
.bar {
width: 24px;
height: 2px;
background: var(--text-primary);
transition: transform 0.2s;
}
.overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 200;
}
.mobileNav {
position: fixed;
top: 0;
right: 0;
width: 280px;
height: 100vh;
background: var(--bg-primary);
padding: 2rem;
display: flex;
flex-direction: column;
gap: 1.5rem;
z-index: 201;
}
:global([dir="rtl"]) .mobileNav {
right: auto;
left: 0;
}
@media (min-width: 768px) {
.desktopNav {
display: flex;
gap: 2rem;
}
.hamburger {
display: none;
}
}Grid layouts for page content
Use CSS Grid for responsive page content layouts:
/* Service cards grid */
.services {
display: grid;
grid-template-columns: 1fr;
gap: 1.5rem;
padding: 2rem 1rem;
}
@media (min-width: 640px) {
.services {
grid-template-columns: repeat(2, 1fr);
padding: 3rem 2rem;
}
}
@media (min-width: 1024px) {
.services {
grid-template-columns: repeat(3, 1fr);
max-width: 1200px;
margin: 0 auto;
padding: 4rem 2rem;
}
}Responsive typography
Scale typography with viewport width for comfortable reading:
.heroTitle {
font-size: 2rem;
line-height: 1.2;
}
@media (min-width: 768px) {
.heroTitle {
font-size: 3rem;
}
}
@media (min-width: 1024px) {
.heroTitle {
font-size: 3.5rem;
}
}Alternatively, use clamp() for fluid typography:
.heroTitle {
font-size: clamp(2rem, 5vw, 3.5rem);
line-height: 1.2;
}Testing responsive designs
Use the browser’s responsive design mode (Chrome DevTools → Toggle device toolbar) to test at various viewport sizes. Test at least: 375px (iPhone SE), 768px (iPad), 1024px (laptop), and 1440px (desktop).
Always test:
- Navigation collapse and hamburger menu functionality
- Image scaling and aspect ratios
- Touch target sizes (minimum 44×44px on mobile)
- Text readability at all sizes
- Grid layout reflow
- RTL layout at every breakpoint