Responsive tables, the smart way - html

I've got a table that contains data. Tabular data. And it looks like this.
See this fiddle.
Now what I'd like is, when it's displayed on a narrower screen, for the table to look like this, so that you don't get a horizontal scroll bar and it keeps the same visual structure:
(or if you want, like this fiddle.)
Now my question is, how do you do that? I'd prefer a CSS only way, but so far, I haven't managed to do that in only CSS. (The second fiddle contains rowspan attributes, which don't have CSS equivalents.)
The HTML is generated server side, so I could generate one of the two layouts depending on the window width, but then it wouldn't respond to a window resize.
I'm not against a little Javascript, but in this case, to translate the first table into the second on a window resize, it would need to be taken apart and rebuilt, cell by cell, and I think that's overkill. Still looking for a media query that can do all the work.
Experimenting a bit, I came this close, but that doesn't work in IE8 and IE9.
So, does anybody have any ideas how to tackle this? The ideal solution would work on table cells of varying height (2 lines of text or more) and any number of columns.

ya as your html is same you can change the styles for the css properties according to the media query a better solution would be-
fiddle
#media only screen and (min-width: 769px) {
#content {
border:1px solid;
border-collapse:collapse;
}
#content td, #content th {
border:1px solid;
text-align:left;
padding:.07em .2em;
white-space:nowrap;
font-weight:400;
}
}
#media only screen and (max-width: 768px) {
#content {
border:1px solid;
border-collapse:collapse;
}
#content tr {
height:4em; border-bottom:1px solid;
}
#content th {
border:1px solid;
text-align:left;
padding:.07em .2em;
white-space:nowrap;
font-weight:400;
height:4em;
}
#content td {
padding:.07em .2em;
white-space:nowrap;
height:1.4em;
display:inline;
}
#content td:not(:last-child)::after {
display:block; content:'';
height:0;
border-bottom:1px solid;
}
}
one possible solution is to use media queries an hide the respective blocks
or change styles accordingly
here is a fiddle
changed smaller table id to content2
#media only screen and (max-width: 768px) {
#content{
display:none !important;
}
}
#media only screen and (min-width: 769px) {
#content2{
display:none !important;
}
}

I know this isn't exactly what you want but I created a jsfiddle some time ago as a reference which might help: jsfiddle.net/webbymatt/MVsVj/1
essentially the markup remains the same, there's no JS and the content just reflows as expected. you just need to add the data-type attribute to the table cell.

Check this CodePen.
I found this solution long ago in css-tricks.com.
The table gets a little messy:
<table>
<tr>
<td>
Description 1
</td>
<td>
<table class="responsive" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td class="text-center">Data 1A</td>
<td class="text-center">Data 1B</td>
<td class="text-center">Data 1C</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>
Description 2
</td>
<td>
<table class="responsive" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td>Data 2A</td>
<td>Data 2B</td>
<td>Data 2C</td>
</tr>
</tbody>
</table>
</td>
</tr>
</table>
And this is the css:
/* Small display targeting */
#media only screen and (max-width: 767px) {
/* Force table to not be like tables anymore */
.responsive, .responsive thead, .responsive tbody, .responsive th, .responsive td, .responsive tr {
display: block;
}
/* Hide table headers (but not display: none;, for accessibility) */
.responsive thead tr {
position: absolute;
top: -9999px;
left: -9999px;
}
.responsive td {
/* Behave like a "row" */
position: relative;
}
.responsive td:before {
/* Now like a table header */
position: absolute;
}
}

You could inline block the elements. I haven't had much time to play, but something like the following:
#content {
border:1px solid;
border-collapse:collapse;
}
#content td, #content th {
border:1px solid;
text-align:left;
padding:.07em .2em;
white-space:nowrap;
font-weight:400;
}
#content td {
display: inline-block;
width: 100px;
}
It's not the prettiest creation, though!
http://jsfiddle.net/8H3bN/

Related

Why does my table not scale within the div?

I have a very simple webpage for homework. The body just consists of various sections div /divbr. The effect is various boxes for each part. Most of my students don't have a computer, they only have a mobile phone. So I am trying to make the webpage display better on mobile phones. I put:
<meta name="viewport" content="width=device-width, initial-scale=1.0">
in the header.
I set all divs to width:95%;
Everything displays nicely on my phone now. The text is a good size, everything is within the confines of the mobile phone screen, no need to magnify with 2 fingers.
EXCEPT my table.
.div-table
{
width:95%;
border:3px;
border-style:solid;
border-color:#FF0000;
text-align:center;
background-color:#32d140;
}
table
{
margin:0 auto;
width:90%;
text-align:center;
background-color:whitesmoke;
border-collapse: separate;
border: 2px solid black;
}
table td {
/*border: 2px solid black;*/
border-style:dotted;
border-width:3px;
border-collapse:separate;
padding: 10px;
}
<div class="div-table">
<p>
<table>
<tr> <td>A watches</td> <td>B cinema</td> <td>C weird</td> <td>D doesn't</td> <td>E like</td> </tr>
<tr> <td>F games</td> <td>G talking</td> <td>H guy</td> <td>I unusual</td> <td>J teaches</td> </tr>
</table>
</p>
</div>
The table spills over its div. You can scroll right a bit to see the last columns. The table was 2 rows of 5 cells. I changed it to 5 rows of 2 cells to get around this now, but I prefer 2 rows 5 columns.
Why does my table not shrink to fit its div? Could you please help me tweak the css to shrink the table?
Basically your table is overflowing, to make it neat and clean you can make it responsive. You can either make the table responsive by adding a horizontal scroll, so users can scroll and see the content. You just have to add following styles in media query, You can see it here
#media (max-width: 767px){
.div-table{
overflow-x: auto;
}
.div-table table{
width: 100%;
}
}
Or, Other option is stacking it vertically which is bit more user friendly, you can see it here
I'm not sure you can confine the table within the div and successfully display it at every resolution.
An alternative solution would be to allow the table to overflow, thereby making it scrollable:
Adding overflow-x: auto; to div-table should work for you:
CSS
.div-table {
width:95%;
border:3px;
border-style:solid;
border-color:#FF0000;
text-align:center;
background-color:#32d140;
overflow-x:auto;
}
.div-table {
width:95%;
border:3px;
border-style:solid;
border-color:#FF0000;
text-align:center;
background-color:#32d140;
overflow-x:auto;
}
table {
margin:0 auto;
width:90%;
text-align:center;
background-color:whitesmoke;
border-collapse: separate;
border: 2px solid black;
}
table td {
/*border: 2px solid black;*/
border-style:dotted;
border-width:3px;
border-collapse:separate;
padding: 10px;
}
<div class="div-table">
<p>
<table>
<tr> <td>A watches</td> <td>B cinema</td> <td>C weird</td> <td>D doesn't</td> <td>E like</td> </tr>
<tr> <td>F games</td> <td>G talking</td> <td>H guy</td> <td>I unusual</td> <td>J teaches</td> </tr>
</table>
</p>
</div>

HTML CSS Responsive Table & CSS Before

My aim is to create responsive tables design that look good when viewing on mobiles (width under 480px).
I have the following markup for my table:
<table class="table eventlist">
<thead>
<tr>
<th>Date</th>
<th>Time</th>
<th>Duration</th>
<th>Location</th>
<th>Cost</th>
</tr>
</thead>
<tr>
<td data-title="Code">AAC</td>
<td data-title="Company">AUSTRALIAN AGRICULTURAL COMPANY LIMITED.</td>
<td data-title="Price" class="numeric">$1.38</td>
<td data-title="Change" class="numeric">-0.01</td>
<td data-title="Change %" class="numeric">-0.36%</td>
<td data-title="Open" class="numeric">$1.39</td>
</tr>
</table>
And the following CSS:
/* Landscape phones and down */
#media (max-width: 480px) {
/* Force table to not be like tables anymore */
table, thead, tbody, th, td, tr {
display: block;
}
/* Hide table headers (but not display: none;, for accessibility) */
thead tr {
position: absolute;
top: -9999px;
left: -9999px;
display:none;
}
tr {
border: 1px solid #ccc;
}
td {
/* Behave like a "row" */
border: none;
border-bottom: 1px solid #eee;
position: relative;
padding-left: 50%;
white-space: normal;
text-align:right;
}
td:before {
padding-right: 10px;
white-space: nowrap;
text-align:left;
font-weight: bold;
}
/*
Label the data
*/
td:before {
content: attr(data-title);
}
}
My table ends up looking like this:
Would you say this is a good user friendly responsive design?
How can I edit the line:
td:before {
content: attr(data-title);
}
So that it reads the <th> for the column?
Here is a live example: JS Fiddle
Re: Would you say this is a good user friendly responsive design?
The layout of it looks great for a single symbol, and still looks quite good for multiple rows when not in "mobile-mode", however if you plan on having multiple quotes, I think it's going to wind up looking quite cluttered on small screens. You might consider removing the borders between rows and only having lines between quotes to keep it visually cleaner.
Just my .02 from a design perspective.

Firefox not respecting visibility:hidden on table header

I want the header of the first column in my table to be hidden, to get this look:
So I am using the CSS visibility: hidden; to do so. The screenshot above is taken in Chrome, where it works perfectly. However, this happens in Firefox:
How can I make Firefox hide the header of the first column in a table?
EDIT: Here's my table CSS, as requested:
.styledtable{
width:100%;
table-layout:fixed; /*each column same width, unless width explicitly specified*/
border:1px solid black;
border-collapse:collapse;
}
.styledtable td, .styledtable th{
border:1px solid black;
padding:3px;
}
.styledtable th{ background:#cfcfcf; }
.styledtable td{ background:white; }
/* in a table with the first columnn empty (ie. with actions in the column below it),
* make the first column take up space, but not actually appear.
* Usage: <th style="width:40%;" class="firstcol"> </th>
*/
.firstcol{
visibility:hidden;
}
/*every second row different color, if the table itself doesn't have the class "no-odd-row-highlight"*/
.styledtable:not(.no-odd-row-highlight) tr:nth-child(odd) td{ background:#eeeeee; }
This works for me in all major browsers:
<style type="text/css">
table {
border: none;
padding: 0;
border-spacing: 0;
border-collapse: collapse;
}
table th,
table td {
margin: 0;
background: #fff;
border: 1px solid #000;
padding: 0;
}
table th.hidden {
border: none;
visibility: hidden;
}
</style>
<table>
<tr>
<th class="hidden"></th>
<th>ID</th>
<th>Something</th>
</tr>
<tr>
<td>Options</td>
<td>1</td>
<td>---</td>
</tr>
</table>
Depends upon what you want to achieve in styling, but generally, setting relevant element's (color/background-color/border-(top n left)-color(in this case)) to 'transparent' usually works across browsers.
hope this helps someone.

Issue to scroll tbody on IE 9 (tbody's height = height-line)

Sorry for my bad English, I hope you're going to understand what I want to say...
I'm trying to implement an HTML table which support scrolling of table bodies independently of the table head.
I found the following question which helped me a lot :
How to scroll table's "tbody" independent of "thead"?
I tested the following code, it works on Chrome (22), Firefox (16) and Opera (12) without issue :
HTML :
<table>
<thead>
<tr>
<th>Title1</th>
<th>Title2</th>
<!-- ... -->
</tr>
</thead>
<tbody>
<tr>
<td>...</td>
<td>...</td>
<!-- ... -->
</tr>
<!-- ... -->
</tbody>
</table>
CSS :
thead, tbody {
display: block;
}
tbody {
height:500px;
overflow-y:auto;
overflow-x:hidden;
}
thead {
line-height: 20px;
}
So it works on the main browsers except IE 9, on IE, I have some issues :
The tbody's height is not defined (so I don't have any scrollbar)
Each has an height of 500px (the tbody's height on other browsers)
The two following examples have exactly the same issues : http://jsfiddle.net/nyCKE/2/ , http://www.imaputz.com/cssStuff/bigFourVersion.html
I saw the following question (and answer) but it doesn't help me : IE9 + css : problem with fixed header table
So I'm sure that the bug comes from IE but I don't have any idea how to fix it without change my HTML structure.
Have someone any idea ?
I have slightly tried to fix it. Hope it gives some idea
HTML
<div class="wrap">
<div class="inner">
<table>
<thead><tr>
<th><p>Problem</p></th>
<th><p>Solution</p></th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>​
CSS
p {margin:0 0 1em}
table p {margin :0}
.wrap {
margin:50px 0 0 2%;
float:left;
position:relative;
height:200px;
overflow:hidden;
padding:25px 0 0;
border:1px solid #000;
width:150px
}
.inner {
padding:0 ;
height:200px;
overflow:auto;
}
table { margin:0 0 0 -1px; border-collapse:collapse; width:130px}
td {
padding:5px;
border:1px solid #000;
text-align:center;
}
thead th {
font-weight:bold;
text-align:center;
border:1px solid #000;
padding:0 ;
color:#000;
}
thead th {border:none;}
thead tr p { position:absolute; top:0; }
.last { padding-right:15px!important; }​
Demo http://jsfiddle.net/nyCKE/272/
Here is a shorter answer that allows you to scroll the table with a fixed header in ie9.
Add a conditional div around the table
<!--[if lte IE 9]>
<div class="old_ie_wrapper">
<!--<![endif]-->
<table>
...
<!--[if lte IE 9]>
</div>
<!--<![endif]-->
Add the following styles for ie9
.old_ie_wrapper {
height: 500px;
overflow: auto;
}
.old_ie_wrapper tbody {
height: auto;
}
.old_ie_wrapper thead tr {
position: absolute;
}
.old_ie_wrapper tbody tr:first-child {
height: 67px;
vertical-align: bottom;
}
You will have to adjust the heights and probably other properties based on your table.

Make link in table cell fill the entire row height

I have a table of data and each cell is a link. I want to allow the user to click anywhere in the table cell and have them follow the link. Sometimes the table cells are more than one line but not always. I use td a {display: block} to get the link to cover most of the cell. When there is one cell in a row that is two lines and the others are only one line the one liners don't fill the entire vertical space of the table row. Here is the sample HTML and you can see it in action here http://www.jsfiddle.net/RXHuE/:
<head>
<style type="text/css">
td {width: 200px}
td a {display: block; height:100%; width:100%;}
td a:hover {background-color: yellow;}
</style>
<title></title>
</head>
<body>
<table>
<tbody>
<tr>
<td>
<a href="http://www.google.com/">Cell 1<br>
second line</a>
</td>
<td>
Cell 2
</td>
<td>
Cell 3
</td>
<td>
Cell 4
</td>
</tr>
</tbody>
</table>
</body>
Set an arbitrarily large negative margin and equal padding on the block element and overflow hidden on the parent.
td {
overflow: hidden;
}
td a {
display: block;
margin: -10em;
padding: 10em;
}
http://jsfiddle.net/RXHuE/213/
You need a small change in your CSS. Making td height:100%; works for IE 8 and FF 3.6, but it doesn't work for Chrome.
td {
width: 200px;
border: solid 1px green;
height: 100%
}
td a {
display: block;
height:100%;
width:100%;
}
But making height to 50px works for Chrome in addition to IE and FF
td {
width: 200px;
border: solid 1px green;
height: 50px
}
td a {
display: block;
height:100%;
width:100%;
}
Edit:
You have given the solution yourself in another post here; which is to use display: inline-block;.
This works when combined with my solution for Chrome, FF3.6, IE8
td {
width: 200px;
border: solid 1px green;
height: 100%}
td a {
display: inline-block;
height:100%;
width:100%;
}
Update
The following code is working for me in IE8, FF3.6 and chrome.
CSS
td {
width: 200px;
border: solid 1px green;
height: 100%;
}
td a {
display: inline-block;
height:100%;
width:100%;
}
td a:hover {
background-color: yellow;
}
HTML
<table>
<tbody>
<tr>
<td>
<a href="http://www.google.com/">Cell 1<br>
second line</a>
</td>
<td>
Cell 2
</td>
<td>
Cell 3
</td>
<td>
Cell 4
</td>
</tr>
</tbody>
</table>
The example lays here
Little late to the party, but there's a nice solution I just discovered.
You can use a combination of relative and absolute positioned elements, along with a pseudo element to get the effect you're looking for. No extra markup needed!
Change the table cell (<td>), to be position: relative;, and create a ::before or ::after pseudo element on the <a> tag, and set it to position: absolute;, and also use top: 0; left: 0; right: 0; bottom: 0;.
Because the pseudo element is attached to the anchor tag, and you're telling it to take up the entire table cell, it will force the anchor tag to be at least that size, whilst not affecting the actual content of the anchor tag itself (thereby retaining its vertically centered alignment).
For example
table {
border-collapse: collapse;
table-layout: fixed;
}
td {
position: relative;
width: 200px;
padding: 0.5em 1em;
border: 2px solid red;
background-color: lime;
}
td a {
/* FONT STYLES HERE */
text-decoration: none;
}
td a::after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 0;
}
<table>
<tbody>
<tr>
<td>
<a href="http://www.google.com/">Cell 1<br>
second line</a>
</td>
<td>
Cell 2
</td>
<td>
Cell 3
</td>
<td>
Cell 4
</td>
</tr>
<tr>
<td>
Cell 5
</td>
<td>
<a href="http://www.google.com/">Cell 6<br>
second line</a>
</td>
</tr>
</tbody>
</table>
Hope this helps!
Following hack works [Tested on Chrome / Firefox / Safari]
Have the same padding for td and anchor elements. And for anchor also have margin which is equal to -ve of padding value.
HTML
<table>
<tr>
<td><a>Hello</a></td>
</tr>
</table>
CSS:
td {
background-color: yellow;
padding: 10px;
}
a {
cursor:pointer;
display:block;
padding: 10px;
margin: -10px;
}
Working Fiddle :http://jsfiddle.net/JasYz/
Try display: block:
td a {display: block; height:100%;}
[EDIT] WTF ... I can confirm this doesn't work in FF 4 and Chrome. This works:
td a {display: block; height: 2.5em; border: 1px solid red;}
That suggests that height:100%; isn't defined in a table cell. Maybe this is because the cell gets its size from the content (so the content can't say "tell me your size" because that would lead to a loop). It doesn't even work if you set a height for the cells like so:
td {width: 200px; height: 3em; padding: 0px}
Again the code above will fail. So my suggestion is to use a defined height for the links (you can omit the width; that is 100% by default for block elements).
[EDIT2] I've clicked through a hundred examples at http://www.cssplay.co.uk/menus/ but none of them mix single line and multi-line cells. Seems like you hit a blind spot.
I will post the same answer here, as I did on my own question.
Inspired by Jannis M's answer, I did the following:
$(document).ready(function(){
$('table tr').each(function(){
var $row = $(this);
var height = $row.height();
$row.find('a').css('height', height).append(' ');
});
});
I added a since empty links (not containing text nodes) can not be styled(?).
See my updated fiddle.
Only problem here is that using display: block forces the browser to ignore the vertical align: center...
oops.
I jury rigged it to look right for one cell with height:60 and a font that occupied 20 pixels by adding a br... Then I realized that I had some items with 2-line text. Dang.
I ended up using the javascript. The javascript doesn't give the nice mousey pointy clicker thing, but the line of text does, so it will actually trigger a visual response, just not where I want it to... Then the Javascript will catch all the clicks that 'miss' the actual href.
Maybe not the most elegant solution, but it works well enough for now.
Now if I could only figure out how to do this the right way....
Any ideas on how to add the mouse icon change to a hand for the area covered by the onclick? Right now, the click to page works, but the icon only changes when it hits the href which only affects the text.
Why don't you just get rid of the <a> altogheter and add an onClick to the <td> directly?
<head>
<style type="text/css">
td {
text-align:center;
}
td:hover {
cursor:pointer;
color:#F00;
}
</style>
<title></title>
</head>
<body>
<table>
<tbody>
<tr>
<td onclick="location.href='http://www.google.com/';">Cell 1<br />second line</td>
<td onclick="location.href='http://www.google.com/';">Cell 2</a></td>
<td onclick="location.href='http://www.google.com/';">Cell 3</td>
<td onclick="location.href='www.google.com';">Cell 4</td>
</tr>
</tbody>
</table>
This way you cut out the middle man.
PS: i know this was asked and answered many years ago, but none of the answers above solved the problem in my case. Hope this helps someone.
For me the only solution is to replace <table> <tr> with <div>s and style them using display:table and display:table-row accordingly.
Then you can replace <td> with just <a> and style it with display:table-cell.
Work perfectly even on varying heights of <td> contents.
so original html without anchors:
<table>
<tr>
<td>content1<br>another_line</td>
<td>content2</td>
</tr>
</table>
now becomes:
a:hover
{
background-color:#ccc;
}
<div style="display:table; width:100%">
<div style="display:table-row">
content1<br>another_line
content2
</div>
</div>
I have used this solution: works better then the rest in my case.
CSS:
.blocktd {width: 100%; height: 100%; padding: 0px; overflow: hidden}
a.blocktd {margin: 0em; padding: 50px 20px 50px 20px; display: block;}
a.blocktd:hover {border: 4px solid #70AEE8; border-radius: 10px; padding: 46px 16px 46px 16px; transition: 0.2s;}
And in HTML: ...