Have you ever wanted to absolutely or relatively position a table cell? Well, I can’t help you there. Table cell elements just won’t take those position values. And thus, you also can’t absolutely position elements within the context of those elements either. I can help you out with that issue.
The answer is just to make a generic wrapper element inside the table cells (the exact same size of the table cell) and use that as the relative positioning context. Non-semantic? Yep, but we’ll chuck that markup in with JavaScript so it’s not a big deal. Kludgy fix? You know it. Does it work? Sure does.
Before
<table>
<tr>
<td>
<img src="yay.jpg" alt="">
</td>
</tr>
</table>
After
<table>
<tr>
<td>
<div class="innerWrapper"> <!-- appended with JavaScript -->
<img src="yay.jpg" alt=""> <!-- original content of cell -->
</div>
</td>
</tr>
</table>
jQuery Plugin
You could insert your inner div wrappers however you want, but there is appeal to using JavaScript/jQuery to do it because 1) it’s pretty easy and 2) it keeps your markup the same / clean.
We’ll make a quick jQuery plugin here, so that it can be called on any arbitrary set of elements.
$.fn.iWouldLikeToAbsolutelyPositionThingsInsideOfFrickingTableCellsPlease = function() {
var $el;
return this.each(function() {
$el = $(this);
var newDiv = $("<div />", {
"class": "innerWrapper",
"css" : {
"height" : $el.height(),
"width" : "100%",
"position": "relative"
}
});
$el.wrapInner(newDiv);
});
};
This plugin iterates through each element it is passed, creates a <div>
which has relative positioning and is the same height and width of the parent cell, then wraps the inside of that cell within itself.
Bear in mind I’m not using all the generally-regarded-as-smart plugin conventions like this does.
Usage
Load jQuery. Then run the above plugin code. Then use the plugin like this, either at the bottom of your web page or within a DOM ready statement.
$("th, td").iWouldLikeToAbsolutelyPositionThingsInsideOfFrickingTableCellsPlease();
That appends the inner wrapper to all table cells (<th>
and <td>
elements) although as you can see you can apply it to any arbitrary set of elements.
Nice function name :)
Been thinking about table styling recently, with regard to displaying them reasonably on mobile devices. All the usual fluid width or arranging elements vertically stuff can’t really be applied, particularly if the table has a lot of columns. Mostly tables just end up being cropped or the user has to do a lot of scrolling in all directions.
I haven’t seen a suitable solution and even the W3C seem to write it off as impossible.
I’m wondering if some sort of absolute positioning might help as presumably with this technique you can force elements to move outside of their containing cell?
“Non-semantic? Yep, but we’ll chuck that markup in with JavaScript so it’s not a big deal.” There is totally no difference between putting that DIV element in initial source or add it later with Javascript. If you need it, you use it. “HTML validation” is just a tool, not something to hack.
doing it via javascript keeps the static markup clean for later, but in the grand scheme of things – yeah, you’re right.
Me, I don’t have static markup – all my markup is generated via php – so I wouldn’t bother with the javascript anyway.
There’s a difference between doing it with PHP vs. JS – with JS a screen reader with JavaScript disabled will just see the semantic markup, whereas if it was done in PHP they couldn’t avoid it.
very true. didn’t consider that.
Is it possible by doing this method without JavaScript, Do we have any alternative for the same doing this trick only with CSS?
Some missing pieces of info:
Test what you make without JavaScript on. And if you can get it to look good with both JavaScript on and off, go with the JavaScript method. Why? Well, you put the class on the and if someday it is possible to get the styles using semantic CSS, you aren’t leaving non-semantic tags in your files.
Also, it is a possible file-size performance win if you keep the function cached and the semantic HTML as the only part downloaded uniquely. Especially if you use this on every page, and you have lots of page-views per user. Of course, if you only use this on a couple pages or users only view a few pages and leave, this part is false and you can implement this using a server-side language such as PHP like Thaq is doing.
Now a days nobody use or , Its good to be working with tag..
I love the name of the jquery plugin class!
Contrary to the article, you can absolutely position table rows and it works fine in IE7+ and standards compliant browsers.
We have an internal tool that is basically a stripped down database editor which displays the fields in a given MySQL table as an HTML table, in order of appearance in the MySQL table.
I wanted to see the rows in a different order and group them by color, but I didn’t have access to the source of the editor, only the CSS of the page. So I used CSS and absolute positioning to position the table rows in different places. So at least one table element other than the table itself can be absolutely positioned.
You can fixed position rows as well, which is handy. I’ll update the wording of the article to be more accurate.
Excellent article and a great tutorial on writing jQuery functions.
do you always have to sound so miserable? thanks for the tips ; D
thanks for the tips, gonna try this out now!
Great find, but IMHO not the best solution. There is a much easier and faster way to do it with CSS without even using your jquery hack (which what this is really) so, when epople dont have JS turned on, you basically wouldnt be able to use this effect.
Anyways, this is what I came up with (had to do the same effect in one of our projects and I was hoping theres a better way around it because we use tables in most of our WordPress sites for layout, easier to keep the sidebars and content more flexible, so it took me a while, but it works perfect) :
What I am trying to do is to have a cell that spans 2 rows and has all the major elements in it align to the top and have the last widget (testimonial) be “sticking” to the bottom of the cell every time the cell height resizes with another cell (content) getting longer:
Ex.:
[Table] /* Our structure table ; CSS: position:relative; display:block; height:100% */ instead of display:cell-table which is the default, also 100% has to be used if your table has a parant div container so it also fits into it instead of just automatically resizing
[TR]
[TD colspan=2 valign=top][/TD] Our content cell, when it resizes, the cell grows down
[TD rowspan=2 valign=top height=100%] Right Sidebar “all elements supposed to float to top and height adjusts to height of the whole table, not just elements inside the cell*/
…..
[div class=testimonial][/div] /* CSS: display:block; bottom:0; width:200px; height:auto; position:absolute;
[/TD]
[TR]
done, this works for me very fine, try it
[TR]
….
[TR]
[/Table]
Cool name for jQuery plugin class :) Thx for the tips