Skip to content

Instantly share code, notes, and snippets.

@phonx
Created January 20, 2017 02:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save phonx/ef5f71f402a9ddd7a440cda03281d600 to your computer and use it in GitHub Desktop.
Save phonx/ef5f71f402a9ddd7a440cda03281d600 to your computer and use it in GitHub Desktop.
movey backgrounds grid
<div class="box">
<div class="image-wrap">
<div class="image image-0"></div>
</div>
<div class="border"></div>
<div class="text">
<span>Sugar plum</span>
</div>
</div>
<div class="box">
<div class="image-wrap">
<div class="image image-1"></div>
</div>
<div class="border"></div>
<div class="text">
<span>apple pie</span>
</div>
</div>
<div class="box">
<div class="image-wrap">
<div class="image image-2"></div>
</div>
<div class="border"></div>
<div class="text">
<span>gummy bears</span>
</div>
</div>
<div class="box">
<div class="image-wrap">
<div class="image image-3"></div>
</div>
<div class="border"></div>
<div class="text">
<span>sesame snaps</span>
</div>
</div>
<div class="box">
<div class="image-wrap">
<div class="image image-4"></div>
</div>
<div class="border"></div>
<div class="text">
<span>chupa chups</span>
</div>
</div>
<div class="box">
<div class="image-wrap">
<div class="image image-5"></div>
</div>
<div class="border"></div>
<div class="text">
<span>chocolate cookie</span>
</div>
</div>
<div class="box">
<div class="image-wrap">
<div class="image image-6"></div>
</div>
<div class="border"></div>
<div class="text">
<span>cheescake muffin</span>
</div>
</div>
<div class="box">
<div class="image-wrap">
<div class="image image-7"></div>
</div>
<div class="border"></div>
<div class="text">
<span>sweet toffee</span>
</div>
</div>
<div class="box">
<div class="image-wrap">
<div class="image image-8"></div>
</div>
<div class="border"></div>
<div class="text">
<span>carrot cake</span>
</div>
</div>
<div class="box">
<div class="image-wrap">
<div class="image image-9"></div>
</div>
<div class="border"></div>
<div class="text">
<span>lollipop</span>
</div>
</div>
<div class="box">
<div class="image-wrap">
<div class="image image-10"></div>
</div>
<div class="border"></div>
<div class="text">
<span>macaroon</span>
</div>
</div>
<div class="box">
<div class="image-wrap">
<div class="image image-11"></div>
</div>
<div class="border"></div>
<div class="text">
<span>lemon tart</span>
</div>
</div>
<div class="unsplash-info">all images in this demo are from <a target="_blank" href="https://unsplash.com">unsplash.com</a></div>

movey backgrounds grid

That effect where the background moves when you hover over an image.

No libraries, I tried to use as little JS as possible, and add comments.

A Pen by Rachel Smith on CodePen.

License.

// for storing mouse x / y position
var mousePos = {
x: -10,
y: -10
};
// select the .box DOM elements
var boxElements = document.getElementsByClassName('box');
// create an array of objects to store the box elements and their image
// positions
var boxes = [];
for (var i = 0; i < boxElements.length; i++) {
boxes.push({
el: boxElements[i],
targetX: 0,
targetY: 0,
prevX: 0,
prevY: 0,
x: 0,
y: 0,
left: boxElements[i].offsetLeft,
top: boxElements[i].offsetTop,
size: boxElements[i].offsetWidth
})
}
function mousemove(e) {
// update mouse position
mousePos.x = e.pageX;
mousePos.y = e.pageY;
}
function updateBox(box) {
// check if mouse is in box area
if (mousePos.x > box.left && mousePos.x < (box.left+box.size) &&
mousePos.y > box.top && mousePos.y < (box.top+box.size)) {
// the mouse is in the space over the box - update the box image target position dependent on how far the mouse position is from the center of the box (box size/2)
box.targetX = (box.size/2 - (mousePos.x - box.left)) * 0.1;
box.targetY = (box.size/2 - (mousePos.y - box.top)) * 0.1;
} else {
// otherwise the box isn't being hovered, its target is 0
box.targetX = 0;
box.targetY = 0;
}
// update the image element position by lerping position to target
// http://codepen.io/rachsmith/post/animation-tip-lerp
box.x += (box.targetX - box.x)*0.2;
box.y += (box.targetY - box.y)*0.2;
// check that the values aren't really small already, to overcome javascripts poor handling of high precision math
if(Math.abs(box.x) < .001) box.x = 0;
if(Math.abs(box.y) < .001) box.y = 0;
// only update CSS if the position has changed since last loop
if (box.prevX !== box.x && box.prevY !== box.y) {
// update css of image element
box.el.children[0].children[0].style.transform = 'translate3d('+box.x+'px, '+box.y+'px, 0)';
}
// update prev values for next comparison
box.prevX = box.x;
box.prevY = box.y;
}
function loop() {
// in the loop - updated each of the boxes
for (var i = 0, l = boxes.length; i < l; i++) {
updateBox(boxes[i]);
}
requestAnimationFrame(loop);
}
function resize() {
// the box positions/sizes have updated on resize, so they need to be
// reset
for (var i = 0; i < boxes.length; i++) {
boxes[i].left = boxes[i].el.offsetLeft;
boxes[i].top = boxes[i].el.offsetTop;
boxes[i].size = boxes[i].el.offsetWidth;
}
}
// attach the mouse event listener to the document
document.addEventListener('mousemove', mousemove);
// listen for resize event, so box sizes can be updated
window.addEventListener('resize', resize);
// run the animation loop
loop();
html, body {
width: 100%;
}
body {
font-size: 40px;
font-family: 'Bungee Shade', cursive;
color: #222;
background: #222;
}
.box {
position: relative;
overflow: hidden;
cursor: pointer;
float: left;
&:hover {
.border {
transform: scale(0.94);
transition-duration: 140ms;
}
.text {
opacity: 1;
transform: translate3d(0,0,0);
transition-duration: 140ms;
}
.image-wrap {
transform: scale(1);
opacity: 1;
transition-duration: 140ms;
}
}
}
.border, .text, .image {
width: 100%;
height: 100%;
position: absolute;
pointer-events: none;
}
.image-wrap {
position: absolute;
width: 130%;
height: 130%;
left: -15%;
top: -15%;
transform: scale(0.8);
transition: 280ms ease-out;
pointer-events: none;
opacity: 0.74;
}
.border {
left: -30px;
top: -30px;
border: 30px solid #222;
box-sizing: content-box;
transition: 360ms ease-in-out;
}
.text {
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transform: translate3d(0, -4%, 0);
transition: 280ms ease-out;
text-align: center;
}
.unsplash-info {
background: #111;
color: #fff;
width: 100%;
position: fixed;
bottom: 0px;
font-family: Arial, sans-serif;
font-size: 14px;
padding: 2px 8px;
a {
text-decoration: none;
color: #eee;
}
}
/* box sizing */
.box {
width: 100%;
height: 100vw;
float: left;
}
@media (min-width: 500px) {
.box {
width: 50%;
height: 50vw;
}
}
@media (min-width: 800px) {
.box {
width: 33.333333%;
height: 33.33333vw;
}
}
@media (min-width: 1200px) {
.box {
width: 25%;
height: 25vw;
}
}
/* image backgrounds */
.image-0 {
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/53148/box-image_0.jpg);
}
.image-1 {
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/53148/box-image_1.jpg);
}
.image-2 {
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/53148/box-image_2.jpg);
}
.image-3 {
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/53148/box-image_3.jpg);
}
.image-4 {
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/53148/box-image_4.jpg);
}
.image-5 {
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/53148/box-image_5.jpg);
}
.image-6 {
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/53148/box-image_6.jpg);
}
.image-7 {
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/53148/box-image_7.jpg);
}
.image-8 {
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/53148/box-image_8.jpg);
}
.image-9 {
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/53148/box-image_9.jpg);
}
.image-10 {
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/53148/box-image_10.jpg);
}
.image-11 {
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/53148/box-image_11.jpg);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment