<svg viewBox='0 0 100 100' preserveAspectRatio='xMidYMid slice'>
    <defs>
        <mask id='mask-1' x='0' y='0' width='100' height='100'>
            <rect x='0' y='0' width='100%' height='100%' fill='#000' />
            <circle cx='50' cy='50' r='20' fill='#fff' />
        </mask>
    </defs>
    <g width='100' height='100' >
        <rect x='0' y='0' width='100%' height='100%' fill='#ccc' />
        <image x='20%' y='20%' width='60%' height='60%' href='https://picsum.photos/id/1020/800/800' />
    </g>
    <g width='100' height='100' mask='url(#mask-1)'>
        <rect x='0' y='0' width='100%' height='100%' fill='#fff' />
        <image x='20%' y='20%' width='60%' height='60%' href='https://picsum.photos/id/1025/800/800' />
    </g>
</svg>
body {
    overflow: hidden;
}

svg {
    display: block;
    height: 100vh;
    width: 100vw;
}
View Compiled
const svg = document.querySelector('svg');
const circle = document.querySelector('circle');
const images = document.querySelectorAll('image');

function updateSize() {
    const width = window.innerWidth;
    const height = window.innerHeight;
    const size = Math.min(width, height);

    svg.setAttribute('viewBox', `0 0 ${width} ${height}`);
    circle.setAttribute('r', size / 5);
}

updateSize();

window.addEventListener('resize', updateSize);

window.addEventListener('mousemove', (e) => {
    circle.setAttribute('cx', e.clientX);
    circle.setAttribute('cy', e.clientY);
});
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.