Saturday 6 April 2013

Aligning and element with background-size:cover

The CSS property background-size:cover is incredibly useful but due to the nature of it resizing in different directions, it's difficult to pinpoint where a particular part of the image is on the background at any given time. Difficult but not impossible of course.

To do this you first need to understand how background-size:cover works. Basically the image will fill the screen at all times by stretching out while maintaining aspect ratio. This means that unless the window is perfectly sized to fit the image, either the image is going to be cut off at the top and bottom edges, or the left and right edges.

Given this we can calculate the scale of the image and the x or y offset to find out the actual coordinates of the target location. I've created a little example using Google's logo that positions a red dot inside the red 'o' character. Resizing the window will keep the red dot inside the 'o' no matter how you resize the window.


Demo on jsFiddle

<div id="pointer"></div>
body {
    background:url( no-repeat center center fixed;

#pointer {
var image = { width: 550, height: 190 };
var target = { x: 184, y: 88 };

var pointer = $('#pointer');


function updatePointer() {
    var windowWidth = $(window).width();
    var windowHeight = $(window).height();

    // Get largest dimension increase
    var xScale = windowWidth / image.width;
    var yScale = windowHeight / image.height;
    var scale;
    var yOffset = 0;
    var xOffset = 0;

    if (xScale > yScale) {
        // The image fits perfectly in x axis, stretched in y
        scale = xScale;
        yOffset = (windowHeight - (image.height * scale)) / 2;
    } else {
        // The image fits perfectly in y axis, stretched in x
        scale = yScale;
        xOffset = (windowWidth - (image.width * scale)) / 2;

    pointer.css('top', (target.y) * scale + yOffset);
    pointer.css('left', (target.x) * scale + xOffset);