What is a loose tile?
In Metro design language when we show a list of tiles that are representing options to choose to a user, we want to give user a feeling of an unstable state. This means user should not stay at such page/state for a long time because in Metro design language content is center of user experience and we want to let user reach content she want as soon as possible. Metro gives this unstable state feeling by making tiles react to touch/click like they are not firmly sticked in their place. If you ever used Windows 8 you know how does it feel
Using CSS3 Transforms
I used CSS3 transforms to rotate tiles around X and Y axises and JavaScript to determine which axis and which direction I should rotate the tile.
CSS for different axis and directions of rotations based on point of interaction:
.top:active { -webkit-transform: rotateX(10deg); -moz-transform: rotateX(10deg); -ms-transform: rotateX(10deg); -o-transform: rotateX(10deg); transform: rotateX(10deg); } .bottom:active { -webkit-transform: rotateX(-10deg); -moz-transform: rotateX(-10deg); -ms-transform: rotateX(-10deg); -o-transform: rotateX(-10deg); transform: rotateX(-10deg); } .left:active { -webkit-transform: rotateY(-10deg); -moz-transform: rotateY(-10deg); -ms-transform: rotateY(-10deg); -o-transform: rotateY(-10deg); transform: rotateY(-10deg); } .right:active { -webkit-transform: rotateY(10deg); -moz-transform: rotateY(10deg); -ms-transform: rotateY(10deg); -o-transform: rotateY(10deg); transform: rotateY(10deg); } .center:active { -webkit-transform: scale(0.96); -moz-transform: scale(0.96); -ms-transform: scale(0.96); -o-transform: scale(0.96); transform: scale(0.96); }
JavaScript Code to apply proper CSS class based on mouse position:
function mousemoveHandler (event) { var regions = { top: { x1: this.offsetLeft + this.offsetWidth * 1/3, x2: this.offsetLeft + this.offsetWidth * 2/3, y1: this.offsetTop, y2: this.offsetTop + this.offsetHeight * 1/3 }, right: { x1: this.offsetLeft + this.offsetWidth * 2/3, x2: this.offsetLeft + this.offsetWidth, y1: this.offsetTop, y2: this.offsetTop + this.offsetHeight }, bottom: { x1: this.offsetLeft + this.offsetWidth * 1/3, x2: this.offsetLeft + this.offsetWidth * 2/3, y1: this.offsetTop + this.offsetHeight * 2/3, y2: this.offsetTop + this.offsetHeight }, left: { x1: this.offsetLeft, x2: this.offsetLeft + this.offsetWidth * 1/3, y1: this.offsetTop, y2: this.offsetTop + this.offsetHeight }, center: { x1: this.offsetLeft + this.offsetWidth * 1/3, x2: this.offsetLeft + this.offsetWidth * 2/3, y1: this.offsetTop + this.offsetHeight * 1/3, y2: this.offsetTop + this.offsetHeight * 2/3 } }; for (var region in regions) { this.classList.remove(region); if (regions[region].x1 < event.pageX && event.pageX < regions[region].x2 && regions[region].y1 < event.pageY && event.pageY < regions[region].y2) { this.classList.add(region); } } this.parentElement.style.webkitPerspectiveOriginX = this.offsetLeft + this.offsetWidth / 2 + "px"; this.parentElement.style.webkitPerspectiveOriginY = this.offsetTop + this.offsetHeight / 2 + "px"; }
Demo
Here is demo of loose tiles: Loose Tiles