Velvet Star Monitor

Standout celebrity highlights with iconic style.

news

How to vertically align an image inside a div

Writer Matthew Martinez

How can you align an image inside of a containing div?

Example

In my example, I need to vertically center the <img> in the <div> with class ="frame":

<div> <img src="" />
</div>

.frame's height is fixed and the image's height is unknown. I can add new elements in .frame if that's the only solution. I'm trying to do this on Internet  Explorer 7 and later, WebKit, Gecko.

See the jsfiddle here.

.frame { height: 25px; /* Equals maximum image height */ line-height: 25px; width: 160px; border: 1px solid red; text-align: center; margin: 1em 0;
}
img { background: #3A6F9A; vertical-align: middle; max-height: 25px; max-width: 160px;
}
<div class=frame> <img src="" height=250 />
</div>
<div class=frame> <img src="" height=25 />
</div>
<div class=frame> <img src="" height=23 />
</div>
<div class=frame> <img src="" height=21 />
</div>
<div class=frame> <img src="" height=19 />
</div>
<div class=frame> <img src="" height=17 />
</div>
<div class=frame> <img src="" height=15 /> </div>
<div class=frame> <img src="" height=13 /> </div>
<div class=frame> <img src="" height=11 /> </div>
<div class=frame> <img src="" height=9 /> </div>
<div class=frame> <img src="" height=7 /> </div>
<div class=frame> <img src="" height=5 /> </div>
<div class=frame> <img src="" height=3 /> </div>
4

37 Answers

12

The only (and the best cross-browser) way as I know is to use an inline-block helper with height: 100% and vertical-align: middle on both elements.

So there is a solution:

.frame { height: 25px; /* Equals maximum image height */ width: 160px; border: 1px solid red; white-space: nowrap; /* This is required unless you put the helper span closely near the img */ text-align: center; margin: 1em 0;
}
.helper { display: inline-block; height: 100%; vertical-align: middle;
}
img { background: #3A6F9A; vertical-align: middle; max-height: 25px; max-width: 160px;
}
<div> <span></span><img src="" height=250px />
</div>
<div> <span></span><img src="" height=25px />
</div>
<div> <span></span><img src="" height=23px />
</div>
<div> <span></span><img src="" height=21px />
</div>
<div> <span></span><img src="" height=19px />
</div>
<div> <span></span> <img src="" height=17px />
</div>
<div> <span></span> <img src="" height=15px />
</div>
<div> <span></span> <img src="" height=13px />
</div>
<div> <span></span> <img src="" height=11px />
</div>
<div> <span></span> <img src="" height=9px />
</div>
<div> <span></span> <img src="" height=7px />
</div>
<div> <span></span> <img src="" height=5px />
</div>
<div> <span></span> <img src="" height=3px />
</div>

Or, if you don't want to have an extra element in modern browsers and don't mind using Internet Explorer expressions, you can use a pseudo-element and add it to Internet Explorer using a convenient Expression, that runs only once per element, so there won't be any performance issues:

The solution with :before and expression() for Internet Explorer:

.frame { height: 25px; /* Equals maximum image height */ width: 160px; border: 1px solid red; white-space: nowrap; text-align: center; margin: 1em 0;
}
.frame:before,
.frame_before { content: ""; display: inline-block; height: 100%; vertical-align: middle;
}
img { background: #3A6F9A; vertical-align: middle; max-height: 25px; max-width: 160px;
}
/* Move this to conditional comments */
.frame { list-style:none; behavior: expression( function(t){ t.insertAdjacentHTML('afterBegin','<span></span>'); t.runtimeStyle.behavior = 'none'; }(this) );
}
<div><img src="" height=250px /></div>
<div><img src="" height=25px /></div>
<div><img src="" height=23px /></div>
<div><img src="" height=21px /></div>
<div><img src="" height=19px /></div>
<div><img src="" height=17px /></div>
<div><img src="" height=15px /></div>
<div><img src="" height=13px /></div>
<div><img src="" height=11px /></div>
<div><img src="" height=9px /></div>
<div><img src="" height=7px /></div>
<div><img src="" height=5px /></div>
<div><img src="" height=3px /></div>

How it works:

  1. When you have two inline-block elements near each other, you can align each to other's side, so with vertical-align: middle you'll get something like this:

    Two aligned blocks

  2. When you have a block with fixed height (in px, em or another absolute unit), you can set the height of inner blocks in %.

  3. So, adding one inline-block with height: 100% in a block with fixed height would align another inline-block element in it (<img/> in your case) vertically near it.
4

This might be useful:

div { position: relative; width: 200px; height: 200px;
}
img { position: absolute; top: 0; bottom: 0; margin: auto;
}
.image { min-height: 50px
}
2

matejkramny's solution is a good start, but oversized images have a wrong ratio.

Here's my fork:

Demo:

preview


HTML:

<div> <img src="foo"/>
</div>

CSS:

.frame { height: 160px; /* Can be anything */ width: 160px; /* Can be anything */ position: relative;
}
img { max-height: 100%; max-width: 100%; width: auto; height: auto; position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: auto;
}
1

A three-line solution:

position: relative;
top: 50%;
transform: translateY(-50%);

This applies to anything.

From here.

2

A pure CSS solution:

.frame { margin: 1em 0; height: 35px; width: 160px; border: 1px solid red; position: relative;
}
img { max-height: 25px; max-width: 160px; position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: auto; background: #3A6F9A;
}
<div class=frame> <img src="" height=250 />
</div>
<div class=frame> <img src="" height=25 />
</div>
<div class=frame> <img src="" height=23 />
</div>
<div class=frame> <img src="" height=21 />
</div>
<div class=frame> <img src="" height=19 />
</div>
<div class=frame> <img src="" height=17 />
</div>
<div class=frame> <img src="" height=15 />
</div>
<div class=frame> <img src="" height=13 />
</div>
<div class=frame> <img src="" height=11 />
</div>
<div class=frame> <img src="" height=9 />
</div>
<div class=frame> <img src="" height=7 />
</div>
<div class=frame> <img src="" height=5 />
</div>
<div class=frame> <img src="" height=3 />
</div>

Key stuff

// position: relative; - in .frame holds the absolute element within the frame
// top: 0; bottom: 0; left: 0; right: 0; - this is key for centering a component
// margin: auto; - centers the image horizontally & vertically
0

For a more modern solution, and if there is no need to support legacy browsers, you can do this:

.frame { display: flex; /** Uncomment 'justify-content' below to center horizontally. ✪ Read below for a better way to center vertically and horizontally. **/ /* justify-content: center; */ align-items: center;
}
img { height: auto; /** ✪ To center this image both vertically and horizontally, in the .frame rule above comment the 'justify-content' and 'align-items' declarations, then uncomment 'margin: auto;' below. **/ /* margin: auto; */
}
/* Styling stuff not needed for demo */
.frame { max-width: 900px; height: 200px; margin: auto; background: #222;
}
p { max-width: 900px; margin: 20px auto 0;
}
img { width: 150px;
}
<div> <img src="">
</div>

Here's a Pen using Flexbox:

EDIT 1/13/22

There's a better way to do this using CSS Grid and the place-content shorthand:

.frame-text-grid { display: grid; place-content: center; /** ✪ "place-content" is the shorthand for "align-content" and "justify-content". ✪ The "place-content" shorthand requires two values, the first one is for "align-content" and the second one for "justify-content". If only one value is present (like in this demo), then that single value is applied to both directions. ✪ Comment the "place-content: center;" declaration above to see how the elements are spread along the height of the container. **/
}
<div> <h2>Using Grid and <code>place-content</code></h2> <p>Only two lines are needed to center vertically and horizontally.</p>
</div>

Here's a Pen using CSS Grid:

0

This way you can center an image vertically (demo):

div{ height: 150px; // Internet Explorer 7 fix line-height: 150px;
}
img{ vertical-align: middle; margin-bottom: 0.25em;
}
0

Also, you can use Flexbox to achieve the correct result:

.parent { align-items: center; /* For vertical align */ background: red; display: flex; height: 250px; /* justify-content: center; <- for horizontal align */ width: 250px;
}
<div> <img src="" />
</div>
1

There is a super easy solution with flexbox!

.frame { display: flex; align-items: center;
}
3

Imagine you have

<div> <img src="#">
</div>

And css:

.wrap { display: flex;
}
.wrap img { object-fit: contain;
}
0

You could try setting the CSS of PI to display: table-cell; vertical-align: middle;

0

You can try the below code:

.frame{ display: flex; justify-content: center; align-items: center; width: 100%;
}
<div> <img src="" />
</div>
0

CSS Grid

If you want to align a single image vertically inside an image container you can use this:

.img-container { display: grid;
}
img { align-self: center;
}
.img-container { display: grid; grid-auto-flow: column; background: #BADA55; width: 1200px; height: 500px;
}
img.vertical-align { align-self: center;
}
<div> <img src="" /> <img src="" /> <img src="" />
</div>

If you want to align multiple images inside an image container you can use this:

.img-container { display: grid; align-items: center;
}
.img-container { display: grid; grid-auto-flow: column; align-items: center; background: #BADA55; width: 1200px; height: 500px;
}
<div> <img src="" /> <img src="" /> <img src="" />
</div>

Please note that I have used grid-auto-flow: column in both the cases because otherwise the elements wrap to a row with specifying explicit grid items. In the question code, I see the item centered horizontally too. In that case, just make use of the place-items: center instead of align-items: center.

0

Background image solution

I removed the image element altogether and set it as background of the div with a class of .frame

This at least works fine on Internet Explorer 8, Firefox 6 and Chrome  13.

I checked, and this solution will not work to shrink images larger than 25 pixels height. There is a property called background-size which does set the size of the element, but it is CSS 3 which would conflict with Internet Explorer 7 requirements.

I would advice you to either redo your browser priorities and design for the best available browsers, or get some server-side code to resize the images if you'd want to use this solution.

0
.frame { height: 35px; /* Equals maximum image height */ width: 160px; border: 1px solid red; text-align: center; margin: 1em 0; display: table-cell; vertical-align: middle;
}
img { background: #3A6F9A; display: block; max-height: 35px; max-width: 160px;
}

The key property is display: table-cell; for .frame. Div.frame is displayed as inline with this, so you need to wrap it in a block element.

This works in Firefox, Opera, Chrome, Safari and Internet Explorer 8 (and later).

UPDATE

For Internet Explorer 7 we need to add a CSS expression:

*:first-child+html img { position: relative; top: expression((this.parentNode.clientHeight-this.clientHeight)/2+"px");
}
0

You could do this:

Demo

CSS

.frame { height: 25px; /* Equals maximum image height */ line-height: 25px; width: 160px; border: 1px solid red; text-align: center; margin: 1em 0; position: relative; /* Changes here... */
}
img { background: #3A6F9A; max-height: 25px; max-width: 160px; top: 50%; /* Here.. */ left: 50%; /* Here... */ position: absolute; /* And here */
} 

JavaScript

$("img").each(function(){ this.style.marginTop = $(this).height() / -2 + "px";
})
5

This works for modern browsers (2016 at time of edit) as shown in this demo on codepen

.frame { height: 25px; line-height: 25px; width: 160px; border: 1px solid #83A7D3;
}
.frame img { background: #3A6F9A; display:inline-block; vertical-align: middle;
}

It is very important that you either give the images a class or use inheritance to target the images that you need centered. In this example we used .frame img {} so that only images wrapped by a div with a class of .frame would be targeted.

3

Solution using a table and table cells

Sometimes it should be solved by displaying as table/table-cell. For example, a fast title screen. It is a recommended way by W3 also. I recommend you check this link called Centering a block or image from W3C.org.

The tips used here are:

  • Absolute positioning container displayed as table
  • Vertical aligned to center content displayed as table-cell
.container { position: absolute; display: table; width: 100%; height: 100%;
}
.content { display: table-cell; vertical-align: middle;
}
<div> <div> <h1>Peace in the world</h1> </div>
</div>

Personally I actually disagree about use helpers for this purpose.

My solution:

<div> <div> <img src="" alt="" /> </div>
</div>
.container { display: table; float: left; border: solid black 1px; margin: 2px; padding: 0; background-color: black; width: 150px; height: 150px;
}
.frame { display: table-cell; text-align: center; vertical-align: middle; border-width: 0;
}
.img { max-width: 150px; max-height: 150px; vertical-align: middle;
}

Try this solution with pure CSS

Maybe it is the main problem with your HTML. You're not using quotes when you define class & image height in your HTML.

CSS:

.frame { height: 25px; /* Equals maximum image height */ width: 160px; border: 1px solid red; position: relative; margin: 1em 0; top: 50%; text-align: center; line-height: 24px; margin-bottom: 20px;
}
img { background: #3A6F9A; vertical-align: middle; line-height: 0; margin: 0 auto; max-height: 25px;
}

When I work around with the img tag it's leaving 3 pixels to 2 pixels space from top. Now I decrease line-height, and it's working.

CSS:

 .frame { height: 25px; /* Equals maximum image height */ width: 160px; border: 1px solid red; margin: 1em 0; text-align: center; line-height: 22px; *:first-child+html line-height:24px; /* For Internet Explorer 7 */ } img { background: #3A6F9A; vertical-align: middle; line-height: 0; max-height: 25px; max-width: 160px; }
@media screen and (-webkit-min-device-pixel-ratio:0) { .frame { line-height:20px; /* WebKit browsers */ }

The line-height property is rendered differently in different browsers. So, we have to define different line-height property browsers.

Check this example:

Check this example about line-height different in different browsers: input height differences in Firefox and Chrome

1

I am not sure about Internet Explorer, but under Firefox and Chrome, if you have an img in a div container, the following CSS content should work. At least for me it works well:

div.img-container { display: table-cell; vertical-align: middle; height: 450px; width: 490px;
}
div.img-container img { max-height: 450px; max-width: 490px;
}
2

An easy way which work for me:

img { vertical-align: middle; display: inline-block; position: relative;
}

It works for Google Chrome very well. Try this one out in a different browser.

0

For centering an image inside a container (it could be a logo) besides some text like this:

Enter image description here

Basically you wrap the image

.outer-frame { border: 1px solid red; min-height: 200px; text-align: center; /* Only to align horizontally */
}
.wrapper{ line-height: 200px; border: 2px dashed blue; border-radius: 20px; margin: 50px
}
img { /* height: auto; */ vertical-align: middle; /* Only to align vertically */
}
<div> <div> some text <img src=""> </div>
</div>

If you can live with pixel-sized margins, just add font-size: 1px; to the .frame. But remember, that now on the .frame 1em = 1px, which means, you need to set the margin in pixels too.

Now it's not centered any more in Opera…

I had the same problem. This works for me:

<style type="text/css"> div.parent { position: relative; } img.child { bottom: 0; left: 0; margin: auto; position: absolute; right: 0; top: 0; }
</style>
<div> <img>
</div>
1

You can use this:

 .loaderimage { position: absolute; top: 50%; left: 50%; width: 60px; height: 60px; margin-top: -30px; /* 50% of the height */ margin-left: -30px; }

Using table and table-cell method do the job, specially because you targeting some old browsers as well, I create a snippet for you which you can run it and check the result:

.wrapper { position: relative; display: table; width: 300px; height: 200px;
}
.inside { vertical-align: middle; display: table-cell;
}
<div> <div> <p>Centre me please!!!</p> </div> <div> <img src="" /> </div>
</div> 

Want to align an image which have after a text / title and both are inside a div?

See on JSfiddle or Run Code Snippet.

Just be sure to have an ID or a class at all your elements (div, img, title, etc.).

For me works this solution on all browsers (for mobile devices you must to adapt your code with: @media).

h2.h2red { color: red; font-size: 14px;
}
.mydivclass { margin-top: 30px; display: block;
}
img.mydesiredclass { margin-right: 10px; display: block; float: left; /* If you want to allign the text with an image on the same row */ width: 100px; heght: 100px; margin-top: -40px /* Change this value to adapt to your page */;
}
<div> <br /> <img src=""> <h2>Text aligned after image inside a div by negative manipulate the img position</h2>
</div>

I have been playing around with using padding for center alignment. You will need to define the top level outer-container size, but the inner container should resize, and you can set the padding at different percentage values.

jsfiddle

<div class='container'> <img src='image.jpg' />
</div>
.container { padding: 20%; background-color: blue;
}
img { width: 100%;
}

The best solution is that

.block{ /* Decor */ padding:0 20px; background: #666; border: 2px solid #fff; text-align: center; /* Important */ min-height: 220px; width: 260px; white-space: nowrap;
}
.block:after{ content: ''; display: inline-block; height: 220px; /* The same as min-height */ width: 1px; overflow: hidden; margin: 0 0 0 -5px; vertical-align: middle;
}
.block span{ vertical-align: middle; display: inline-block; white-space: normal;
}
12