I have the following table, and I wanted an expression to get the Percentage of the Category "OC". Is it possible to extract via XPath?
<tbody>
<tr>
<th class="textL">Category</th>
<th class="textR">No. of Items</th>
<th class="textR">Percentage</th>
</tr>
<tr class="data_row">
<td>OC</td>
<td class="textR">100</td>
<td class="textR">4.70</td>
</tr>
<tr class="data_row">
<td>FP</td>
<td class="textR">200</td>
<td class="textR">38.82</td>
</tr>
<tr class="data_row">
<td>FI</td>
<td class="textR">300</td>
<td class="textR">20.39</td>
</tr>
</tbody>
Selecting table entry based on value of another entry
To select the Percentage for the given "OC" Category:
//td[.='OC']/following-sibling::td[count(../..//th[.='Percentage']/preceding-sibling::th)]/text()
The above XPath will return
"4.70"
as requested.
Note that it will continue to work in the face of many changes, including row and column rearrangements as long as the targeted column continues to be named "Percentage" and remains after the Category column in the first column. One could even further generalize the expression by taking the difference of the positions of the two columns rather than assuming that Category is the first column.
Explanation: From the td that contains "OC", go over the number of siblings equal to the position of the "Percentage" column header, and there select the text in the correct sibling td.
Another XPath, also dependent on the order of the table's columns
//td[text()='OC']/following-sibling::td[2]
(explanation: take the second td sibling among the siblings of a td that contains text 'OC')
There are multiple XPaths for that. This one will work:
/tbody[1]/tr[2]/td[3]/text()
But it is based on the current layout of the XML
This works:
tbody/tr/td[. eq "OC"]/../td[#class eq "textR"][2]/text()
It assumes that the OC td element will be there, and that the value you want is the 2nd element with a "textR" attribute.
<TR class="bcgrndClr">
<span class="Title">
My title
</span>
</TR>
I wrote this part, but the background color is not coming in chrome and other browsers, where as working fine in "IE".
so is it necessary to put a <td> before <span>
or should i go for <th> instead of <tr>
or how else should i give the title (with some conditions) to this particular table
TH and TD are interchangable, but not TH and TR. Thats how i been using it at least.
you can do something like:
<tr><td colspan="2"><span>Hello World</span></td></tr>
colspan is used to make a TD element stretch across multiple row elements.
Yes, you need <td>. Browsers will still try to render the table if you write invalid HTML, but the rendering will be inconsistent between browsers.
<th> can take the place of <td> if the cell is a header cell. It does not take the place of <tr> which is always required.
You can always check the HTML5 spec if you are in doubt about which elements are required and which are optional:
The tr element represents a row of cells in a table. Permitted
contents Zero or more of: one td element, or one th element
If you look at the HTML 4 spec or HTML5 Spec, you will see
HTML 4:
<!ELEMENT TR - O (TH|TD)+ -- table row -->
<!ATTLIST TR -- table row --
%attrs; -- %coreattrs, %i18n, %events --
%cellhalign; -- horizontal alignment in cells --
%cellvalign; -- vertical alignment in cells --
>
HTML5:
4.9.8 The tr element
Content model: Zero or more
td, th, and script-supporting elements
Notice the TH and TD? Those are the only two child elements allowed.
What happens when you add an invald element to the TR is up to the browser. Some will try to figure out what you are doing, others will remove it from the flow and add it after. Write valid code so the browser does not have to guess.
Since you have a class of title, it seems like you should not be using a row. If you want a title row on the table, you want to use the <caption> element.
From MDN:
The HTML <caption> Element (or HTML Table Caption Element) represents
the title of a table. Though it is always the first descendant of a
<table>, its styling, using CSS, may place it elsewhere, relative to
the table.
Basic usage:
<table summary="Description Text">
<caption>My Table Of Numbers</caption>
<thead>
<tr>
<th>C 1</th>
<th>C 2</th>
<th>C 3</th>
</tr>
</thead>
<tbody>
<tr>
<td>1-1</td>
<td>1-2</td>
<td>1-3</td>
</tr>
<tr>
<td>2-1</td>
<td>2-2</td>
<td>2-3</td>
</tr>
</tbody>
<tfoot>
<tr>
<th>C 1</th>
<th>C 2</th>
<th>C 3</th>
</tr>
</tfoot>
</table>
JSFiddle: http://jsfiddle.net/vM688/
According to spec, a tr can contain only th and td elements. As other have said, don't be lazy and write the few extra characters to make your HTML valid
Use
<table>
<thead>
<tr>
<!-- text b/w <th></th> will bold and center aligned by default -->
<th> You title here </th>
</tr>
</thead>
<tbody>
<!-- Content of you table here -->
</tbody>
</table>
A td tag stands for table data whereas a tr tag is a table row.
So you make a row in HTML and then add a td to it the number of tds you add decides the number of columns in that row.
A th tag stands for table heading which can be used in a row.
The background color will show if you add the span tag inside the td. Your code will look somewhat like this:
<table><tr class="bg-color"><td><span class="title">My title</span></td></tr></table>
And the css should go like:
.bg-color{background:#ff0000;}
I want to align columns in a table based on a class on the header.
For example, if I have the following table:
<table>
<thead>
<th>Name</th>
<th class="price">Price</th>
</thead>
<tbody>
....
</tbody>
<table>
I know I can use :nth-of-type but sometimes the column will be the 2th, other time will be the 5th and in some places I'll have several columns in the same table align to the right.
Is there a way to accomplish that?
I don't need to support legacy browsers, not even Internet Explorer 9 (if is works on chrome and/or firefox is enough for me)
Just for clarification, I want to align the text in the columns that are in the body associated with the column at the head
No, you cannot style table cells so that styling depends on a class attribute on a column header th. There is nothing in CSS that connects cells that way.
The most robust way to align a column is to generate class attributes on each cell in it. Well, technically, using the HTML align attribute is even more robust.
EDIT: As commented below this only works with a few properties. Text-align isn't included.
Put this in your CSS:
col.price { text-align:right; }
And your HTML:
<table>
<col />
<col class="price" />
<tr>
<td>First TD of first TR</td>
<td>9,95</td>
</tr>
<tr>
<td>First TD of second TR</td>
<td>4,85</td>
</tr>
</table>
Reference:
http://quirksmode.org/css/css2/columns.html
Here is what I need to do.
I'm creating a grid with widgets that are supposed to be represented in a table. Each widget has a variable width that represents the colspan of the td that contains it, and a height of 1 or 2 that is supposed to represent the rowspan of that cells.
Everything works fine, until I'm having a case where all the cells of a row have a colspan of 2, and the next row can have any type of cells. The next row is getting displayed right next to the previous row instead of the next one.
Here is a jsfiddle that replicates the problem and here is the code:
<table>
<tr>
<td rowspan = "2">ONE</td>
</tr>
<tr>
<td rowspan = "1">1</td>
<td rowspan = "1">2</td>
<td rowspan = "1">3</td>
<td rowspan = "1">4</td>
</tr>
</table>
Is this a bug? Am I doing something wrong?
EDIT: To be clear, what I want to do, is having a row of widgets that have twice the height of a regular row
It's difficult to visualize exactly what you want, but perhaps you should be using block elements rather than a table. A table should only be used for tabular data. The rowspan attribute won't function correctly if there aren't any rows to span.
<table>
<tr>
<td rowspan="2">ONE</td>
<td>TWO</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
</table>
See the fiddle
Instead of forcing a thing to two rows, which is normally only done when you have more cells in that set of rows, simply set the cell's height:
http://jsfiddle.net/vjPMw/5/
td {
height: 20px;
background-color: #eee;
}
td.doubleheight {
height: 40px;
}
<table>
<tr>
<td class="doubleheight">ONE</td>
</tr>
<tr>
<td rowspan = "1">1</td>
<td rowspan = "1">2</td>
<td rowspan = "1">3</td>
<td rowspan = "1">4</td>
</tr>
</table>
Really, I'd have expected even that to be unnecessary, as a cell normally expands to contain its contents. Maybe a more complete demo of your situation is in order. Also, I agree with Aarolama Bluenk that maybe a table isn't the right approach here to begin with.
The first row has 1 cell with rowspan=2, so html expects next row to be the one which is "spanned", however you've added row with 4 td's.
I'd recommend adding empty <tr></tr> after first one and play with it OR fix first td to: <td rowspan="2" colspan="4">ONE</td>
How can I specify a td tag should span all columns (when the exact amount of columns in the table will be variable/difficult to determine when the HTML is being rendered)? w3schools mentions you can use colspan="0", but it doesn't say exactly what browsers support that value (IE 6 is in our list to support).
It appears that setting colspan to a value greater than the theoretical amount of columns you may have will work, but it will not work if you have table-layout set to fixed. Are there any disadvantages to using an automatic layout with a large number for colspan? Is there a more correct way of doing this?
Just use this:
colspan="100%"
It works on Firefox 3.6, IE 7 and Opera 11! (and I guess on others, I couldn't try)
Warning: as mentioned in the comments below this is actually the same as colspan="100". Hence, this solution will break for tables with css table-layout: fixed, or more than 100 columns.
I have IE 7.0, Firefox 3.0 and Chrome 1.0
The colspan="0" attribute in a TD is NOT spanning across all TDs in any of the above browsers.
Maybe not recommended as proper markup practice, but if you give a higher colspan value than the total possible no. of columns in other rows, then the TD would span all the columns.
This does NOT work when the table-layout CSS property is set to fixed.
Once again, this is not the perfect solution but seems to work in the above mentioned 3 browser versions when the table-layout CSS property is automatic.
If you want to make a 'title' cell that spans all columns, as header for your table, you may want to use the caption tag (http://www.w3schools.com/tags/tag_caption.asp / https://developer.mozilla.org/en-US/docs/Web/HTML/Element/caption) This element is meant for this purpose. It behaves like a div, but doesn't span the entire width of the parent of the table (like a div would do in the same position (don't try this at home!)), instead, it spans the width of the table. There are some cross-browser issues with borders and such (was acceptable for me). Anyways, you can make it look as a cell that spans all columns. Within, you can make rows by adding div-elements. I'm not sure if you can insert it in between tr-elements, but that would be a hack I guess (so not recommended). Another option would be messing around with floating divs, but that is yuck!
Do
<table>
<caption style="gimme some style!"><!-- Title of table --></caption>
<thead><!-- ... --></thead>
<tbody><!-- ... --></tbody>
</table>
Don't
<div>
<div style="float: left;/* extra styling /*"><!-- Title of table --></div>
<table>
<thead><!-- ... --></thead>
<tbody><!-- ... --></tbody>
</table>
<div style="clear: both"></div>
</div>
As a partial answer, here's a few points about colspan="0", which was mentioned in the question.
tl;dr version:
colspan="0" doesn't work in any browser whatsoever. W3Schools is wrong (as usual). HTML 4 said that colspan="0" should cause a column to span the whole table, but nobody implemented this and it was removed from the spec after HTML 4.
Some more detail and evidence:
All major browsers treat it as equivalent to colspan="1".
Here's a demo showing this; try it on any browser you like.
td {
border: 1px solid black;
}
<table>
<tr>
<td>ay</td>
<td>bee</td>
<td>see</td>
</tr>
<tr>
<td colspan="0">colspan="0"</td>
</tr>
<tr>
<td colspan="1">colspan="1"</td>
</tr>
<tr>
<td colspan="3">colspan="3"</td>
</tr>
<tr>
<td colspan="1000">colspan="1000"</td>
</tr>
</table>
The HTML 4 spec (now old and outdated, but current back when this question was asked) did indeed say that colspan="0" should be treated as spanning all columns:
The value zero ("0") means that the cell spans all columns from the current column to the last column of the column group (COLGROUP) in which the cell is defined.
However, most browsers never implemented this.
HTML 5.0 (made a candidate recommendation back in 2012), the WhatWG HTML living standard (the dominant standard today), and the latest W3 HTML 5 spec all do not contain the wording quoted from HTML 4 above, and unanimously agree that a colspan of 0 is not allowed, with this wording which appears in all three specs:
The td and th elements may have a colspan content attribute specified, whose value must be a valid non-negative integer greater than zero ...
Sources:
https://www.w3.org/TR/html50/tabular-data.html#attributes-common-to-td-and-th-elements
https://html.spec.whatwg.org/multipage/tables.html#attributes-common-to-td-and-th-elements
https://www.w3.org/TR/html53/tabular-data.html#attributes-common-to-td-and-th-elements
The following claims from the W3Schools page linked to in the question are - at least nowadays - completely false:
Only Firefox supports colspan="0", which has a special meaning ... [It] tells the browser to span the cell to the last column of the column group (colgroup)
and
Differences Between HTML 4.01 and HTML5
NONE.
If you're not already aware that W3Schools is generally held in contempt by web developers for its frequent inaccuracies, consider this a lesson in why.
For IE 6, you'll want to equal colspan to the number of columns in your table. If you have 5 columns, then you'll want: colspan="5".
The reason is that IE handles colspans differently, it uses the HTML 3.2 specification:
IE implements the HTML 3.2 definition, it sets colspan=0 as colspan=1.
The bug is well documented.
If you're using jQuery (or don't mind adding it), this will get the job done better than any of these hacks.
function getMaxColCount($table) {
var maxCol = 0;
$table.find('tr').each(function(i,o) {
var colCount = 0;
$(o).find('td:not(.maxcols),th:not(.maxcols)').each(function(i,oo) {
var cc = Number($(oo).attr('colspan'));
if (cc) {
colCount += cc;
} else {
colCount += 1;
}
});
if(colCount > maxCol) {
maxCol = colCount;
}
});
return maxCol;
}
To ease the implementation, I decorate any td/th I need adjusted with a class such as "maxCol" then I can do the following:
$('td.maxcols, th.maxcols').each(function(i,o) {
$t = $($(o).parents('table')[0]); $(o).attr('colspan', getMaxColCount($t));
});
If you find an implementation this won't work for, don't slam the answer, explain in comments and I'll update if it can be covered.
Another working but ugly solution : colspan="100", where 100 is a value larger than total columns you need to colspan.
According to the W3C, the colspan="0" option is valid only with COLGROUP tag.
Below is a concise es6 solution (similar to Rainbabba's answer but without the jQuery).
Array.from(document.querySelectorAll('[data-colspan-max]')).forEach(td => {
let table = td;
while (table && table.nodeName !== 'TABLE') table = table.parentNode;
td.colSpan = Array.from(table.querySelector('tr').children).reduce((acc, child) => acc + child.colSpan, 0);
});
html {
font-family: Verdana;
}
tr > * {
padding: 1rem;
box-shadow: 0 0 8px gray inset;
}
<table>
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
<th>Header 3</th>
<th>Header 4</th>
<th>Header 5</th>
<th>Header 6</th>
</tr>
</thead>
<tbod><tr>
<td data-colspan-max>td will be set to full width</td>
</tr></tbod>
</table>
Simply set colspan to the number of columns in the table.
All other "shortcuts" have pitfalls.
The best thing to do is set the colspan to the correct number to begin with. If your table has 5 columns, set it to colspan="5" That is the only way that will work in all scenarios. No, it's not an outdated solution or only recommended for IE6 or anything -- that's literally the best way to handle this.
I wouldn't recommend using Javascript to solve this unless the number of columns changes during runtime.
If the number of columns is variable, then you'll need to calculate the number of columns so that you can populate the colspan. If you have a variable number of columns, whatever is generating the table should be able to be adapted to also calculate the number of columns the table has.
As other answers have mentioned, if your table is not set to table-layout: fixed, you can also just set colspan to a really large number. But I find this solution messy, and it can be a headache if you come back later and decide it should be a fixed table layout. Better just to do it correctly the first time.
A CSS solution would be ideal, but I was unable to find one, so here is a JavaScript solution: for a tr element with a given class, maximize it by selecting a full row, counting its td elements and their colSpan attributes, and just setting the widened row with el.colSpan = newcolspan;. Like so...
var headertablerows = document.getElementsByClassName('max-col-span');
[].forEach.call(headertablerows, function (headertablerow) {
var colspan = 0;
[].forEach.call(headertablerow.nextElementSibling.children, function (child) {
colspan += child.colSpan ? parseInt(child.colSpan, 10) : 1;
});
headertablerow.children[0].colSpan = colspan;
});
html {
font-family: Verdana;
}
tr > * {
padding: 1rem;
box-shadow: 0 0 8px gray inset;
}
<table>
<tr class="max-col-span">
<td>1 - max width
</td>
</tr>
<tr>
<td>2 - no colspan
</td>
<td colspan="2">3 - colspan is 2
</td>
</tr>
</table>
You may need to adjust this if you're using table headers, but this should give a proof-of-concept approach that uses 100% pure JavaScript.
Anyone else here feel that diving into JS for this seemingly minor issue seems a bit much?
PURE CSS
Boom! I have a pure CSS solution to offer you! Example is below, you just have to add a class to the row that you want to span all columns. Then the CSS will make the first <td> element span the full width and hide the remaining <td> elements. (You must use visibility:hidden; and NOT display:none; for this.)
Note: You will need at least two cells for this method to render nicely, and CSS will render best if you keep the correct quantity of <td> elements - don't remove any to make room for span element. This will help ensure the cells / rows still flow normally.
EXAMPLE
/* standard styling css */
table {
border-collapse: collapse;
}
table, tr, td {
border: 1px solid black;
}
td {
padding: 3px;
}
/* make full width class span the whole table */
.full-span {
position:relative;
}
.full-span > * {
visibility: hidden;
border:0;
}
.full-span > *:nth-child(1) {
display: block;
visibility: unset;
position:absolute;
}
<table>
<tbody>
<tr>
<td>A1</td>
<td>A2</td>
<td>A3</td>
<td>A4</td>
</tr>
<tr class="full-span">
<td>B1 long text</td>
<td>B2</td>
<td>B3</td>
<td>B4</td>
</tr>
<tr>
<td>C1</td>
<td>C2</td>
<td>C3</td>
<td>C4</td>
</tr>
<tr>
<td>D1</td>
<td>D2</td>
<td>D3</td>
<td>D4</td>
</tr>
</tbody>
</table>
Bonus tip!
if you are dynamically producing your table in PHP/JS, this may clean up some of your code. Say you are looping through a 2D array to create a table: for each row that needs to span all columns you'll need to add some logic to calculate the amount of columns, add the colspan attribute, add any remaining <td> elements required to make up the full width of the table and so on.
Using my method, you can loop through all the columns and output them all, and simply include the class in the parent row.
Just want to add my experience and answer to this.
Note: It only works when you have a pre-defined table and a tr with ths, but are loading in your rows (for example via AJAX) dynamically.
In this case you can count the number of th's there are in your first header row, and use that to span the whole column.
This can be needed when you want to relay a message when no results have been found.
Something like this in jQuery, where table is your input table:
var trs = $(table).find("tr");
var numberColumns = 999;
if (trs.length === 1) {
//Assume having one row means that there is a header
var headerColumns = $(trs).find("th").length;
if (headerColumns > 0) {
numberColumns = headerColumns;
}
}
colspan="100%"
it's work also in email outlook , gmail....