How to build a founder about section in React
A React founder about section pairs a portrait placeholder on the left with a serif blockquote, name, role and bio on the right inside a two-column CSS grid. Both columns animate in on scroll with Framer Motion's whileInView, the image scaling up from 0.95 and the text sliding from y:20.
- Stack: React + Framer Motion + Lucide React, ~145 lines, zero extra dependencies.
- Animations: whileInView with once:true, custom spring EASE [0.16, 1, 0.3, 1], 100ms stagger between image and text.
- Grid collapses to a single column on narrow viewports via inline style; the portrait uses a 3/4 aspect ratio.
- Fully theme-aware: every color and spacing value pulls from CSS custom properties, compatible with all 7 presets.
- Accessible: semantic blockquote + p tags, accent color on role text, image placeholder visible in any theme mode.
AboutFounder is a split-layout React section designed to put a human face on a brand. It places a portrait placeholder on the left and a large serif quote, name, role, and bio paragraph on the right. Both sides scroll into view independently, giving the reveal a natural, unhurried feel without loading a single animation library beyond Framer Motion.
Anatomy
The outer section uses CSS custom properties for all padding and background. Inside, a two-column grid (320px fixed left column, 1fr right) holds two motion.div elements. The left column renders a 3/4 aspect-ratio placeholder with a tinted background overlay and a centered ImageIcon from Lucide. The right column stacks four elements top-to-bottom: a Quote icon above the blockquote, a name/role row separated from the bio by a bottom border, and the bio paragraph itself.
How it works
Both motion.div elements use whileInView to trigger once the element crosses the viewport. The image column animates opacity 0→1 and scale 0.95→1 over 600ms. The content column uses the same duration but starts 100ms later (delay: 0.1) and slides in from y:20 instead of scaling. Both share the same custom cubic-bezier ease [0.16, 1, 0.3, 1], which produces a snappy overshoot-free deceleration typical of high-quality product sites. The viewport option `once: true` prevents the animation from replaying on scroll-up.
How to build it in React
Set up the two-column grid
Wrap everything in a section with CSS-variable padding, then inside place a div with display:grid, gridTemplateColumns:'320px 1fr' and a 4rem gap. On mobile you'll override to a single column. Using inline styles against CSS tokens avoids any Tailwind breakpoint friction.
<div style={{ display: "grid", gridTemplateColumns: "320px 1fr", gap: "4rem", alignItems: "center", }}>Animate the portrait placeholder into view
Wrap the left column in a motion.div. Set initial to opacity:0, scale:0.95 and whileInView to opacity:1, scale:1. Pass viewport={{once:true}} so the reveal fires only the first time. Use the custom ease constant for a smooth deceleration.
const EASE = [0.16, 1, 0.3, 1] as const; <motion.div initial={{ opacity: 0, scale: 0.95 }} whileInView={{ opacity: 1, scale: 1 }} viewport={{ once: true }} transition={{ duration: 0.6, ease: EASE }} >Stagger the content column
The right column uses the same transition settings with a y:20 slide-in and a 100ms delay. That small stagger makes the two columns feel choreographed rather than simultaneous. Keep both durations identical so the timing reads as intentional.
<motion.div initial={{ opacity: 0, y: 20 }} whileInView={{ opacity: 1, y: 0 }} viewport={{ once: true }} transition={{ duration: 0.6, delay: 0.1, ease: EASE }} >Wire up the blockquote and bio
Inside the right column, place a Quote icon (Lucide) with low opacity above a semantic blockquote element. Below that, render name and role in a flex row, separated from the bio by a bottom border. Pass all text content as props so the component stays reusable across different founders or team members.
When to use it
Use this section mid-page on startup landing pages, agency sites or portfolio projects to humanize the brand before a social proof or CTA block. It works especially well after a feature section, giving readers a moment to connect with the person behind the product. Skip it on pure e-commerce or transactional pages where personal credibility doesn't drive the conversion, and avoid stacking it directly after another full-bleed image section.
Used by
- Basecamp, Founder Jason Fried's face and direct quotes anchor the About page, establishing personal credibility before the product pitch.
- Notion, Team and founder portraits with short bios appear in the company story section to connect the product to real people.
- Framer, Founder and team grid with name, role and short description in a clean split layout typical of design-tool companies.
FAQ
How do I replace the placeholder with a real photo?
Remove the ImageIcon and the overlay div inside the left motion.div, then render a Next.js Image (or a standard img) filling the container. Keep the borderRadius and overflow:hidden on the wrapper so the portrait stays clipped to the rounded rectangle.
Can I make the grid responsive without Tailwind?
Yes. Add a CSS rule or inline media query that switches gridTemplateColumns to '1fr' below 768px. Because the component uses inline styles you can also pass an sx-style object or wrap it in a styled-component if your project uses those.
Why use once:true on the viewport trigger?
Replaying the entrance animation every time a user scrolls past the section feels glitchy and draws attention to the mechanism rather than the content. once:true fires the reveal on the first intersection only, which reads as a polished page-load transition rather than a looping effect.
What's the serif font used for the blockquote?
The blockquote reads from the CSS custom property var(--font-serif), defined by the active theme preset. Drop in any serif font-family there, Georgia, Lora, Playfair Display, and the quote inherits it automatically without touching the component code.