Hero with Press Mentions and Founder Quote — Free HTML CSS JS Snippet
Hero with Press Mentions and Founder Quote · Heroes · Plain HTML, CSS & JS · Live preview
What's included
Features
About this UI Snippet
Press Mentions + Founder Quote Hero — Rotating Social Proof Card for Landing Pages

A headline promises a product is good; a press mention or an investor's own words prove someone independent already agreed. This hero section pairs both trust signals in one composition — a press-logo strip sitting under the primary copy and CTA, and a self-rotating quote card on the opposite side that cycles between a founder testimonial, an investor endorsement, and a customer story.
One rotation function drives every part of the card
showQuote(index, isManual) is the single source of truth for the quote card's state. It updates the quote text, the person's name and role, the avatar initials, and the active dot — all from one quotes array entry — so there's no risk of the name updating while the quote text lags behind, a common bug in hand-rolled rotators that update each field with separate logic.
Fading text and avatar, not the whole card
Rather than fading the entire .pfq-quote-card (which would visibly dim the surrounding chrome and border on every rotation), only .pfq-quote-text and .pfq-avatar have their opacity toggled, with the actual content swap happening inside a setTimeout timed to the CSS transition's midpoint. This keeps the card's border, background, and dots fully visible and stable throughout the rotation — only the content that's actually changing appears to fade.
`min-height` on the quote text prevents layout jump
Quotes of different lengths would otherwise cause the card — and everything below it, including the dots — to jump vertically each time the text changes. Setting a min-height on .pfq-quote-text reserves enough vertical space for a two-to-three line quote regardless of which one is currently showing, so the dots and avatar stay anchored in place.
Dots are both an indicator and a control
renderDots() rebuilds the dot row on every rotation so the active dot always matches current, and each dot is a real <button> with a click handler bound via an IIFE closure over its own index — a common pitfall in a loop-generated event handler is every handler closing over the same final loop variable, which the IIFE avoids. Clicking a dot calls showQuote(index, true), where the true flag tells the function to call restartTimer() — so a manual click resets the five-second auto-advance clock instead of immediately being overridden by it.
The press-logo strip as understated proof, not a carousel
The press mentions are deliberately static text logotypes below a divider, not another rotating or animated element — stacking two moving elements in one hero would compete for attention. The static row reads as ambient credibility while the quote card, which changes over time, is the one element inviting a second look.
Customizing it
Add or remove entries from the quotes array — each needs text, name, role, and initials; the dots and rotation logic scale automatically to however many entries the array holds. Replace the avatar initials with real <img> photos by swapping .pfq-avatar's textContent assignment for an src update. Adjust the auto-advance interval by changing the 5000 millisecond value passed to setInterval inside restartTimer().
Build with AI
Build, Understand, Optimize, and Extend It With AI
Rather than tracing the fade timing by hand, paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly how showQuote() sequences the opacity fade-out, the setTimeout-delayed content swap, and the fade-in so the two never visually overlap, and why the dot click handlers are wrapped in an IIFE inside the for loop in renderDots(). The same assistant can help you extend it — ask it to add a subtle progress bar under the dots showing time remaining until the next auto-advance, pause the rotation on hover or keyboard focus so a reader is not interrupted mid-read, or pull the quotes array from a CMS or JSON endpoint instead of a hardcoded list. It's also useful for an accessibility pass: ask whether the rotating quote region needs an aria-live attribute, and whether the auto-advance should respect a visitor's prefers-reduced-motion setting. Treat the code less like a finished artifact and more like a starting point for a conversation.
Prompt to recreate it
Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:
Build a two-column hero section in plain HTML, CSS, and vanilla JavaScript pairing a headline/CTA column with a static press-mention logo strip against a self-rotating quote card — no carousel library.
Requirements:
- Left column: an eyebrow label, a large headline, a supporting paragraph, two call-to-action buttons, and a row of press outlet names/logos below a divider.
- Right column: a dark quote card containing a large decorative quote mark icon, a quote paragraph, a small avatar circle with initials, a name and role line, and a row of navigation dots — one per quote.
- Store all quotes (text, name, role, initials) in a single JavaScript array. Write one function that updates the quote text, avatar, name, role, and active dot together from one array entry, so no field can ever visually lag behind another during a transition.
- Auto-advance to the next quote every 5 seconds using setInterval, wrapping back to the first quote after the last.
- Make each dot clickable: clicking one must immediately jump to that quote and reset the 5-second auto-advance timer so it does not fire again right away. Bind each dot's click handler so it correctly captures its own index even though the dots are created in a loop.
- Fade only the quote text and avatar (not the whole card) between quote changes, swapping the actual text content at the midpoint of the fade so the transition never shows mismatched old/new content at once.
- Give the quote text a minimum height so quotes of different lengths do not shift the avatar and dots vertically when the text changes.Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.
Step by step
How to Use
- 1Watch the quote card rotateEvery 5 seconds the card fades to the next founder, investor, or customer quote automatically.
- 2Click a dot to jump quotesClicking any dot immediately shows that quote and resets the auto-advance timer.
- 3Edit the quotes arrayIn the JS panel, edit the text, name, role, and initials fields for each quote.
- 4Update the press logosReplace the .pfq-press-logo spans in the HTML panel with your own outlet names or logo images.
- 5Change the rotation speedEdit the 5000 millisecond value inside restartTimer() in the JS panel.
- 6Export in your formatClick "HTML" for a standalone file, "JSX" for a React component, or "Tailwind" for a React + Tailwind version.
Real-world uses
Common Use Cases
Got questions?
Frequently Asked Questions
Every 5000 milliseconds (5 seconds), set inside restartTimer() via setInterval. Edit that number in the JS panel to speed up or slow down the auto-advance.
showQuote(index, true) runs immediately, updating the text, name, role, avatar, and active dot to the clicked quote, and the true flag tells it to call restartTimer(), which clears the existing interval and starts a fresh 5-second countdown so the auto-advance does not immediately override your manual choice.
Fading the entire card would visibly dim its border, background, and the dot row on every single rotation, which reads as flickery. Only .pfq-quote-text and .pfq-avatar have their opacity toggled, so the card itself stays visually stable while just the content that is actually changing fades in and out.
Add a new object with text, name, role, and initials fields to the quotes array at the top of the JS panel. renderDots() and the rotation logic both read the array's length dynamically, so a fourth dot appears automatically with no other code changes needed.
Yes. Change .pfq-avatar from a div with text content to an img element, and in the JS swap the avatarEl.textContent = q.initials line for avatarEl.src = q.photoUrl, adding a photoUrl field to each entry in the quotes array.
Quotes of different lengths would otherwise cause the card, and the avatar and dots below it, to jump vertically every time the text changes. The min-height reserves enough space for a typical two-to-three line quote so the layout stays visually anchored regardless of which quote is showing.