<div class='card'></div>
$img: url(https://assets.codepen.io/2017/tiger_attitude.jpg);
$card-a: 2;
$card-b: 3;
$card-f: $card-b/$card-a;
$card-t: .25s;
$card-min: 9em;
$card-val: 80;
$card-max: 32em;
$card-ang: 10deg;

@property --i {
	syntax: '<number>';
	initial-value: .5;
	inherits: false
}

@property --j {
	syntax: '<number>';
	initial-value: .5;
	inherits: false
}

body {
	display: grid;
	margin: 0;
	height: 100vh;
	perspective: 35em;
	background: #333
}

.card {
	--card-w: clamp(#{$card-min}, calc(#{$card-val}*1vw), #{$card-max});
	--card-h: calc(#{$card-f}*var(--card-w));
	--card-r: calc(.25*var(--card-w));
	--x: calc(var(--i)*100%);
	--y: calc(var(--j)*100%);
	place-self: center;
	border: solid .25em #ddd;
	width: var(--card-w); height: var(--card-h);
	border-radius: .5em;
	box-shadow: 4px 4px 23px #000;
	background: 
		radial-gradient(circle at var(--x, 50%) var(--y, 50%), 
				#000 calc(var(--card-r) - 1px), #fff var(--card-r)) border-box, 
		$img 50%/ cover;
	background-blend-mode: exclusion;
	transition: $card-t cubic-bezier(.13, 1, .5, 1);
	transition-property: --i, transform, --j;
	
	&:hover {
		transform: 
			rotatex(calc((var(--j) - .5)*#{$card-ang})) 
			rotatey(calc((.5 - var(--i))*#{$card-ang}))
	}
	
	@media (min-aspect-ratio: #{$card-a}/#{$card-b}) {
		--card-h: clamp(#{$card-f*$card-min}, calc(#{$card-val}*1vh), #{$card-f*$card-max});
		--card-w: calc(var(--card-h)/#{$card-f});
	}
}
View Compiled
/*
Created for my Taming Blend Modes: `difference` and `exclusion` (https://css-tricks.com/taming-blend-modes-difference-and-exclusion/) article on CSS-Tricks - check it out for context!
*/

const _CARD = document.querySelector('.card');

let rect;

function setRect() { rect = _CARD.getBoundingClientRect() }

function getRatio(v0, v1, r) { return +Math.min(1, Math.max(0, (v0 - v1)/r)).toFixed(2) }

setRect();

addEventListener('resize', e => setRect, false);

_CARD.addEventListener('mousemove', e => {
	_CARD.style.setProperty('--i', getRatio(e.clientX, rect.left, rect.width));
	_CARD.style.setProperty('--j', getRatio(e.clientY, rect.top, rect.height))
}, false);
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.