84

I would like to center an img inside a div without javascript and without background-images.

Here is some example code

<div> 
    <img src="/happy_cat.png"/> 
</div>
  • I don't know the size of the img and it should be able to exceed the width of the parent
  • I don't know the width of the parent div (it is 100%)
  • The parent div has a fixed height
  • The image is larger than the parent and the parent has overflow:hidden
  • Only need to support modern browsers

Desired result. (Ignore opacities etc, just note the positioning).

enter image description here

I know this can be done easily with background images but that isn't an option for me. I could also use javascript but it seems like a very heavy handed way to achieve this.

Thanks!

Jack

JackMahoney
  • 3,423
  • 7
  • 32
  • 50
  • 3
    I dont think this can be done using CSS alone. Are you open to jquery/js solutions for the same? – Roy M J Oct 30 '13 at 05:23
  • 1
    I only want to use JS here as a last result. If after investigation this is impossible then I will bow out and use JS but I'm sure this can be done with some nifty modern CSS3. – JackMahoney Oct 30 '13 at 05:26
  • @JackMahoney One question: is the dimension (or specifically, height — since the width is 100% already) of the parent `
    ` determined by the inside image alone?
    – Terry Oct 30 '13 at 08:24
  • Good question. The height of the parent is known and fixed. – JackMahoney Oct 30 '13 at 22:22
  • possible duplicate of [center oversized image in div](http://stackoverflow.com/questions/14562457/center-oversized-image-in-div) – dayuloli Jan 26 '15 at 02:54

6 Answers6

110

What about this:

.img {
   position: absolute;
   left: 50%;
   top: 50%;
   -webkit-transform: translateY(-50%) translateX(-50%);
}

This assumes that the parent div is positioned relatively. I think this works if you want the .img relatively positioned rather than absolutely. Just remove the position: absolute and change top/left to margin-top and margin-left.

You'll probably want to add browser support with transform, -moz-transform etc.

Evan Layman
  • 3,691
  • 9
  • 31
  • 48
  • 3
    Ha - you know what this actually works! Thanks man. What an interesting solution. :) – JackMahoney Nov 05 '13 at 23:43
  • I learned about the translate centering recently and it's awesome! Glad it helped you out. – Evan Layman Nov 07 '13 at 06:49
  • 1
    You have no idea how much time you saved me! – 0x_Anakin Nov 03 '14 at 03:17
  • 4
    This works great, but if you want an IE8-compatible version, you should use the answer [here](http://stackoverflow.com/a/19414020/2317532) – dayuloli Jan 26 '15 at 02:55
  • The best answer for align center problem! Thank you! – Davuz May 26 '15 at 07:30
  • 1
    This method is not perfect, cuz if u change margin-top to 50%, the 50% is based on the parent width but not the parent height(assume the parent width is not equal to its height), so it will make a wrong margin-top. What do u say about this situation? – Soon Sep 20 '16 at 10:23
  • @Soon - CSS is still not completely flexible, so I think you'll have to have more knowledge of your elements when defining your CSS, or use some post-processing in javascript to manage that use-case. Good luck! – Evan Layman Jan 16 '17 at 23:18
  • this still used in 2020? any "better" alternative? – zok Jul 22 '20 at 16:59
62

Old question, new answer:

When the image is larger than the wrapping div, a text-align:center or margin:auto is not going to work. But if the image is smaller, then solutions with absolute positioning or a negative left margin are going to produce weird effects.

So when the image size is actually not known in advance (like on a CSM) and it might be larger or smaller than the wrapping div, there is an elegant CSS3 solution that serves all purposes:

div {
    display: flex;
    justify-content: center;
    height: 400px; /* or other desired height */
    overflow: hidden;
}
img {
    flex: none; /* keep aspect ratio */
}

Note that depending on other rules in your stylesheet, you might need to append width:auto and/or max-width:none to the img.

RavanH
  • 791
  • 5
  • 5
2

This is always a bit tricky and there are many solutions out there. I find the best solution to be the following. This centers it both vertically and horizontally.

CSS

#container {
    height: 400px;
    width: 400px;
}
.image {
    background: white;
    width: 100%;
    height: 100%;
    position: relative;
    overflow: hidden;
}

.left {
    width: 100px;
    height: 100%;
    z-index: 2;
    background: white;
    top: 0px;
    position: absolute;
    left: 0px;
}
.right {
    width: 100px;
    height: 100%;
    z-index: 2;
    position: absolute;
    background: white;
    top: 0px;
    right: 0px;
}
.image img {
    margin: auto;
    display: block;
}

HTML

    <div id="container">
<div class="image">
    <div class="left"></div>
    <div class="right"></div>
    <img width="500" src="https://www.google.com.au/images/srpr/logo11w.png" />
</div>

See fiddle

slightly different technique: Fiddle

bicycle
  • 8,315
  • 9
  • 52
  • 72
  • This won't work as you have set an explicit width on the .centered container. I don't know any of the element's widths! – JackMahoney Oct 30 '13 at 04:44
  • If the img width is greater than it's container then the max-width doesn't help center it. http://jsfiddle.net/ZXUxv/1/ – JackMahoney Oct 30 '13 at 04:49
  • I don't think you understand my requirements (sorry if that sounds rude). Even if I set a max-width, if the image itself is larger than the container (which I want to allow for) then it will not be centered. I can't restrict the size of the image with a max-width. It needs to be larger than its parent *and* be centered within it. See the js fiddle in my last comment. It has a larger image and a max-width. – JackMahoney Oct 30 '13 at 05:03
  • @JackMahoney sorry i didn't see your comment. Please check the updated fiddle. It should do what you're asking. Otherwise I have no idea what you're asking. – bicycle Oct 30 '13 at 07:39
  • Sorry the updated fiddle still doesn't have an image that is centered in the parent. Thanks for your time anyway. See my image in the updated question if you are confused by the question. – JackMahoney Oct 30 '13 at 22:30
  • @JackMahoney It really does that, check the updated fiddle to see it more clearly. I think you just need to adjust it to have it fit into your layout needs. Other than this way, i have no idea... – bicycle Oct 31 '13 at 10:14
  • @JackMahoney see updated answer for a slightly different technique as well. Other than that im at a total loss lol Whenever the image is wider than the parent, it gets overflowed at the right side, it's always like that. In order to circumvent that you need to know the image dimensions so you could absolute position it according to the screen rather than the parent relative div. However you can't know the dimensions without javascript :s Good luck! – bicycle Oct 31 '13 at 10:30
  • Thanks for your help man, I'll use JS instead. Hopefully one day this is address in CSS! – JackMahoney Oct 31 '13 at 22:45
2

Thanks everyone for your help. I'm going to consider this unachievable in CSS only.

I will move to a jQuery solution. Here is some [pseudo]code for those interested.

I was going to give up on a CSS solution but looks like it can be done (see accepted answer). Here is the JS solution I was going to go with.

var $img = $('img'),
    w = $img.width();

$img.css({marginLeft: -w});

And the accompanying css

img{
  position:absolute;
  left:50%;
}
JackMahoney
  • 3,423
  • 7
  • 32
  • 50
2

I know this is old but I also came up with a pure css solution very similar to the above.

.parent {
    float: left;
    position: relative;
    width: 14.529%; // Adjust to your needs
}

.parent img {
    margin: auto;
    max-width: none; // this was needed for my particular instance
    position: absolute;
    top: 11px; right: -50%; bottom: 0; left: -50%;
    z-index: 0;
}
1

Just initialize the position of your image as follow.

HTML :

<div> 
    <img id="img" src="/happy_cat.png"/> 
</div>

CSS :

#img {
    left: 0;
    right: 0;
}

Or look with a margin: auto;

This is for horizontal align. To align it vertically too, you can do a display: table-cell; to your <div> an then vertical-align: middle; but it's not a good practice beacause your <div> is not a table.

Emilie
  • 668
  • 1
  • 9
  • 21