I am working on responsive css for a table. I read a tutorial from this link http://css-tricks.com/responsive-data-tables/ (How to make responsive table on css). It worked on some sample page but in my HTML page I have some problem on re-sizing of window and the table does not respond correctly. Here's my HTML code:
<style>
/*
Generic Styling, for Desktops/Laptops
*/
table
{
width: 100%;
border-collapse: collapse;
}
/* Zebra striping */
tr:nth-of-type(odd)
{
background: #eee;
}
th
{
background: #333;
color: white;
font-weight: bold;
}
td, th
{
padding: 6px;
border: 1px solid #ccc;
text-align: left;
}
/*
Max width before this PARTICULAR table gets nasty
This query will take effect for any screen smaller than 760px
and also iPads specifically.
*/
#media only screen and (max-width: 760px), (min-device-width: 768px) and (max-device-width: 1024px)
{
/* 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;
}
tr
{
border: 1px solid #ccc;
}
td
{
/* Behave like a "row" */
border: none;
border-bottom: 1px solid #eee;
position: relative;
padding-left: 50%;
}
td:before
{
/* Now like a table header */
position: absolute; /* Top/left values mimic padding */
top: 6px;
left: 6px;
width: 45%;
padding-right: 10px;
white-space: nowrap;
}
/*
Label the data
*/
td:nth-of-type(1):before
{
content: "First Name";
}
td:nth-of-type(2):before
{
content: "Last Name";
}
td:nth-of-type(3):before
{
content: "Job Title";
}
td:nth-of-type(4):before
{
content: "Favorite Color";
}
td:nth-of-type(5):before
{
content: "Wars of Trek?";
}
td:nth-of-type(6):before
{
content: "Porn Name";
}
td:nth-of-type(7):before
{
content: "Date of Birth";
}
td:nth-of-type(8):before
{
content: "Dream Vacation City";
}
td:nth-of-type(9):before
{
content: "GPA";
}
td:nth-of-type(10):before
{
content: "Arbitrary Data";
}
}
</style>
<body>
<table>
<thead>
<tr>
<th>
First Name
</th>
<th>
Last Name
</th>
<th>
Job Title
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
James
</td>
<td>
Matman
</td>
<td>
Chief Sandwich Eater
</td>
</tr>
<tr>
<td>
The
</td>
<td>
Tick
</td>
<td>
Crimefighter Sorta
</td>
</tr>
</tbody>
</table>
</body>
</html>
It shows the output on re-size window like the figure below:
and it worked well on js-fiddle like the figure below:
Link: http://jsfiddle.net/Cd9Yp/
What's wrong in my code? Can any one guide me, thanks!
Try to define a min-width between your specified viewport. To the parent element table and the child tr if wanted / needed.
table {
width: 100%;
min-width: 320px; // this should do it
border-collapse: collapse;
}
And.
tr {
min-width: 200px; // specify if additionally needed or wanted
}
What resolution are you optimizing for -- I see your #media is tablet but your shooting for smaller obviously -- you shouldn't need to go below 320px; in most cases, so if you minimize below that it shouldn't matter.
Also, why not use nested divs?
It's small mistake i don't specify top of html document type as html5
after it does work perfectly on existing code
<!DOCTYPE html>
Related
I am trying to render the html tags like br,p space tags etc in the td tag that has display:flex.
Note: this is our existing code
red highlighted text (p tags) are need to render with the each new line on the right side but it just renders horizontal in one line
When i try to change display:block the red highlighted displays correct but not render as table on the right column
I want to achieve this
I am not familiar with the display:flex. 'display:flex' is not friendly with the td element if it has html tags? how to achieve with flex and render with html tags.
Give this CSS to parent element of these three boxes:
{
display: flex;
flex-direction: column;
}
I didn't see your full code, but if you want three red box in column and in right side, use this.
I know that you've only asked about the right column, but you should also know that you're not using tables as they should be used here. Your pseudo-element labels are not only making things harder for yourself, they're also not accessible, and they should just be presented as the tabular data they are.
That said, you should really refactor your code.
Like others mentioned, you can use flex-direction: column on that specific cell, if that cell is set to display: flex. That'll then make all of the children inside that cell be organised in a top-to-bottom column, rather than the default left-to-right.
You didn't provide your original code, but he's a refactor including a solution to your issue.
.table {
background-color: #f5f5f5;
border: 1px solid #e3e3e3;
border-spacing: 0 .25em;
padding: 1em;
}
.table__row > * {
vertical-align: top;
text-align: left;
padding: .25em;
}
.table__row th {
background-color: #fefb54;
}
.table__row td {
background-color: #ea4025;
}
.table__row--heading {
background-color: #952516;
color: white;
}
.table__row--heading th,
.table__row--heading td {
background-color: transparent;
}
.table__row th + td {
display: flex;
vertical-align: top;
flex-direction: column;
}
.table__row p {
margin: 0;
}
.table__row p + * {
margin-block-start: 0.5em;
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
<table class="table">
<tr class="table__row table__row--heading">
<th><span class="sr-only">First Name</span></th>
<td>John</td>
</tr>
<tr class="table__row table__row--name">
<th>Last Name</th>
<td>Smith</td>
<tr>
<tr class="table__row table__row--gender">
<th>Gender</th>
<td>
<p>this is a first gender</p>
<p>(break point) </p>
<p>this is the final gender</p>
</td>
</tr>
</table>
You can follow this structure to achieve your requiremnt:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Code</title>
<style>
table {
border-collapse: collapse;
width: 100%;
}
td {
display: block;
}
td.first:before {
content: "First Name";
width: 200px;
display: inline-block;
}
td.last:before {
content: "Last Name";
width: 200px;
display: inline-block;
}
td.gender {
display: flex;
flex-direction: row;
}
td.gender:before {
content: "Gender";
width: 200px;
}
td.gender div p {
margin: 0;
}
</style>
</head>
<body>
<table>
<tbody>
<tr>
<td class="first" title="First Name">John</td>
<td class="last" title="Last Name">Dave</td>
<td class="gender" title="Gender">
<div>
<p>first gender</p>
<p>break point</p>
<p>last gender</p>
</div>
</td>
</tr>
</tbody>
</table>
</body>
</html>
Here is the demo link:
Demo
I have this css style for responsive table. it works as expected in firefox but not in chrome.
In chrome all the text mixed, and it seems that their is a layers.
what is the problem in the code that it works on firefox but not in chrome?
#media only screen and (max-width: 800px) {
/* 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;
}
tr {
border: 1px solid #ccc;
}
td {
/* Behave like a "row" */
border: none;
border-bottom: 1px solid #eee;
position: relative;
padding-right: 50%;
white-space: normal;
text-align: right;
}
td:before {
/* Now like a table header */
position: absolute;
/* Top/left values mimic padding */
top: 6px;
right: 6px;
width: 45%;
padding-right: 10px;
white-space: nowrap;
text-align: right;
font-weight: bold;
}
/*
Label the data
*/
td:before {
content: attr(data-title);
};
}
<table>
<thead>
<tr>
<th>title 1</th>
<th>title 2</th>
<th>title 3</th>
<th>title 4</th>
<th>title 5</th>
</tr>
</thead>
<tbody>
<tr>
<td data-title="title1">
text
</td>
<td data-title="title2">
text
</td>
<td data-title="title3">
text
</td>
<td data-title="title4">
text
</td>
<td data-title="title5">
text
</td>
</tr>
</tbody>
</table>
In the preview it seems ok in chrome byt if I create new simple html file with the table in the body it look very bad.
I understand that I need add something to the css or to the body but I dont know what.
This is how it looks like when I make the screen width small then 800px
From the comments it was found you were missing a doctype. A doctype is required of all modern web pages. Without one, you are in "quirks mode" and things like margin and padding and all kinds of things do not follow the W3C box model.
Adding this to the very first line keeps all browsers in "standards mode"
<!DOCTYPE html>
Activating Browser Modes with Doctype
Chris Coyier wrote an excellent article on making HTML tables better on mobile by structuring them as a list. I love the method, but the tables I deal with are dynamic, and I can't really go into the CSS like he does and label each header title using a content tag.
/*
Label the data
*/
td:nth-of-type(1):before { content: "First Name"; }
td:nth-of-type(2):before { content: "Last Name"; }
td:nth-of-type(3):before { content: "Job Title"; }
td:nth-of-type(4):before { content: "Favorite Color"; }
td:nth-of-type(5):before { content: "Wars of Trek?"; }
td:nth-of-type(6):before { content: "Porn Name"; }
td:nth-of-type(7):before { content: "Date of Birth"; }
td:nth-of-type(8):before { content: "Dream Vacation City"; }
td:nth-of-type(9):before { content: "GPA"; }
td:nth-of-type(10):before { content: "Arbitrary Data"; }
Here's an example of it in action: https://css-tricks.com/examples/ResponsiveTables/responsive.php
But is there a way to make it so I don't have to manually label the headers?
Dynamic content headers with jQuery
We can assign a column number to each cell with .index(). The first column cells have an index number of 0, the second column index is 1, the third column index is 2, etc.
Now that we can identify each column with a number, we can give each cell the correct header text.
Each table header is given a dynamic class based on its column index number starting at header-0.
$('th').each(function () {
$(this).addClass('header-' + $(this).index());
});
Each table cell is given a data-header attribute containing the text of its corresponding header. It selects the table header by the class and matching index number.
$('td').each(function () {
$(this).attr('data-header', $('.header-' + $(this).index()).text());
});
Note: There will be a more efficient method to achieve this.
Complete Example
Change the text in each <th> to see it change for every row.
//Assign class to each header
$('th').each(function() {
$(this).addClass('header-' + $(this).index());
});
//Assign a data-header attribute with the text from the corresponding header
$('td').each(function() {
$(this).attr('data-header', $('.header-' + $(this).index()).text());
});
/* 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;
}
tr {
border: 1px solid #ccc;
}
td {
/* Behave like a "row" */
border: none;
border-bottom: 1px solid #eee;
position: relative;
padding-left: 50%;
}
td:before {
/* Now like a table header */
position: absolute;
/* Top/left values mimic padding */
top: 6px;
left: 6px;
width: 45%;
padding-right: 10px;
white-space: nowrap;
content: attr(data-header);
}
table {
width: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<table>
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
</tr>
</thead>
<tbody>
<tr>
<td>John</td>
<td>Smith</td>
</tr>
<tr>
<td>John</td>
<td>Smith</td>
</tr>
<tr>
<td>John</td>
<td>Smith</td>
</tr>
<tr>
<td>John</td>
<td>Smith</td>
</tr>
<tr>
<td>John</td>
<td>Smith</td>
</tr>
</tbody>
</table>
After I saw the article (and the comments) I will copy and paste one of the comments:
Use data attributes for cells so content is in html and not in css:
<td data-label="First Name">Doug</td>
then css is more like:
td:before { content: attr(data-label); }
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/
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.