Skip to content

Team Cards with Grayscale to Color Photo Hover

Pure CSS team section where grayscale portraits turn to full color, zoom in slightly and reveal social links on hover or keyboard focus.

Live preview

Open in new tab

Code

A warm, editorial team section built with pure CSS: four portrait cards start in black and white and fade into full color when you hover or focus them, while a row of round social links slides up over the photo. It fits agency, studio and startup about pages where you want the team to feel calm and consistent until a visitor shows interest in one person.

How it works

The root section.tgp-team contains a .tgp-header (eyebrow, title and intro) and a ul.tgp-grid of li.tgp-card items. Each card has a .tgp-photo box with a fixed aspect-ratio: 4 / 5, the portrait img with object-fit: cover, and a ul.tgp-social list of three .tgp-social-link icons, followed by the .tgp-name heading and .tgp-role.

The grayscale effect is a single custom property. The image uses filter: grayscale(var(--tgp-gray)), and --tgp-gray switches from 1 to 0 on .tgp-card:hover, on :focus-within and on the default .is-active card. The same states scale the photo by --tgp-zoom, fade in a dark gradient (.tgp-photo::after) for icon contrast, slide .tgp-social up into view and widen the accent line under .tgp-name.

The second card carries is-active so the first view (and the page thumbnail) shows the effect. As soon as the pointer enters the grid or another card receives focus, rules based on .tgp-grid:hover and .tgp-grid:has(.tgp-card:focus-within) return that card to grayscale, so only one person is highlighted at a time. On touch screens (hover: none) photos are shown in color and the links stay visible. No JavaScript is needed.

Customization

  • --tgp-accent on .tgp-team: the terracotta color of the eyebrow, the line under each name and the social link hover state.
  • --tgp-bg and --tgp-card: page background and card background.
  • --tgp-speed: duration of the color fade and the slide, e.g. 0.3s for a quicker reveal.
  • --tgp-zoom: zoom of the photo in the revealed state; set it to 1 to disable the zoom.
  • --tgp-radius: the photo corner radius (the card radius follows it).
  • Move is-active to another .tgp-card, or remove it, to change which portrait is in color on load.
  • aspect-ratio on .tgp-photo: use 1 / 1 for square portraits.
  • grid-template-columns in the .tgp-grid media queries: one column on phones, two from 540px, four from 960px.

Accessibility

The section is labelled by its heading, and every portrait has a descriptive alt text with the person's name. Social links are real anchors with an aria-label such as "Sofia on LinkedIn", and each list has its own label. Because the reveal also reacts to :focus-within, keyboard users see the links appear when they Tab into a card, and every link shows an accent outline. With prefers-reduced-motion: reduce the transitions and the zoom are switched off; the color change still happens instantly.

Usage notes

The portraits come from Unsplash; replace them with your own team photos, ideally cropped to the same 4:5 ratio. The :has() rule needs a current browser; older browsers simply keep the default card in color while another card is focused.

Requirements

No dependencies. Pure HTML, CSS and JavaScript.

Team Cards with Grayscale to Color Photo Hover – Pure CSS team sections component screenshot
Team Cards with Grayscale to Color Photo Hover · Pure CSS Team Sections

More Team Sections

Team Cards with Hover Info – Bootstrap 5 team sections preview

Team Cards with Hover Info

Bootstrap 5 team section with portrait cards that reveal a bio and social links on hover or keyboard focus. Pure CSS, no JavaScript.

Team Grid – Tailwind CSS team sections preview

Team Grid

Dark Tailwind CSS team section with portrait photos, roles, short bios, accessible social links and a hiring card.