Grow your CSS skills. Land your dream job.

Absolutely Position Element Within a Table Cell

Published by Chris Coyier

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.

View Demo

Comments

  1. 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?

  2. Maris
    Permalink to comment#

    “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.

    • Permalink to comment#

      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.

    • Permalink to comment#

      very true. didn’t consider that.

  3. Permalink to comment#

    Is it possible by doing this method without JavaScript, Do we have any alternative for the same doing this trick only with CSS?

  4. Havvy
    Permalink to comment#

    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.

  5. Permalink to comment#

    Now a days nobody use or , Its good to be working with tag..

  6. Christopher Smoak
    Permalink to comment#

    I love the name of the jquery plugin class!

  7. Permalink to comment#

    Excellent article and a great tutorial on writing jQuery functions.

  8. Jose
    Permalink to comment#

    do you always have to sound so miserable? thanks for the tips ; D

  9. thanks for the tips, gonna try this out now!

  10. 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]

  11. Permalink to comment#

    Cool name for jQuery plugin class :) Thx for the tips

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".