DEV Community

Cover image for Steam-like Card Interaction by Vanilla JS and CSS
Chell
Chell

Posted on

Steam-like Card Interaction by Vanilla JS and CSS

Steam trading cards are randomly collectible cards during gameplay. It's not a pleasure to have all cards collected since players have to exchange their cards with others (or buy them), but interacting with cards on the game page can be interesting.

steam trading card interaction

I made a similar interaction with a few tweaks.

preview

Four parts of the trading card are changing — size, perspective, filter, and shadow.

Perspective

To reproduce the effect, the powerful CSS 3D transform feature has to be involved. The dynamic perspective of the card will imply hovering and moving actions.

There are two ways to activate 3D mode for an HTML element, by perspective or transform: perspective() in CSS. The former one is used by the parent element, which creates a 3D space for its child elements, while the latter one is for a single element. David DeSandro has a great series explaining CSS 3D, go check that if you want to go down the rabbit hole.

  • transform: perspective(400px) rotateY(45deg)

  • perspective: 400px

Rotation

As their names suggest, rotateX(), rotateY(), and rotateZ() can be used to rotate an element in 3D space. If perspective is not enabled, rotate functions will only perform a parallel projection, which is not the case we desire.

rotate function

The rotation degree adjusts proportionally to cursor position and mousemove, which is fired at an element when a mouse is moved while the cursor's hotspot is inside it, is the event to detect that. It is different from mouseenter, which indicates the moment the cursor moves in an element.

card.addEventListener("mousemove", function (event) {
  card.style.transform = `perspective(1000px)
  rotateY(${rotate(event.x, centerX)}deg)
  rotateX(${-rotate(event.y, centerY)}deg)`;
})
Enter fullscreen mode Exit fullscreen mode

The rotation degree can be calculated by the relative position of the cursor and card center. A threshold is needed here to avoid a large rotation degree, in which case the card may turn very thin and impossible to hover above.

function rotate(cursorPosition, centerPosition, threshold = 20) {
  if (cursorPosition - centerPosition >= 0) {
    return (cursorPosition - centerPosition) >= threshold ? threshold : (cursorPosition - centerPosition);
  } else {
    return (cursorPosition - centerPosition) <= -threshold ? -threshold : (cursorPosition - centerPosition);
  }
}
Enter fullscreen mode Exit fullscreen mode

Brightness

As you slide up and down on the card, you will notice a change in the reflection effect. This is not some kind of gradient color overlay effect, but a brightness filter.

function brightness(cursorPositionY, centerPositionY, strength = 50) {
  return 1 - rotate(cursorPositionY, centerPositionY)/strength;
}
// ...
card.style.filter = `brightness(${brightness(event.y, centerY)})`;
Enter fullscreen mode Exit fullscreen mode

Shadow

The shadow is a key part of this interaction and is oriented in the opposite direction of the cursor. I applied a large blur-radius here as Steam does.

card.style.boxShadow = `${-rotate(event.x, centerX)}px ${-rotate(event.y, centerY)}px 80px 0px rgba(48, 65, 0, 0.5)`;
Enter fullscreen mode Exit fullscreen mode

Add transition in CSS to make everything feels smooth.

#card {
    transition: .2s;
}
Enter fullscreen mode Exit fullscreen mode

When everything is finished, make sure the card restores to the initial look after the cursor leaves the area.

card.addEventListener("mouseleave", function (event) {
  card.style.transform = `perspective(500px)`;
  card.style.width = `120px`;
  card.style.height = `160px`;
  card.style.filter = `brightness(1)`;
  card.style.boxShadow = `0 0 0 0 rgba(48, 65, 0, 0.5)`;
})
Enter fullscreen mode Exit fullscreen mode

Thank you for reading this. You can view the result below:

  1. Source Code: https://github.com/imchell/steam-like-card-curation
  2. Preview (open with desktop browser): https://steam-like-card-curation.vercel.app/

Top comments (0)