Hero with Integration Ecosystem Grid — Free HTML CSS JS Snippet

Hero with Integration Ecosystem Grid · Heroes · Plain HTML, CSS & JS · Live preview

Share & Support

What's included

Features

Live substring search filters the integration grid as you type, no submit button
Nodes are hidden via class toggling, never removed from the DOM, for zero re-render cost
Separate hidden and match classes handle fading non-matches and highlighting matches
Match highlight only applies once a real query is typed, not on initial page load
Live "X integrations shown" count stays accurate to the currently filtered set
Central glowing hub node gives the grid a visual ecosystem anchor
data-name attribute drives search independent of the visible tile label
No search or fuzzy-matching library — plain indexOf substring matching
Export as HTML file, React JSX, or React + Tailwind CSS
Mobile (375px), Tablet (768px), Desktop device preview buttons

About this UI Snippet

Integration Ecosystem Hero — Live-Searchable Integration Grid Around a Central Hub

Screenshot of the Hero with Integration Ecosystem Grid snippet rendered live

A wall of integration logos communicates breadth, but it doesn't let a visitor confirm the one tool they actually care about is there. This hero pairs a headline and CTA with a hub-and-grid visual — a glowing central "core" node surrounded by a grid of integration tiles — and a real search input that filters the grid live as a visitor types, turning a passive logo wall into a quick yes/no answer.

Filtering by attribute, not by re-rendering the DOM

applyFilter() never removes or recreates any .ieg-node element. Instead it reads each node's data-name attribute, lowercases both it and the query, and toggles two classes based on a simple indexOf substring match. Keeping every node permanently in the DOM means there's no re-render cost and no risk of losing element state (like a hover or focus outline) — filtering is purely a class toggle applied to elements that already exist.

Two classes, two distinct jobs

.ieg-node-hidden handles non-matches: it fades and shrinks the tile via opacity/transform: scale, then switches to position: absolute so it's pulled out of the grid's flow and doesn't leave a visible gap. .ieg-node-match handles the opposite case — it only applies when there's an active, non-empty query, highlighting matching tiles with a colored border and glow so a visitor gets clear positive confirmation rather than just "everything else disappeared."

Live count reflects the filtered result, not the total

countEl.textContent is updated inside the same loop that classifies each node, incrementing visibleCount only for matches. This keeps the "X integrations shown" line perfectly accurate to what's currently visible in the grid — including the un-filtered case, where every node counts as a match and the number equals the full list.

Why an empty query does not apply the match-highlight style

The matches && query !== '' condition in the .ieg-node-match toggle deliberately excludes the empty-query case — otherwise every tile in the grid would carry the "highlighted match" glow simultaneously as soon as the page loads, which would look like a rendering bug rather than intentional design. The highlight only appears once a visitor has actually typed something and narrowed the results.

The hub is a purely visual anchor, not interactive

.ieg-hub sits absolutely centered behind the grid with a radial glow, representing "your product" as the thing every integration connects to. It has no click handler or filter logic tied to it — its only job is to give the surrounding grid of tiles a visual center of gravity so the composition reads as "ecosystem" rather than "list."

Customizing it

Add more integrations by adding .ieg-node divs with a data-name attribute to #iegGridapplyFilter() re-queries .ieg-node on page load via querySelectorAll, so any node present in the HTML is automatically included in filtering with no JavaScript changes. Swap the plain-text tiles for real logo <img> tags by adding an image inside each .ieg-node div while keeping the data-name attribute for search matching.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Rather than tracing the class-toggling logic by hand, paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly why applyFilter() uses two separate classes (one for hiding non-matches, one for highlighting matches) instead of a single toggle, and why the match-highlight class specifically excludes the empty-query case. The same assistant can help you extend it — ask it to add category filter chips (e.g. "CRM," "Chat," "Analytics") above the search box that combine with the text search using AND logic, animate the grid tiles into a reflowed layout using the FLIP technique when items are hidden so remaining tiles slide smoothly into their new positions, or fetch the integration list from a JSON endpoint instead of a hardcoded HTML grid. It's also useful for a UX review: ask whether a "no results" empty state message is needed when a search query matches zero integrations, since the current version simply shows an empty grid. 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:

text
Build a hero section in plain HTML, CSS, and vanilla JavaScript centered on a live-searchable grid of integration name tiles arranged around a glowing central "hub" element — no search or animation library.

Requirements:
- A two-column layout: a left column with an eyebrow label, a headline, a supporting paragraph, and a search text input with a magnifying-glass icon; a right column containing an absolutely-positioned glowing circular "hub" element layered behind a grid of at least 16 integration name tiles, each carrying a data-name attribute holding its full searchable name (which may differ from its short visible label).
- Typing into the search input must filter the grid live, on every keystroke, with no submit button — case-insensitive substring matching against each tile's data-name attribute, not the tile's visible label.
- Non-matching tiles must fade and shrink out via a CSS transition (opacity and a scale transform) and then be removed from the grid's layout flow (e.g. via position: absolute) so the remaining matching tiles reflow into a clean grid with no gaps.
- Matching tiles must receive a distinct highlighted style (a colored border and glow) — but only while a non-empty search query is active; when the search box is empty, no tile should carry the highlight style even though all of them are visible.
- Display a live count of how many integrations are currently visible, updating on every keystroke to stay in sync with the filtered grid.
- Do not remove or recreate any tile element from the DOM during filtering — use class toggling on the existing elements only, so state is cheap to restore when the search is cleared.

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

  1. 1
    Type into the search boxTry "sla" or "fig" — matching tiles highlight with a glow while non-matches fade out instantly.
  2. 2
    Clear the searchEmptying the input restores the full grid with no highlight applied to any tile.
  3. 3
    Watch the live countThe "X integrations shown" line updates to match exactly what is visible in the grid.
  4. 4
    Add a new integration tileCopy an .ieg-node div in the HTML panel, set its data-name and label — search picks it up automatically.
  5. 5
    Swap in real logosReplace each tile's text content with an img tag while keeping the data-name attribute intact.
  6. 6
    Export 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

Developer tool and API platform homepages
Let a visitor confirm their specific stack is supported instead of scanning a static logo wall.
Integrations and app marketplace landing pages
Pair with a full integration cards directory page linked from the search result count.
Sales and RFP-facing product pages
Give prospects a fast way to verify compatibility with their existing tools during evaluation.
Learn attribute-driven client-side filtering
Study how data-name plus class toggling filters a grid without touching the DOM structure.
Workflow automation and no-code platform pages
Reuse the hub-and-grid visual to communicate "connects everything" for automation-focused products.
Related: Social Proof Logos Hero
See the Social Proof Logos Hero for a simpler static-logo-strip alternative.

Got questions?

Frequently Asked Questions

Substring match, case-insensitive. applyFilter() lowercases both the typed query and each node's data-name attribute and checks name.indexOf(query) !== -1, so typing "sla" matches "Slack" anywhere the letters appear in sequence, not just at the start.

The .ieg-node-hidden class combines opacity: 0, a scale-down transform, and position: absolute. The first two create a smooth fade-out transition, and switching to absolute positioning pulls the tile out of the grid's normal flow afterward so the remaining matched tiles reflow into a clean grid instead of leaving empty gaps.

The match-highlight class is only applied when matches && query !== '' — the query !== '' check specifically excludes the empty-input case. Without it, every tile would carry the highlighted-match glow style as soon as the page loads, which reads as a rendering bug rather than intentional feedback.

countEl.textContent is set inside the same applyFilter() loop that classifies every node, incrementing a visibleCount variable only when a node counts as a match. Because it runs on every keystroke via the input event listener, the displayed number always reflects exactly what is currently visible in the grid.

Add a new div with class ieg-node and a data-name attribute (e.g. data-name="Linear") inside the #iegGrid container in the HTML panel. Because nodes are re-queried via document.querySelectorAll('.ieg-node') and applyFilter() runs generically over whatever it finds, no JavaScript changes are needed for the new tile to be included in search.

Yes. Keep the data-name attribute on each .ieg-node div (search matching depends on it) but replace its text content with an img tag pointing at the integration's logo, sized to fit within the existing tile padding.