---
title: Logo Cloud
description: A partner or customer logo wall, exposed as a labeled list.
category: Marketing
related:
  - /components/image
  - /components/testimonial
  - /components/grid
visibility: guest
draft: false
---

# Logo Cloud

The "trusted by" wall. A responsive grid of partner or customer logos, muted so a
row of clashing brand colors does not compete with your own.

It is a real **list of companies**, not a decorative strip — so someone who cannot
see the wall still learns how many names are being claimed, and each logo carries
its own name.

:::preview{title="Logo cloud with a lead-in"}
<x-wirekit::logo-cloud label="Trusted by teams at">
    <li><x-wirekit::image src="/placeholder/160x48?bg=e5e7eb&fg=374151&label=Acme&gradient=none" alt="Acme" /></li>
    <li><x-wirekit::image src="/placeholder/160x48?bg=e5e7eb&fg=374151&label=Globex&gradient=none" alt="Globex" /></li>
    <li><x-wirekit::image src="/placeholder/160x48?bg=e5e7eb&fg=374151&label=Initech&gradient=none" alt="Initech" /></li>
    <li><x-wirekit::image src="/placeholder/160x48?bg=e5e7eb&fg=374151&label=Umbrella&gradient=none" alt="Umbrella" /></li>
    <li><x-wirekit::image src="/placeholder/160x48?bg=e5e7eb&fg=374151&label=Soylent&gradient=none" alt="Soylent" /></li>
</x-wirekit::logo-cloud>
:::

## Every logo needs a name

A logo is not decoration here — it *is* the claim. Give each one an `alt` naming
the company:

```blade
<x-wirekit::logo-cloud label="Trusted by teams at">
    <li><x-wirekit::image src="/logos/acme.svg" alt="Acme" /></li>
    <li><x-wirekit::image src="/logos/globex.svg" alt="Globex" /></li>
</x-wirekit::logo-cloud>
```

An `alt=""` here would leave a screen-reader user with "list, 5 items" and five
items of nothing — the exact opposite of what the wall is for.

## Muted by default

Logos render grayscale at reduced opacity and return to full color on hover or
keyboard focus. That is purely visual: every logo keeps its `alt`, so nothing
about a company's identity depends on seeing its color.

Pass `:muted="false"` to show them in full color:

```blade
<x-wirekit::logo-cloud :muted="false">…</x-wirekit::logo-cloud>
```

## Naming the list

`label` renders a visible lead-in *and* names the list. When you want the list's
accessible name to differ from the visible text, pass `aria-label` as well:

```blade
{{-- Visible: "Trusted by" · announced: "Customer logos" --}}
<x-wirekit::logo-cloud label="Trusted by" aria-label="Customer logos">…</x-wirekit::logo-cloud>
```

With neither, no name is announced at all — which is deliberate. An `aria-label=""`
announces a boundary and then cannot say what it is for.

## Props

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `label` | `string\|null` | `null` | Visible lead-in above the wall. Also names the list. |
| `ariaLabel` | `string\|null` | `null` | Accessible name for the list, when it should differ from `label`. |
| `muted` | `bool` | `true` | Render the logos grayscale until hover or focus. |
| `scope` | `string\|null` | `null` | Class-scope override. |

## Accessibility

- The wall is a `<ul role="list">` of `<li>` items, so the number of companies is
  announced before the names.
- The muted treatment is decorative and reverses on **keyboard focus** as well as
  hover — a reveal that only answers to a pointer is a mouse-only affordance.
- The filter transition is disabled under `prefers-reduced-motion`.
- Nothing moves. A scrolling logo wall would need a pause control (WCAG 2.2.2) and
  would read its cloned logos twice to a screen reader; a wall that simply sits
  there has neither problem and is easier to read.

## Keyboard Interaction

None of its own. If you wrap a logo in a link it keeps its normal tab behavior,
and focusing it reveals its full color.
