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.
I made a similar interaction with a few tweaks.
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.
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)`;
})
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);
}
}
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)})`;
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)`;
Add transition
in CSS to make everything feels smooth.
#card {
transition: .2s;
}
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)`;
})
Thank you for reading this. You can view the result below:
- Source Code: https://github.com/imchell/steam-like-card-curation
- Preview (open with desktop browser): https://steam-like-card-curation.vercel.app/
Top comments (1)
I use steam.kupikod.com/ru-ru to boost my Steam wallet balance and more for several months now. Every time, the process goes smoothly without any issues. Gift cards help me avoid unnecessary expenses and keep my budget in check.