Is there any way to put images at center vertically inside <div> tag

HI, I searched alot but didn’t find anything useful. Could anyone help me Is there any way to put image at center vertically inside <div> tag.

If you add a display:block to the image and then use the auto portion of margin, that’ll center it for you.

ex:

img.center { display:block; margin: 5px auto; }


<html>
<head>
	<style type="text/css">
		img.center { display: block; margin: 5px auto; }
	</style>
</head>
	<body>
		<img src="dog.jpg" class="center" />
	</body>
</html>

You have to put two divs inside each other and invoke table displays and stuff. Here’s a link. This is one of the most frustrating aspects of css, for all the other fancy stuff it can do, it would seem that this would be one of the most basic effects and one of the most sought-after. IMHO.

You can do it like this:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
	
<style media="all">

div.cont {display: table; background: #e7e7e7; width: 300px;}
.cont div {display: table-cell; vertical-align: middle; margin: 0; padding: 10px;}
img {width: 100px; height: 100px; background: blue; vertical-align: bottom;}

</style>
	
</head>
<body>

<div class="cont">
	<div><img src=""></div>
	<div>Text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text text</div>
</div>

</body>
</html>

If you don’t have the long content in the next “cell” to make the cells taller than the image, you’d have to set a height, which is not a good idea generally, though a min-height would be fine.

@zot - I couldn’t get your link to work. EDIT: Sorry, it’s working now.

I think setting height is the right rule for elements with display: table-cell because for table cells height actually means mininum height. I think I have come across the problem of min-height not being applied to table cells in some browsers - but I can’t be sure now.

Good point, Lemon Juice. Thanks for pointing that out. :slight_smile:

I tested it with a fixed height in all the real browsers (on my Mac) and it acted as a min height.

Okay, recently I was using display: table-cell on a <span> and I can confirm that min-height has no effect on it, at least in firefox. Standard height has to be used.

Lemon Juice is right. A TABLE CELL does not respond to min-height, nor does an element given display:table-cell. In essence, height is a table-cell’s min-height, but tit will stretch as necessary to fit it’s content. The change in height will also affect it sibling elements. So if you give the IMG’s containing DIV display:table-cell, it’s going to try to run ‘inline’ with its sibling elements ( DIVs or what not) ; this may or may not be a desired side effect.

Another issue is: a table cell CANNOT be positioned nor does it have margin. Again this may or may not prove inconvenient.

Add to that limited IE support.

If none of the above concerns you, then .vCenter { display:table-cell; vertical-align:middle; } is a simple solution.

HOWEVER, the same effect can be achieved w/o using display:table-cell


.cont>span, .cont>img{ display:inline-block; vertical-align: middle}
.cont>span{ width: 80%; margin-left:3%}
.cont>img{ width:150px; max-width: 15%}
.cont {border: 1px solid;  padding:15px;}
 
<div class="cont">
	 <img src=""> 
	<span>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</span>
</div>	

ASSUMING, the IMG was by itself in a DIV, or other block element, and that block element had explicit height, you could do this:


 .cont:after{ display:inline-block; vertical-align: middle; }
 .cont:after{content:''; height:100%}
.cont {height:250px; width: 500px;  border: 1px solid; padding:15px; text-align: center}
img {border: 1px solid}

hope that helps

If the parent div has a fixed height and all you want is the image centred vertically then just set the line-height to the height of the div and it will centre automatically in ie8+.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Untitled Document</title>
<style type="text/css">
div {
	height:300px;
	width:600px;
	border:1px solid #000;
	line-height:300px;
	text-align:center;
}
img {
	vertical-align:middle;
	display:inline;
}
</style>
</head>

<body>
<div><img src="images/img1.jpg" width="100" height="100" alt="test"> <img src="images/img2.jpg" width="100" height="150" alt="test"></div>
</body>
</html>

No need for anything fancy unless you have extra content in there.

Good tips!

<rant>

However, whenever I’m reading such tips I’m wondering whether the guys who standardize CSS have no ability to think or are intentionally trying to make our lives harder? Why not allow vertical-align on all elements? Or why not create a simple rule for vertical aligning of anything inside a block element like block-vertical-align? I can’t understand why we need to read/create tips, tutorials, blogs, articles, courses, whatever, on such basic stuff like how to centre something vertically?? This should be self-evident just from reading the specs and the issue should have never even turned up among developers! :headbang:

</rant>

There are two ways this could be done through the CSS of the image.

Method1:

img{
vertical-align:middle;
}

Method 2:

img{
margin: auto 0;
}

in method 2, margin: auto 0; means that the img is given an auto margin from top and bottom, and thus being centralized and it is being given 0 margin from right and left.

Hi,

Thanks for the suggestions but I’m afraid you haver misunderstood how css works and neither of those tips are accurate and will confuse beginners who read them.

  1. Vertical-align only applies to inline elements (and inline-block) and will only vertically align the content on a single line in respect to the other content on that line. It will not align the element in respect of a block parent. Vertical-align does however apply to table cells and as already stated in a number of examples above can be used by setting the display of an element to display:table-cell.

  2. First of all margin:auto only applies to block elements so does not naturally apply to images unless you have set the images to display:block. Also margin:auto 0 does not vertically align the element within its parents dimensions at all. For vertical margins auto is effectively zero as it is only horizontal margins when set to auto will centre the element horizontally. It would have been nice if margin:auto 0; did vertically center elements but it does not but the facility is already available width display:table-cell anyway.

I think the main problem was simply that IE7- (ie7 and under) never implemented display:table-cell (which was in the css2 specs and implemented in most other browsers for years) and allowed an easy mechanism to vertically center elements as had been done in tables since the year dot. Therefore as Ie6 previously dominated the browser market we had no way of easily centring something vertically and resorted to all these tricks and hacks. These days we can almost forget about ie7 and under (or just let them have basic styles) and we can now use the simpler methods we should have been using from the start which is simply to make the parent display as a table-cell and then content can be vertically aligned.

When you think of it vertical alignment is a slightly complicated concept anyway as you have to wonder what the element is going to be vertically aligned with. If the parent div has no height then there is nothing to vertically center; if the parent’s height depends on content then that will be something unknown until run time and as with percentage widths based on the width of content defined by the percentage width of some other content then the specs usually say the behaviour is undefined. In the end the sensible way to vertically centre is to use the table-cell algorithms that already have special in-built height routines to cater for height or for content height. Height in table-cells is treated as a minimum as you pointed out and indeed in html table-cells “height” was never a valid attribute for a table-cell anyway.

It still would have been nice for margin:auto 0 to vertically center an element within its parent height but that would assume no other content was present and as soon as you start thinking about it it gets complicated :slight_smile:

Paul, once again you beat me to the punch. Although, I must confess I am not a 100% fan of display-table cell, as it removes the possibility of using other attributes such as margin, or position ( possibly because of the table algorithm itself), Sometimes tho, it’s the best solution available.

I wanted to add an ‘intuitive’ tip. It may seem like a display:block element should be able to vertically center content with ease, after all we can center horizontally quite easily, right? And thus the error in thought. a block element has a ‘default explicit’ width of 100%, but as Paul mention blocks have no default height. Even BODY/HTML depend on content. As such, height is figured from the inner element -> outward, rather than from wrapping elements inwards ( unless explicitly declared). So it really can’t be ‘that simmple’ even tho it ‘seems’ it could be.

But once that ILLUSION is burst, we can think more clearly to wards achieving the same goal as the circumstances allow.

EG.:

Situation1:Centering an image, or multiple images, vertically in a block container ( a container no hz siblings), when we ant the container size to be dependent on its content .
Use vertical-align middle and vertical padding as needed.

Situation2:Centering an image, or multiple images,in a container when we ant the container size is explicit and INDEPENDENT of its content .
Use vertical-align middle , and give the container line height = to the desired height of the container ; caveat this method is no good if the line of content must wrap around.

Situation3:Centering an image, or multiple images,in a container when we ant the container size is explicit and INDEPENDENT of its content , when content must wrap around
wrap the images in a span, give the span display:inline-block; explicit width, and give the container line height = to the desired height of the container ;

Once you clear your mind that a block element should “just be able to center content vertically the way it dos horizontally” it will become easier to see tons of situation/solution pairs.

Good post :slight_smile:

Yes that is one of the downsides of display:table-cell and you have to resort to methods that you would have had to use in a real table to get the same effect. I often use border-spacing to create the gaps between the cells but is a little awkward and it would have been nice if margin could have been slipped in there somewhere.

We are still some way from a perfect layout system but with the proposed grid systems and flexbox modules there will come a time in the not too distant future when all of our dreams will come true :slight_smile: I just hope that they can keep it simple enough to be of use and not get carried away with all the bells and whistles.

Old IE is a different problem, what I meant was that the CSS specs make vertical alignment unnecessarily complicated.

I think you are overcomplicating things. Every block element has width and height and it doesn’t matter if the height is explicitly defined or is computed at run time to contain the content, the height is there. The child element also has a height so what is the problem to centre it?

You may think that multiple child elements might make things complicated but there’s an easy solution - if CSS vertical centring were defined on the parent element, not on the child element(s) then anything that is inside the parent container can be centred. This is exactly the same mechanism that works in table cells and has existed since browsers as ancient as Netscape Communicator - and you are saying this is too complicated by today’s standards? I mean simply allowing vertical centring on all block elements just like it is allowed on table cells is absolutely enough to make it easy for everyone. There’s no need to invent any new algorithms.

When you look at the current situation is that we all use hacks for centring. display: table-cell is a hack. I don’t want the element to be displayed as a table cell nor do I want it to behave like a table cell, why would I if it is not to be presented as tabular data? I just want to centre something vertically! Sure, this is better than having to use tables in HTML, but now the hack is simply moved from HTML to CSS. display: table-cell for centring is semantically incorrect in CSS and doesn’t remotely describe the intention of what I want to achieve. The only reason why I’m using it is because there is no other way - therefore it’s a hack.

To some extent I treat margin: 0 auto for horizontal centring also as a hack because it is also far from being intuitive or descriptive. We can guess quite correctly why the same thing doesn’t work for vertical centring - but how many people who learn this actually treat it as something logical?

Now think about how many hours people spend on learning all these CSS hacks, wasting precious time on learning the most basic CSS tasks instead of simply looking up the specs. If vertical-align: middle were allowed on all elements then we would have an example of a simple and easy to understand CSS rule that is also so much faster to read and debug when you come back to your style sheet later on.

As I said earlier, these problems don’t really exist since all block elements have a height and thus could position their inner content in the middle of them with ease. Of course, if we would want margin: auto 0 to work then we would run into some complications (what happens if some elements are centred while others not?). But if the vertical centring were applied to the parent element like on table cells then these problems are gone. This mechanism has worked very well for so many years in tables and there’s no reason why it would have to be more difficult in blocks. Table cells also have heights that are often computed at run time and are even more fluid as they adjust to other cells in a row and still browsers have no problem with them.

It’s just a question of making the right specs and the browsers will follow.

Every block element has width and height and it doesn’t matter if the height is explicitly defined or is computed at run time to contain the content, the height is there.

ah… and that’s the fallacy my previous post was referring to. block elements actually DONT have height. they obtain their height from their CONTENTS via computed algorithm.

this is why an EMPTY DIV, without explicit height essentially disappears. It has no height. Give it a border:1px and you will see… IT STILL has no height, but it has 100% width. this was arbitrarily decided in the spec. Block element : no height; 100% width of available container space.

Now, we can say… hey this was arbitrarily decided, so why not arbitrarily decide it has height too? I am sure that passed through their minds at some point. The problem is what height? With width is simple the root container was the HTML, it would naturally be 100% of the viewport wide… but since web is a scrolling medium it would most likely be more than 100% of the view port 's height. So it follows the height of the element would be determine by the sum of the heights of its children… now were are back at calculating heights from the inside out. Which the leads to what Paul pointed out, the container doesnt know it’s height UNTIL it knows the height of its children … BUT in order to center something you have to the height of the container. And thus the infinite loop. Programmers HATE infinite loops, I hear.

Table elements on the other hand take the opposite approach , but they do so at the cost of margins, and positioning capabilities. I dont think it’s an accident that tables ‘reverse’ the box model ( that is padding is part of the width as opposed to adding to it. Since the children of a table add up to 100% of the table ( and not the table adds up to 100% of its children… the logic is NOT reversible is what I mean) … any padding /spacing/border… must come at the cost of content space.

Well, this is getting a bit too academic in regards to what you mean or don’t mean by “have height”. If height is obtained/computed does it mean it doesn’t exist? A block has height only if it has height CSS rule? And what if it has min-height? To me this is splitting hairs and we are beginning to talk about theoretical nomenclature. In practice every block element has a height, it can be seen and it can be easily retrieved with javascript.

Of course, an empty DIV has no height - but it can be equally said that it has a height of 0.

I have no idea how you got to the infinite loop here! First of all, if you leave the block’s height at its default, that is it’s the sum total of its children heights, then the issue of vertical centring doesn’t exist because there is nothing to centre, or to be more precise, there is no room to centre so nothing happens. Vertical centring can kick in only if the block’s height is greater than the total heights of it’s children and that can happen only when you declare height manually so the container knows its height immediately. For example, hypothetical rendering of a 100px-high block with text vertically centred in a 200px container:

  1. the browser renders the container DIV, initially it’s empty but is declared as 200px high so it renders it such immediately
  2. the browser receives the inner DIV, initially it’s 0 height and places it vertically in the middle at 100px (if it has a 1px border, then it would be positioned at 99px and a 2px line would be visible because the content has 0 height)
  3. the browser receives the text and the inner DIV becomes 100px high to accommodate the text so the browser moves it up to keep the vertical centring
  4. if the content of the div changes at any time the browser repositions it so that it is centred vertically
    Ad.1. The browser doesn’t even need to know the height immediately - if it changes during page rendering or by script manipulation, the contents are simply re-centred.

Where’s the problem? This is a simple and linear process and there are no loops whatsoever, not to mention infinite loops!

Are you implying that the lack of margins is what makes vertical align possible? I don’t think it has any connection to this because margins are outside of the box, so for the containing block they are irrelevant and for the inner elements they would simply add up to the overall height of the boxes to centre. Positioning also is not a problem - fixed and absolute positioned element couldn’t be centred anyway because there is nothing to centre against, while relative positioning would work as usual - that is positioning relatively to the centred position.

CSS does get complex as soon as you start digging into the details and the reasons why things have been done in a certain way. However, for vertical-align I don’t see how one line of code and no extra mark up is excessively complicated.

e.g.


.test{
display:table-cell;
vertical-align:middle;
}

Remember that the display:table properties have nothing whatsoever to do with tabular data. They are not meant for tabular data (as that’s what tables are for) and are simply a mechanism to reproduce certain specific table behaviours - one of which is to vertically align block elements. There is no loss of semantics in using display:table as css does not add semantics to the structure of a document; that’s html’s job.

I do agree with you that perhaps a separate property could have been used for vertically aligning things as obviously the routines are in place for the display:table-properties but then I guess that would cause some duplication of the underlying code to achieve something that is in effect already achievable. It would have been nice to perhaps have a valign property that did not turn the element into a table-cell but did vertically center its children. However, as I said before css is still evolving and there will be better layout methods in the future. There are many things I don’t like in CSS (margin-collapse for one) but I do understand why they have come about although I sometimes thing they err on the wrong side of usefulness.:slight_smile:

We also have to remember that vertical-align (outside of tables) is used to layout inline elements with respect to each other on the same line and to manage their vertical alignment specifically. So we would have needed something else to manage the vertical-alignment of block elements anyway.

I think you are overcomplicating things. Every block element has width and height and it doesn’t matter if the height is explicitly defined or is computed at run time to contain the content, the height is there. The child element also has a height so what is the problem to centre it?

CSS isn’t like javascript where you can grab the width and height of elements because with javascript you grab the dimensions only after the page has loaded. Put your js in the head and then try to grab dimensions and you will get nothing. CSS has to lay the page out first and it does this sequentially so the height of a parent that is dictated by its content is not known until the children have been laid out. It would mean doing a second pass of the code (which is what tables do) and therefore slow things down considerably in complex layouts.

This is why vertical percentage margins always refer to the width of the element and not the height of the element as a lot of users may expect.

Notwithstanding the above I realise that sometimes CSS is unintuitive but it is evolving and improving all the time.

absolute positioned element couldn’t be centred anyway

Well actually its easier to vertically and horizontally center absolute elements than you may think and the following will do just that. Very few people will actually realise that this works.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Untitled Document</title>
<style type="text/css">
p { margin:0 }
.test {
	position:relative;
	width:50%;
	margin:auto;
	border:1px solid #000;
}
p.vert {
	position:absolute;
	top:0;
	bottom:0;
	left:0;
	right:0;
	width:100px;
	height:100px;
	margin:auto;
	line-height:100px;
	background:red;
	border:1px solid #000;
}
</style>
</head>

<body>
<div class="test">
		<p>Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet </p>
		<p>Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet </p>
		<p class="vert">Vertical center</p>
</div>
</body>
</html>


The above may add fuel to your question as to why things couldn’t be more easily centred and indeed to my mind the browser is doing all the calculations to find the center of this fluid width and height block. I guess because the element is absolutely positioned and out of the flow it can be held back until the height is known unlike in-flow elements which need to be there to determine the height etc.

Although I may seem to disagree with you at certain points I do also feel that some things in CSS could be easier and more intuitive from the start.

No, this is not excessively complicated when you already know what and why. But when someone is learning CSS things are not so obvious and some deeper investigation is necessary to understand this. That was my main point that if there were a dedicated, semantic rule for centring content in block elements then the code would be self evident and at worst would require a novice to look up the specs.

You are right, I got carried away too far with my reasoning about tabular data. What I meant was ‘tabular way of displaying data’, actually you described it pretty well. My point was that triggering tabular display only to centre content is far from being intuitive.

Sure, these are understandable considerations, I’m not insisting on vertical-align being applied to block elements, this was just an example. Any rule would be fine as long as it is descriptive and simple to use.

Sure you are right but browsers have been coping with this quite well. On a slow internet connection sometimes we can see how page elements resize and/or change position a few times before stabilizing in their eventual state - this was more apparent with table-based designs for obvious reasons. Sure, all of this adds up to consuming more processing power but this is the price for progressive rendering. And if people need to centre vertically they will do it using all kinds of hacks that are available - I don’t think that substituting display: table-cell with a dedicated aligning rule would slow down the process.

Nice trick, I think I’ve never seen this before :D. Looking at the CSS I would never have thought that you are centring an element! So yes, this example can only add fuel to my rants so I’ll stop here because this discussion is becoming purely hypothetical and complaining here about CSS won’t make things better. I don’t want to go further into discussing CSS for complex layouts, which is even more full of hacks but as you said, this is all improving and new features for layout should make our work easier in the future. So far my impression is that CSS is wonderful for styling text and other elements but for layout it’s like cooking dinner in a car workshop instead of a fully equipped kitchen - you can do wonderful things there but the tools are a bit not what you would really want to use.

There comes a point, when learning CSS in which you must SHED and ABANDON what one CONSIDERS intuitive and replace it for what actually is intuitive in CSS.
You have to understand that everything in the world ( CSS or otherwise) is a mathematical balance. If a rendering routine allows you vertically center something, it probably consumed rendering information to do so, and now cant to something else… such as margins or positioning, is wanting to eat your cake and have it too.

A DIFFERENT example, tangentially related to centering: display:inline-block.

like a block element, it allows to set dimensions and ‘effective’ padding, but other than that you must THINK of it as an inline element! For example, vertical margins wont work on inline block. I was very disappointed when I first found this out, as I thought inline block would be a way to completely eliminate float my code; teh I also realized that float allows you to set SOME elements in one direction and others in another… and that just not the way inline could EVER MATHEMATICALLY work; how would you ‘justify’ text so that some words are on the left and other words in the SAME LINE are on the right?

As long as we are on the topic display:inline block. You can vertically center inline-blocks to each other. You keep AP/PR, but as i mention vertical margins wont work, and since they are not displaying as table cells the sibling elements don’t adjust to match each others height. In short: gains and trade offs.


<html>
	<head>
		<title></title>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<meta name="viewport" content="width=device-width">
		<style type="text/css">
ul{margin:0;padding:0;list-style: none; outline: 1px solid; position: relative;}
li{width:15%; vertical-align: middle; padding: 15px;display: inline-block }
li+li:before{ content:''; border-left: 1px solid; width: 1; position: absolute; top:0; bottom:0; margin-left:-.15em}/* for effect only*/
 		</style>
	</head>
	<body>
<ul class='row'>
	<li>An item</li>
	<li>Lorem ipsum dolor sit amet, consectetur adipisicing elit, </li>
	<li>an even longer item.</li>
	<li>An item</li>
	<li>An item</li>
 </li>
	</body>
</html>