Partner and integration logo walls
How to build an even partner logo grid by normalizing size and weight, choosing mono or color, spacing cells, linking logos and keeping claims true.
6 min read
A wall of logos is one of the most common sections on a crypto site: the chains you support, the wallets that connect, the exchanges where your token trades. It's also one of the easiest to get wrong. Drop the official files into equal boxes and you get a wall where one wordmark shouts, another whispers and a round symbol looks lost. This guide shows how to make the wall look even, and how to keep what it says accurate.
Why equal boxes look unequal
Logos come in very different shapes. A circular token symbol is about 1:1. A horizontal exchange wordmark might be 5:1. Fit each one into the same 160 × 64 px box with object-fit: contain and the wordmark fills the width but ends up thin, while the circle fills the height and ends up a small coin. Neither looks like it carries the same weight.
Two things drive how big a logo looks: area, meaning how much space the artwork covers, and density, meaning how heavy its shapes are. Fix area with a formula, then fix density by eye.
Normalize by area, not by width or height
Give every logo roughly the same area, then clamp it to the cell. For a logo with aspect ratio r = width / height and a target area A, the dimensions that keep the ratio are height = √(A / r) and width = height × r.
export type Logo = {
name: string
src: string
href: string
ratio: number // width / height, from the SVG's viewBox
scale?: number // optical correction, 1 = none
}
const CELL = { width: 160, height: 64 }
const TARGET_AREA = 3600 // about 60 × 60 px; tune by eye
export function logoSize({ ratio, scale = 1 }: Logo) {
let height = Math.sqrt(TARGET_AREA / ratio) * scale
let width = height * ratio
if (width > CELL.width) {
width = CELL.width
height = width / ratio
}
if (height > CELL.height) {
height = CELL.height
width = height * ratio
}
return { width: Math.round(width), height: Math.round(height) }
}
With a target of 3,600 px², a square symbol comes out at 60 × 60, a 2.5:1 lockup at about 95 × 38, and a 5:1 wordmark at about 134 × 27. Side by side, those look much closer in weight than three logos that each fill the same box.
You need each logo's aspect ratio. For SVGs, divide the last two numbers of the viewBox (width by height) and store the result in your data, rather than measuring at runtime. Trim the files first so the viewBox hugs the artwork; padding baked into a file throws the math off.
Correct optical weight by hand
Area gets you close; your eyes do the rest. A logo built from thick, solid shapes looks heavier than an outlined one of the same area, and a logo with a lot of empty space inside looks lighter. The scale field handles this: values between about 0.85 and 1.15 are usually enough. Adjust while looking at the whole wall, not one logo at a time. Squint, or blur a screenshot, and any logo that stands out as a darker or paler blob needs a nudge. The same idea applies at icon scale; see optical balance.
Mono or color
| Single color | Full color | |
|---|---|---|
| Visual weight | Even; differences shrink | Uneven; bright logos dominate |
| Fit with your design | Takes on your palette | Brings a dozen palettes |
| Recognition | By shape | By shape and color |
| Files | Official one-color versions where available | Official full-color files |
| Typical use | Supported networks rows, footers, "Works with" strips | Integration directories, partner detail pages |
Single-color walls are calmer and read as one unit, which is why they're so common. If you go that way, use the white or black versions from each brand's press kit rather than running full-color files through a CSS grayscale() filter. A filter turns colors into uneven grays, and a logo whose parts are separated only by color can lose its internal shapes. The guide on mono versions explains why.
A popular pattern shows logos in one color and reveals full color on hover. It's fine as decoration, but touch screens have no hover, so the default state has to stand on its own.
Dim gray logos are also common on dark sites. WCAG exempts logotypes from the text contrast minimum in 1.4.3, and logos aren't required to meet 1.4.11 Non-text Contrast either, but a wall nobody can make out doesn't do its job. Keep the logos clearly visible against the background.
Grid and spacing
A CSS grid with equal cells handles most walls:
.logo-wall {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
gap: 1px;
margin: 0;
padding: 0;
list-style: none;
background: var(--line); /* shows through the gaps as hairlines */
}
.logo-wall a {
display: grid;
place-items: center;
height: 96px;
padding: 16px;
background: var(--surface);
}
.logo-wall img {
display: block;
max-width: 100%;
height: auto;
}
And the markup, using the sizes computed above:
export function LogoWall({ logos }: { logos: Logo[] }) {
return (
<ul className="logo-wall">
{logos.map((logo) => {
const { width, height } = logoSize(logo)
return (
<li key={logo.name}>
<a href={logo.href}>
<img src={logo.src} alt={logo.name} width={width} height={height} loading="lazy" />
</a>
</li>
)
})}
</ul>
)
}
A few layout rules of thumb:
- Keep gaps equal. Consistent spacing between logos matters more than anything else in the grid.
- Fill whole rows. Twelve logos divide into rows of 2, 3, 4 or 6; eleven leave a hole at almost every width. Pick a count that divides well, or center the last row.
- Order deliberately. Alphabetical order is neutral and easy to scan. Ordering by importance implies a ranking you may have to defend.
- Check a phone. At two columns, a 134 px wordmark leaves little room; make sure nothing gets clipped.
Links and names
Each logo is usually a link, so decide where it goes. Your own page about the integration ("Using our app with Base") is often more useful to the reader than the partner's homepage. Either way:
- give each image alt text that names the partner, like
alt="Base", never "logo" or a file name; the guide on alt text for logos covers the details; - if the link goes to your integration page rather than the partner's site, a short visible caption under the logo makes the destination clear;
- keep a visible focus style on the link; the logo alone gives keyboard users no sign of where they are.
Keep the claims accurate
The heading above a logo wall is a claim about every logo under it. "Partners" says each organization agreed to work with you. "Trusted by" says they use your product. "Supported networks" says you're deployed there. Choose a heading that's true for every logo on the wall, and split the wall if one heading can't cover them all. The guide on using logos in marketing covers wording and when to ask for permission; as there, this is general information, not legal advice.
Logo walls also go stale quietly. When an integration is removed or a partnership ends, the logo tends to stay. Keep the wall's data in one file, with a note per entry saying what backs the claim and when it was last checked, and review it on a schedule:
export const networks: (Logo & { basis: string; checked: string })[] = [
{
name: 'Base',
src: '/logos/base.svg',
href: '/integrations/base',
ratio: 1,
basis: 'Contracts deployed on Base mainnet',
checked: '2026-10-15',
},
]