1

I know this is another centering question but I think this is different to any of the others on StackOverflow. Before anyone says it yes I have searched for a solution but found nothing.

To get my point across better I've mocked up an image to give you an idea of what I would like my image to do: http://cl.ly/1q143w1P2p19322s2L0s

The problem

I have a fluid, full browser width layout. For this question and to explain it better my image is set at 400% width (height calculated automatically to maintain its aspect ratio). So therefore the image will fill the entire screen (and more). Every method I have tried makes the image scale from the top left of the parent/wrapper of the container so the top left hand side of the image is always in view but I don't want this to happen.

Instead, I want the exact center of my image to always be on view when you resize the browser. No matter the height or width of the browser window.

I hope that all makes sense, its quite hard to explain. I've tried pure CSS solutions so far but no luck so far. Can jQuery help me?

--

I have tried this technique (http://css-tricks.com/centering-in-the-unknown/) but the image scales from the top left of the image, which isn't what I want.

egr103
  • 3,858
  • 15
  • 68
  • 119
  • It's quite a common problem when people are trying to make a zoom feature, you might find answers in that sort of location. – Orbling Mar 01 '12 at 16:20
  • jquery: .offset(), .height() and .width() should be all you need to calculate the center of every element. – ggzone Mar 01 '12 at 16:32

1 Answers1

2

If all you are trying to achieve is keeping the centre of an image in a constant position, then you just need to adjust the top and left properties of the image, so that the centre of the image lies in the middle of the surrounding frame.

The calculation is simply finding the midpoint of your frame, which is half way along it, and subtracting half the width of the image to find your left position, the same with heights for the top position.

I have made you a demonstration program to show you, change the widths in the box, maximum of 500, and you will see the image stays centred.

Demo: http://jsfiddle.net/Orbling/ZZrjP/

Centred Image - 200x200 Centred Image - 200x200

Centred Image - 400x400 Centred Image - 400x400

I am using the #outer-frame to represent your window, or outer div of your website, the #image-frame is whatever size you want the image to appear at. If you want your image to occupy the full window, dispense with the concept of the outer frame and use the window as your image frame.

HTML:

<div id="outer-frame">
    <div id="image-frame">
        <img src="http://fc01.deviantart.net/fs50/f/2009/317/f/4/Colour_Spiral_by_Deatant2.jpg" alt="Spiral by Deatant2" width="1280" height="736" />
    </div>
</div>
<div id="controls">
    Width: <input type="text" id="iwidth" name="iwidth" value="200" />
    Height: <input type="text" id="iheight" name="iheight" value="200" />
</div>

CSS:

#outer-frame { width: 500px; height: 500px; margin: 10px; border: 1px dashed black; }
#image-frame { width: 200px; height: 200px; overflow: hidden; position: relative; }
#image-frame img { position: relative; }
#controls { margin: 10px 10px 0 10px; }
#controls input { width: 80px; }

Note the position: relative;​ directives, these ensure the positions are relative to the container, if they were relative to the page, the calculations would need to be offset.

jQuery:

$('#image-frame').bind('reposition-image', function() {
    var imageFrame = $(this);
    var outerFrame = $('#outer-frame');
    var image = imageFrame.find('img');

    var frameWidth = imageFrame.width();
    var frameHeight = imageFrame.height();

    // center image frame
    imageFrame.css({ left: (outerFrame.width() / 2) - (imageFrame.width() / 2),
                     top:  (outerFrame.height() / 2) - (imageFrame.height() /2)});

    // position image in frame
    image.css({ left: (imageFrame.width() / 2) - (image.attr('width') / 2),
                top: (imageFrame.height() / 2) - (image.attr('height') / 2)});
}).trigger('reposition-image');

$('#controls input').change(function() {
    var jThis = $(this);
    var cDim = jThis.attr('id').replace(/^i/, '');

    var nSize = parseInt(jThis.val());

    if (!isNaN(nSize) && nSize != 0) {
        var outerFrame = $('#outer-frame');
        nSize = (nSize > outerFrame[cDim]() ? outerFrame[cDim]() : nSize);        
        $('#image-frame')[cDim](nSize).trigger('reposition-image');
    }
});
​
Orbling
  • 20,413
  • 3
  • 53
  • 64
  • Thats quite a reply. Thanks for taking the time to answer. You mentioned above "If you want your image to occupy the full window, dispense with the concept of the outer frame and use the window as your image frame". How would I alter your JS to remove this outer frame and substitute with the window width? I should hopefully be able to change your reference from pixels to percentages. Thanks for your detailed reply. I think I could work with this. Cheers. – egr103 Mar 01 '12 at 19:51
  • @egr103: How do you mean percentages? – Orbling Mar 01 '12 at 21:39
  • @egr103: As for using the window, it depends where you have your image in your HTML. If the image is inside a `
    ` that takes up the whole window, then all you need to do, for a one off positioning, is use the couple of lines after the "position image in frame" comment, setting `imageFrame` to a selector matching your `
    ` and `image` to a selector matching your ``. If the `` is directly in the ``, then use `$(window)` instead of `imageFrame`.
    – Orbling Mar 01 '12 at 21:43
  • @egr103: As the question said jQuery, I assumed you were familiar with it. Should have read the question more thoroughly to find out you were more a design-end person with the CSS preference; I would have simplified the example considerably, as the code is quite advanced. Using CSS only to do it would be tricky at best, if possible at all. – Orbling Mar 01 '12 at 21:46
  • Yeah I am a designer more than a coder :) I've tried CSS but no luck whatsoever. Hence my question. I've edited the CSS & HTML to match the way my document is setup but not sure how to adjust the jQuery code to recreate your effect (minus the buttons of course): http://jsfiddle.net/FrW7u/ – egr103 Mar 02 '12 at 13:07
  • @egr103: Most of the complexity of the code was just the mechanics to get it to update nicely in the display, so you could see how it changes. But ofcourse, if you are a non-coder, it just confuses. This is the essence: http://jsfiddle.net/Orbling/FrW7u/2/ - the `#image-frame` bit should be at the body level, or you could just use `$(window)` instead for that bit to tie it to the window. Note it will not update automatically if the window is resized. That would require more code. – Orbling Mar 05 '12 at 20:59
  • @egr103: A secondary example for window resizing, it doesn't work inside jsFiddle, due to the way jsFiddle handles the frames. I made the routine a new event on the image frame, just so it can be called from anywhere. Note all these examples are jQuery code, you need jQuery loaded first. – Orbling Mar 05 '12 at 21:09
  • This is great @Orbling thanks! Two points. 1) How can I base the sizing on percentages? Currently if the image is smaller than the browser window, it doesn't stretch to fit the whole window, which is what I need. Is there a way to do this? I tried removing the fixed px sizes in the HTML and placing width 100% on the image within the CSS but the centering no longer works. 2) To ensure the image scales when the browser resizes, could I just use this code? or, are there better ways to get this setup? $(window).bind('resize',function(){ window.location.href = window.location.href; }); – egr103 Mar 06 '12 at 10:11
  • @egr103: That last bit of code causes the page to refresh on resize, most likely not what you want. I note I didn't post a link to my window resize version somehow, which was the whole point of the second message: http://jsfiddle.net/Orbling/FrW7u/3/ – Orbling Mar 06 '12 at 14:48
  • @egr103: That code does no scaling of the image, if you want it to center if bigger, and scale up if smaller. Then there would need to be a check as to the situation and alter the image dimensions to the window size in that case. Would need to know what to do about aspect ratio in that case, lock or stretch? – Orbling Mar 06 '12 at 14:50
  • I'm not to sure what you mean by lock or stretch @Orbling but as long as the images aspect ratio is maintained then thats the most important thing. It should maintain aspect ratio by width rather than height. Does that help at all? – egr103 Mar 06 '12 at 21:41
  • @egr103: Yes, maintaining aspect ratio, is aspect locked, not stretched out of shape. So always stretched to the width of the window if smaller than it, or centred and cropped when bigger. Doable, I'll sort it out shortly. – Orbling Mar 06 '12 at 22:42
  • That would be great if you could @Orbling I look forward to it :) Many thanks again for all your hard work! – egr103 Mar 07 '12 at 15:57
  • @egr103: See what this is like for you: http://jsfiddle.net/Orbling/FrW7u/7/ - it does not work 100% correctly in jsFiddle, but the code should be alright. The frame is automatically resized to the window size by the code, and the image is scaled aspect-locked, full-width, when smaller, or centred when larger. – Orbling Mar 07 '12 at 16:59
  • Thats great @Orbling thanks. Just curiosity more than anything, obviously the height of the image doesn't fill the div at certain points. Would it be hard to change so that the image grows to 200% (for example) at the same time as the window size is increased? Granted the image will get blown up but least the height of the box would be filled. Thoughts? – egr103 Mar 08 '12 at 09:19
  • @egr103: With that code, it should fill the whole window at all times with the image - with the proviso, that it locks the aspect ratio and matches the width. Do you mean that you would always like the window filled entirely? The way to do that is a slight change in the logic, finding the minimum size, aspect-locked, that will result in both dimensions being equal to or greater than the window size. http://jsfiddle.net/Orbling/FrW7u/10/ – Orbling Mar 09 '12 at 15:44