I have a simple table with 1 TD with vertical-align:middle;. This TD contains an Image :
table
{
border:solid 1px red;
width:300px;
}
td
{
height:100px;
vertical-align:middle;
width:100%;
border:solid 1px green;
}
img
{
height:43px;width:43px;
}
span
{
vertical-align:middle;
}
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8/>
<title>JS Bin</title>
</head>
<body>
<table>
<tr>
<td>
<img src='http://static.jsbin.com/images/favicon.png'/>
</td>
</tr>
</table>
</body>
</html>
Everything is Ok and the IMG is vertical-aligned.
But If I add another elements after that Image ( a span for example ) :
table
{
border:solid 1px red;
width:300px;
}
td
{
height:100px;
vertical-align:middle;
width:100%;
border:solid 1px green;
}
img
{
height:43px;width:43px;
}
span
{
vertical-align:middle;
}
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8/>
<title>JS Bin</title>
</head>
<body>
<table>
<tr>
<td>
<img src='http://static.jsbin.com/images/favicon.png'/>
<span>aaa</span>
</td>
</tr>
</table>
</body>
</html>
Question
Doesn't the vertical align of the TD should vertical align all its childs ?
How can I make the span to be centered as well ?
NB
I don't want to add another TD , nor using float with padding/margin. IE8+.
edit:
Desired result :
Question
Doesn't the vertical align of the TD should vertical align all its childs ?
NO.
When you apply vertical-align to td, it is only applied to td, and is not inherited by any of its children.
If i have a TD with only span in it - it will vertical align. If I had a TD with only IMG inside it - it will also align.
This is because of the way vertical-align for td works. The total height of the cell i.e td is calculated and the whole cell is aligned vertically.
If there is a single img, then the height of td is same as that of img, so it seems that vertical-align for img is also middle. But actually, the td is vertically aligned to the middle with the img as vertical-align : baseline
Same is the case when there is a single span.
but if i have both - it doesn't. why is that ?
Because now, the height of td is the combined height of both img + span. So, actually, td is vertically aligned in the middle, but not img and span.
How can I make the span to be centered as well ?
You need to apply this CSS :
td > * {
vertical-align : middle;
}
This will apply the CSS to all the children.
Check the JSFiddle for a better picture.
Hope, this answers your question.
You can just use vertical-align: middle; to your span
img
{
height:43px;width:43px;
display: inline;
vertical-align: middle;
}
span
{
vertical-align:middle;
display: inline;
}
your jsbin
As per comment
You may think as if td is given vertical-align: middle; then it should align all the contents inside this but having an image and a span in which browser is understanding the image is what? : is this inline or inline-block, so you need to set display: inline or inline-block; Then you may see its working only applying display property for image. demo
Edit
img tag : source: display inline vs inline-block
They are "block" elements in that they have a width and a height.
It's true, they are both - or more precisely, they are "inline block" elements. This means that they flow inline like text, but also have a width and height like block elements.
Also check this:
Replaced Elements
A replaced element is any element whose appearance and dimensions are defined by an external resource. Examples include images ( tags), plugins ( tags), and form elements (, , , and tags). All other elements types can be referred to as non-replaced elements.
Replaced elements can have intrinsic dimensions—width and height values that are defined by the element itself, rather than by its surroundings in the document. For example, if an image element has a width set to auto, the width of the linked image file will be used. Intrinsic dimensions also define an intrinsic ratio that’s used to determine the computed dimensions of the element should only one dimension be specified. For example, if only the width is specified for an image element—at, say, 100px—and the actual image is 200 pixels wide and 100 pixels high, the height of the element will be scaled by the same amount, to 50px.
Replaced elements can also have visual formatting requirements imposed by the element, outside of the control of CSS; for example, the user interface controls rendered for form elements.
In an inline formatting context, you can also think of a replaced element as being one that acts as a single, big character for the purposes of wrapping and layout. A width and height can be specified for replaced inline elements, in which case the height of the line box in which the element is positioned is made tall enough to accommodate the replaced element, including any specified box properties.
Here's a JS fiddle solution
fiddle
Here's the css
table
{
border:solid 1px red;
width:300px;
}
td
{
height:100px;
vertical-align:middle;
width:100%;
border:solid 1px green;
}
img
{
display: inline;
height: 43px;
width: 43px;
position: relative !important;
float: left;
}
span
{
height: auto !important;
width: 80%;
float: right;
position: relative;
vertical-align: middle !important;
text-align: left;
}
In all the cases, the vertical-align: middle; on the td does what is expected of it. That is, align the td to the center of that row and the entire contents of the td to the vertical middle (by default) leaving equal spaces at the top and the bottom.
Here is what the W3 Spec says about vertical-align: middle:
The center of the cell is aligned with the center of the rows it spans.
Row height calculation:
The height of a 'table-row' element's box is calculated once the user agent has all the cells in the row available: it is the maximum of the row's computed 'height', the computed 'height' of each cell in the row, and the minimum height (MIN) required by the cells.
In CSS 2.1, the height of a cell box is the minimum height required by the content. The table cell's 'height' property can influence the height of the row (see above), but it does not increase the height of the cell box.
Cell boxes that are smaller than the height of the row receive extra top or bottom padding.
As a result of the above, the height of the tr and the td becomes 100px but the cell box takes up only the amount of height required by the contents (img height = 43px). Now since the Cell box is smaller than the row height, extra padding is added like shown in Box 5 of the image above and thus makes the contents also get aligned to the middle.
TD has only image:
When there is only an img, the content height is equal to the height of the img. So it gets positioned to the middle.
As can be seen in the above image, this does not require a vertical-align: middle on the img explicitly because the td aligns its contents to the middle.
TD has only inline data:
When the td has only a span or span plus an inline div, the height of the content is equal to the default line-height for text (or any specified line-height). In this case also, the td aligns it correctly.
When the text content goes beyond the first line (refer to the demo), you can see that the td automatically pushes the first-line (marked in cyan background) upwards to ensure that the contents on the whole is aligned to the middle (not just a single line).
TD has an image and a span:
When we put an img and a span (inline text) within the td, the content height becomes equal to the height of the img plus the line-height of the second and subsequent lines.
In this situation, there are two possible cases as described below:
Case 1 - img tag has no vertical-align specified
In this case, the img is aligned to the baseline (default). Then the td aligns the entire content to the middle. This means the td leaves around 28.5px (= (100-43)/2) gap at the top and the bottom of the content. Again, the vertical-align on td does the job, it puts the contents in the middle (that is, leave equal gap on top and bottom). But the text gets pushed down because img height is more.
If we reduce the img height to less than the line height (say 10px), we can see that even with img + span it gets aligned to the middle.
Case 2 - img tag has vertical-align: middle
In this case also vertical-align on the td does the same as what it did for Case 1. However, the text in this case is near the middle because the img is also aligned to the middle of the line.
table {
border: solid 1px red;
}
td {
height: 100px;
width: 200px;
vertical-align: middle;
border: solid 1px green;
}
img {
height: 43px;
width: 43px;
border: solid 1px green;
}
.one td + td img {
vertical-align: middle;
}
.three td + td img {
height: 10px;
width: 10px;
}
.four img {
vertical-align: middle;
}
.five img + img{
height: 50px;
width: 50px;
}
td:first-line {
background-color: cyan;
}
div {
display: inline;
}
<table>
<tr class='one'>
<td>
<img src='http://static.jsbin.com/images/favicon.png' />
</td>
<td>
<img src='http://static.jsbin.com/images/favicon.png' />
</td>
</tr>
<tr class='two'>
<td>
<div>aaa</div>
<span>aaa</span>
</td>
<td>
<div>aaa</div>
<span>aaa aaaaaaa aaaaaaaa aaaaaaaa</span>
</td>
</tr>
<tr class='three'>
<td>
Case 1
<img src='http://static.jsbin.com/images/favicon.png' />
<span>Image + Span</span>
</td>
<td>
Case 1
<img src='http://static.jsbin.com/images/favicon.png' />
<span>Image + Span</span>
</td>
</tr>
<tr class='four'>
<td>
Case 2
<img src='http://static.jsbin.com/images/favicon.png' />
<span>Image + Span</span>
</td>
<td>
<img src='http://static.jsbin.com/images/favicon.png' />
<span>Image + Span + more text.......</span>
</td>
</tr>
<tr class='five'>
<td>
Case 3
<img src='http://static.jsbin.com/images/favicon.png' />
<img src='http://static.jsbin.com/images/favicon.png' />
<span>Image + Span text...</span>
</td>
<td>
<img src='http://static.jsbin.com/images/favicon.png' />
<span>Image + Span + more text.......</span>
</td>
</tr>
</table>
Just add vertical-align:middle; to your img style?
Demo
<style>
table
{
border:solid 1px red;
width:300px;
}
td
{
height:100px;
width:100%;
border:solid 1px green;
vertical-align:middle;
line-height:100px;
}
img
{
height:43px;width:43px;
vertical-align:middle;
}
</style>
DEMO
just add this class:
td *{
vertical-align:middle
}
Edit:
question is why when you add a pic to the td text goes bottom of pic and not any more middle of td.
this is my answer:
when you set td vertical-align to middle it should not set all content vertical-align to middle, they are still baseline. and when you add a pic to the text, the line height rise to the height of image and text is bottom of this height, so you need to set vertical-align to middle for fix this problem.
here you can see what i said: DEMO
and sorry about my bad english
Is this what you mean? http://jsfiddle.net/JFVNq/
The reason is spans are treated as inline so you need to make them block.
CSS for the span:
td.vert span
{
vertical-align: middle;
display: block;
}
I think we are all nearly there but
td img,
td span {
display:inline-block;
vertical-align:middle;
}
seems to work.
Codepen Example
Or am I missing something?
This CSS attribute doesn't go on any other kinds of elements. When the novice developer applies vertical-align to normal block elements (like a standard ) most browsers set the value to inherit to all inline children of that element.
You simply need to add vertical-align: middle to the <img> class.
Your CSS should look like this...
table
{
border:solid 1px red;
width:300px;
}
td
{
height:100px;
vertical-align:middle;
width:100%;
border:solid 1px green;
}
img
{
height:43px;width:43px;
vertical-align: middle;
}
You can view the Sample Fiddle...
Just move your vertical-align: middle from the span to the image.
The image will align itself on the text; works better than the opposite ;)
img
{
height:43px;width:43px;
vertical-align:middle;
}
http://jsfiddle.net/ZnpNF/1/
Related
Full Source Located At: http://nounz.if4it.com/Nouns/Applications/A_Application_1.NodeComponent.html
Problem: There is an HTML div that is being used for a web page header, ultimately containing a table that has three columns for the left logo, a center title, and a right logo. I set the div width to "100%" in the CSS statement but the div is not dynamically expanding, in a horizontal direction, to fit the width of the window.
In short, the SVG canvas, further down in the page, requires a wider div and I'd like to get all the other full width divs to expand horizontally to keep things neater.
The div code looks like:
<div class="div_Header">
<table class="table_Header">
<tr>
<td class="td_HeaderLeft"><img src="../../IMAGES/SITE_HEADERS/IF4IT_Logo.png" alt="Header Left Image" /></td>
<td><img src="../../IMAGES/SITE_HEADERS/Title_Gold_Shadow.png" alt="Header Center Image" /></td>
<td class="td_HeaderRight"><img src="../../IMAGES/SITE_HEADERS/NOUNZ_Logo_DarkBlueAndGold.png" alt="Header Left Image" /></td>
</tr>
</table>
</div>
The CSS statement being used is:
div.div_Header {
width: 100%;
border:2px solid White;
border-radius:7px;
background: WhiteSmoke;
font: bold 14px Arial;
font-family:Arial, Helvetica, sans-serif;
color:WhiteSmoke;
text-align:center;
}
I've tried adding "overflow: auto;" as is recommended in this other SO post on the topic. However, it doesn't seem to work.
Any thoughts on how best to fix the issue?
You need to 0 out the padding and margin on the body element to prevent the browsers native stylesheets from applying those attributes which prevents you from having a true 100% width on your divs:
body {
margin:0px;
padding:0px;
}
The actual answer is partially explained in this article, titled: "Using CSS "Display: table-cell" for columns". However, it does not cover the full answer, either. The code, below, includes the full answer and has been tested.
The first part of the answer is to ensure that the entire html and body envelopes are given a baseline...
html, body {
margin: 0px;
padding: 0px;
width: 100%;
}
The second part of the answer is to create a full width div that will act as a container for the child divs. As mentioned in the above article, the containing div should be told to "act like an HTML table element" by using the "display: table;" attribute...
div#div_header_container {
background: ' + headerBackgroundColor + ';
border:2px solid ' + 'White' + ';
border-radius:7px;
width: 100%;
display: table;
vertical-align: middle;
}
Third, each of the child divs (in this case there are three) should be given a width that is a percentage of the parent container. And, since the parent container has been told to act like an HTML table element, these child divs should be told to act like table cells using the "display: table-cell;" attribute. They should also be set to vertically align their elements in the middle using the "vertical-align: middle;" attribute, ensuring that each image in each child div will all align along their middles.
div#div_header_left {
width: 20%;
border-radius:7px;
display: table-cell;
vertical-align: middle;
}
div#div_header_center {
width: 60%;
border-radius:7px;
display: table-cell;
text-align: center;
vertical-align: middle;
}
div#div_header_right {
width: 20%;
border-radius:7px;
display: table-cell;
vertical-align: middle;
}
Finally, the images that will be located within each child div that acts like a table cell should be decoupled from the divs, themselves and should be given their appropriate alignments...
img.image_header_left {
float: left;
}
img.image_header_center {
text-align: center;
}
img.image_header_right {
float: right;
}
When applied, the dom's source code will look like:
<body>
<div id="div_header_container">
<div id="div_header_left">
<img class="image_header_left" src="./Logo_Left.png" alt="Header Left Image" />
</div>
<div id="div_header_center">
<img class="image_header_center" src="./Logo_Center.png" alt="Header Center Image" />
</div>
<div id="div_header_right">
<img class="image_header_right" src="./Logo_Right.png" alt="Header Right Image" />
</div>
</div>
</body>
I have a table with a known width, 776 pixels, and three columns. The third column has a known width, 216 pixels, but the other two do not have known widths. The behavior I want is for the second column to have the same width as its child element. Whatever width is left over, 776 - 216 - 2nd, would be the width for the first column.
I found an example that sets the width of the column that should have its width minimized to 1 pixel. This does seem to work, but it seems like it is a hack and I don't understand why it works. Is there a more "standard" way to achieve the same result?
Here is my HTML with inline CSS as an example:
<table style="width:776px; height:48px;">
<tr>
<td style="height:48px;">
<!-- Note: Setting font size to zero prevents white space from contributing to an inline block element's width -->
<div style="background:#f0f0f0; border:solid 2px #808080; font-size:0; margin-left:8px; text-align:center;">
<h3 style="display:inline-block; font-size:20px; line-height:28px; padding:8px;">Art</h3>
<h3 style="display:inline-block; font-size:20px; line-height:28px; padding:8px;">Events</h3>
<h3 style="display:inline-block; font-size:20px; line-height:28px; padding:8px;">Papers</h3>
<h3 style="display:inline-block; font-size:20px; line-height:28px; padding:8px;">Research</h3>
</div>
</td>
<!-- Note: Setting width to one pixel removes horizontal spacing -->
<td style="vertical-align:middle; width:1px; height:48px;">
<h3 style="margin-left:8px;"><label for="search">Search:</label></h3>
</td>
<td style="vertical-align:middle; width:216px; height:48px;">
<input id="search" style="margin-left:8px; width:208px;" type="text" value="" maxlength="32">
</td>
</tr>
</table>
Well, an easy way would be to set the 1st cell to width: 100%. That would force it to fill as much as it can the parent table's width. Then, to the third cell, you put a 216px content element (like a div).
The table's cell always try to respect its content. So this way, the 2nd div would be squized in the middle, just respecting its own content. The 3rd one would respect its 216px content, and the 1st would fill up the rest.
Working JsFiddleExample
<table>
<tr>
<td>1stContent</td> <!-- Fills what it can -->
<td>2ndContent</td> <!-- Squized in the middle -->
<td>
<!-- Will respect the width of its content -->
<div class="dv3rd">
216px
</div>
</td>
</tr>
</table>
CSS:
table {
width: 776px;
background: silver;
}
td:nth-child(1) {
width: 100%;
background: red;
}
td:nth-child(2) {
background: green;
}
td:nth-child(3) {
background: blue;
}
.dv3rd {
width: 216px;
}
However
As well commented, you should not be using tables for the page layout. A simple replacement would be working with css tables, where your divs can act like display: table and display: table-cell elements.
Here's the same example, but using div's instead:
Working JsFiddleExample - Tableless
<div class="table">
<div>
1stContent
</div>
<div>
2ndContent
</div>
<div>
<div class="dv3rd">
216px
</div>
</div>
</div>
CSS:
.table {
width: 776px;
background: silver;
display: table;
}
.table > div:nth-child(1) {
display: table-cell;
width: 100%;
background: red;
}
.table > div:nth-child(2) {
display: table-cell;
background: green;
}
.table > div:nth-child(3) {
display: table-cell;
background: blue;
}
.dv3rd {
width: 216px;
}
I found the reason why this work's in BoltClocks link (in the comments): http://www.w3.org/TR/CSS21/tables.html#auto-table-layout
...This algorithm may be inefficient since it requires the user agent
to have access to all the content in the table before determining the
final layout and may demand more than one pass.
Column widths are determined as follows:
Calculate the minimum content width (MCW) of each cell: the formatted content may span any number of lines but may not overflow the cell box. If the specified 'width' (W) of the cell is greater than MCW, W is the minimum cell width. A value of 'auto' means that MCW is the minimum cell width...
Answer:
Calculate the minimum content width (MCW) of each cell: the formatted content ... may not overflow the cell box.
I like tables since text align is pretty nice there. If we have a text inside a <td> like <td>Sample Text</td>, it doesn't matter how much height the cell have, the text will be vertically aligned on center. The text will be automatically re aligned if there is less space in the cell for the text to accommodate.
But, if I have a span inside the td, having the same height of td, the text will be aligned on top. I can give a fixed padding inside span for the text to align vertically, but then at the time of resizing, it won't pull the text upward inside the cell, leaving a permanent top padding.
What I want is to make the text behave inside a span (which is inside a td), to behave exactly as it is inside a td. Below image describes what I am trying to say;
Here is a demo fiddle, I just want to display text inside span to display exactly as it behaves inside the td.
HTML:
<table cellpadding="0" cellspacing="0">
<tr>
<td>Sample Text</td>
</tr>
<tr>
<td>Sample Text rearranged</td>
</tr>
<tr>
<td><span>Sample Text</span></td>
</tr>
</table>
CSS:
td{
border: solid 1px #000;
height: 40px;
width: 100px;
}
span{
height: 40px;
display: block;
background: orange;
}
One easy approach is setting a line-height. But this won't work, if you have fluid heights and/or multiple lines of text.
span {
line-height: 40px;
}
Another way inside the td would be vertical-align: middle; along with removing display: block;. You can set the background color on the td.
td {
background-color: orange;
}
span {
vertical-align: middle;
}
You have set display:block to your span that's why it is not vertically centered. Set background for TD instead of SPAN.
You can set this style:
div, span{
width:100%;
text-align:center;
padding-top:5px;
}
set display:table to the parent tag and display:table-cell and vertical-align:middle to the span like this:
DEMO
this works for all elements not just td
HTML
<div>
<span>
some text
</span>
</div>
CSS
div{
width:100px;
height:100px;
background:gold;
display:table;
}
span{
display:table-cell;
vertical-align:middle;
}
I dont really know the wright way, but you can put padding-top. Or use what you said is working. but if you include
line-height:100px; /* the same as your div height */
will work. But if it is just one line. Otherwise you have to include padding, or I think so.
Okay first I must tell you the difference between a div and a span.
A div is a block element ( which takes the full width of browser )
while a span is an inline element ( which takes the width of the content )
So when you put a span inside a td, It is not actually taking the full width . So , either you can convert it to div or make the span as display: block;
Now since the width is adjusted now, we must also adjust the height. Since span understands the height of the span as the height of the content, so we give a line height of 40px. i.e. line-height: 40px; which is the height of the td.
As a summary .. display block is to take the full width and line height is for making the height as much as we want. In our case we made it equal to the td height.
Hope this helps !
span {
background: orange;
line-height: 40px;
display:block;}
http://jsfiddle.net/f45Sv/8/
I want to put text in the middle of the box in CSS3, but it's not working for some reasons.
Here's my code snippet (with code from Angularjs):
<div class="a" ng-repeat="i in l | filter:query">
<a class="b" href="{{i.a}}">{{i.b}} {{i.c}}</a>
</div>
And here's my css:
.b {
display: inline-block;
float: left;
margin: 8px;
height: 20px;
width: 100px;
}
And even if I add vertical-align: middle; to the above CSS, it doesn't put the text in the middle of the box... why?
Thanks.
You need to use css table-cell
DEMO http://jsfiddle.net/LstNS/31/
.b {
display: table-cell;
vertical-align: middle;
}
.a {
display: table;
height: 200px;
border: black thin solid;
}
vertical-align requires a lot of things to work right...
easiest method , and what I do, is just use line-height
so do
.b {
line-height: 20px;
}
adjust number of pixels accordingly, but that will center the text vertically for you
float kills display and so vertical-align if avalaibe.
inline-blocks element can be vertical-align aside text, other inline-boxes or on the line-height.
In your case , line-height alone will give height of parent (if unprecised) and set the link on it, right in the middle :), no need to give an inline-block display to <a> unless you need it to size it for instance (or whatever else style that needs layout) .
If .a has an height, give it an equal line-height.
Line-height works fine as long as you have one line of text.
if you want to use inline-block, and set middle alignement from itself it won'nt work, you need at least 2 elements as another inline-boxe, so it can center from something ... an extra box or pseudo-element might help.
.a {height:300px;}
.a:before {
content:'';
height:100%;
}
.a:before, .a a {
display:inline-block;
vertical-align:middle;
}
Else, vertical-align works on content of <td> or element wich receive a display:table-cell;. .a could then receive a display:table-cell and vertical-align and eventually an height. Usually it needs a parent as display:table to work fine.
.a {
display:table-cell;
height:200px;
vertical-align:middle;
}
I have no special links on tutorial for vertical-align , on W3C it is confusing somehow since both vertical-align for inline-box and cell content are dispatched in different documents.
I have a div that is display:table; - inside that div there are two display:table-cell.
one table-cell is a span holding and img,and the other is span holding text,
for some reason there is a space between the two display:table-cell that I don't want.
how can I made the table-cells be one next to each other?
here is my html:
<div class="statusCommentUser">
<span><img src="/Content/Images/contactDemo_small_image.png" class="SmallUserImg"></span>
<span>Sounds great, man!</span>
</div>
here is my css:
.statusCommentUser {
width:450px;
height:50px;
display:table;
}
.statusCommentUser span {
display: table-cell;
vertical-align: middle;
}
When you assign css rule display:table-cell to any element, it behaves as any td element of some table. So, in that case, it auto adjusts itself according to the parent width and the number of other tds in the same row, only when, you don't specify a width to this td.
That's why both your span cum TDs are taking that width.
simply assign a width to the first one, it should solve your problem.
i.e. try adding this class
.statusCommentUser span:first-child{
width:50px;
}
see the demo
Moreover, if all that you want is to position your image span and text span horizontally aligned, you can do it through many other ways i.e. change your css classes to this:
.statusCommentUser {
width:450px;
height:50px;
}
.statusCommentUser span {
float:left;
}
.statusCommentUser span:last-child{
position:relative;
top:40px;
}
see this demo
See Demo Here
Just add class to the span which contains your image and then set the width
HTML
<div class="statusCommentUser">
<span class="user"><img src="http://placehold.it/30x30/" class="SmallUserImg"></span>
<span>Sounds great, man!</span>
</div>
CSS
span.user {
width: 35px;
}
If the div is acting like a table, try adding this to .statusCommentUser:
border-collapse: collapse;
This CSS is used to remove the spacing between cells in a table.
The space comes from the newline and indentation between the two <span>s.
Try this:
<span><img width="100" height="100" class="SmallUserImg"></span><span>Sounds great, man!</span>
What about this:
.statusCommentUser img
{
width: 100%;
height: 100%;
float: left;
}
Your image will become the total size of your cell. Also your image has to be floated to be positioned in the cell (OP example the image is not in the middle of the cell).
To prevent stretching of the image, you can make a static width of the image span. Or you can make the cell adjust automatically based on the image size. However you would have to remove the static width of your div tabel.
Manish Mishra's image used for dummy image ^^
jsFiddle
I was facing the same problem and was able to resolve by adding the property in display:table-cell element
border-spacing: 0;
Hope it solves for those still looking