CSS to display table row headers above data cells - html

Suppose I have a table like this on an HTML page, with a purple border around the th cells and a green border around the td cells:
Some code that produces this (the CSS for the view-small class isn't in use in the above display but it's about to be explained):
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Table Transformation</title>
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,400italic,700,700italic' rel='stylesheet' type='text/css'>
<link href='https://fonts.googleapis.com/css?family=Open+Sans+Condensed:300,300italic,700' rel='stylesheet' type='text/css'>
<style>
body { font-family: "Opens Sans", sans-serif; }
td { border: 1px solid green; }
th { border: 1px solid purple; }
.view-small table { display: block; width: 100%; }
.view-small tbody { display: block; }
.view-small tr { display: block; width: 100%; margin: 2em auto; position; relative; }
.view-small th { display: block; width: 100%; position: absolute; left: 50%; transform: translateX(-50%); }
.view-small td { display: inline-block; height: 1em; width: 30%; transform: translateY(1.5em); }
</style>
</head>
<body class="">
<h1>Table Example</h1>
<table>
<tr>
<th>Numbers</th>
<td>One</td>
<td>Two</td>
<td>Three</td>
</tr>
<tr>
<th>Countries</th>
<td>Canada</td>
<td>Mexico</td>
<td>Guatemala</td>
</tr>
<tr>
<th>Planets</th>
<td>Mars</td>
<td>Jupiter</td>
<td>Saturn</td>
</tr>
</table>
<p>End of test</p>
</body>
</html>
We were thinking that for smaller devices, it would be neat if we could save horizontal space by display each row header over its corresponding data cells. If I set class="view-small" in the body tag in the code above, I get this in Chrome on Windows and pretty much the same thing in Firefox and IE11:
This demonstrates what I'm going for. What I'd really like to achieve includes having the data cells take up the horizontal space that the full row would have occupied. In the above code, I have their width set artificially to 30%, but that isn't ideal!
I'm going to tinker with this some more, but I thought I'd see whether anyone else has tried anything like this or seen a solution somewhere!

Try to change the width and margin values. The total value of width (including both horizontal margins) should be around 33%. These '3' after dot make it more precise.
div{
width: 30.3333333333%;
margin: 0 1.5%;
display: inline-block;
border: 1px solid black;
height: 20px;
box-sizing: border-box;
float: left;
}
<div></div>
<div></div>
<div></div>

Related

Table cell break word won't shrink

I often use this HTML/CSS structure to create a mobile-friendly table (It changes layout on narrow (mobile) screens; something very lacking in CSS frameworks) and it has been quite reliable for me. In my main project I have several tables with lots of data and varying widths.
If you open this codepen and change the view to 'debug' you can shrink the page width. Past 500px the table layout will change. The thead is hidden, secondary labels are shown and the tds are set to display: flex. (I like to use the responsive device toolbar in the inspector).
Under the table is a more simple set of divs, that behaves the way I want the divs inside the TD to work, but for some reason, the second div inside the td stops shrinking at a certain point. I have tried different combinations of word-wrap and white space but so far no luck. Seems the difference has to do with these divs being inside a table...
Is this just a limitation of tables or is there a way I can make the right div shrink like the second example?
Thanks!
https://codepen.io/sinrise/pen/qoypYJ
<table cellpadding="0" cellspacing="0">
<thead>
<tr>
<th>number</th>
<th>content</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div class="td-label">number</div>
<div>this is the first one</div>
</td>
<td>
<div class="td-label">number</div>
<div>this is the second one</div>
</td>
</tr>
</tbody>
</table>
<div class="cont">
<div class="in1">oneoneone oneone one oneoneoneoneoneon</div>
<div class="in2">two two twotwotwo twotwotwotwo</div>
</div>
table { width: 100%; table-layout: fixed; margin: 0 0 10px; }
th { padding: 10px 10px 0; text-align: left; }
td { padding: 10px; border: 1px solid #ccc; }
.td-label {
display: none;
min-width: 100px;
max-width: 100px;
font-weight: bold;
}
#media(max-width: 500px) {
thead { display: none; }
td {
display: flex;
margin: 0 0 10px;
> div:not(.td-label) {
word-wrap: break-word;
min-width: 1px;
}
}
.td-label {
display: table;
}
}
.cont {
display: flex;
border: 1px solid black;
> div {
&:first-of-type {
min-width: 100px;
max-width: 50px;
}
min-width: 1px;
border: 1px solid #aaa;
word-wrap: break-word;
}
}
The trick is to set the table width to 100%, add a min-width to the second div, and set display: table on the second div. I updated the pen and code above to reflect.

fixed header table deform when resizing window

this fixed-header table deforms column when resizing window horizontally. Is there way to stop that?
<!DOCTYPE html>
<html>
<head>
<style>
table {
width: 100%;
table-layout: fixed;
border-collapse: collapse;
}
table th {
border-left: 1px solid blue;
}
table th,
table td {
padding: 5px;
text-align: left;
border-left:1px solid blue;
}
table th, table td {
width: 150px;
}
table thead tr {
display: block;
position: relative;
}
table tbody {
display: block;
overflow: auto;
width: 100%;
height: 300px;
}
</style>
</head>
<body>
<table>
<thead>
<tr>
<th>id</th>
<th>pick_up_location</th>
<th>destination</th>
<th>instruction</th>
<th>created_at</th>
<th>status</th>
</tr>
</thead>
<tbody>
<tr>
<td>12322</td>
<td>Whanga Road</td>
<td>Crescent Street</td>
<td>Call when arrive</td>
<td>123442342331</td>
<td>comming</td>
</tr>
</tbody>
</table>
</body>
</html>
Keep in mind this fixed-header table. Mean when you have 100 rows. you can scroll the row but the header position is fixed. The display block attributes can not be removed.
UPDATE:
With Mark answer, the table looks fine but still deform at small screen. A screenshot of it
To don't have problems with resizing you have to work in height and width with %.
Like : width: 30%;
height: 40%;
Hope help you.
Do not apply an explicit width or height to tag. Instead, give it:
max-width:100%;
max-height:100%;
just modify the last two ccs declarations as follows:
table{
display: block;
position: relative;
}
table tbody {
position : relative;
overflow: auto;
width: 100%;
height: 300px;
}
Adding word-break: break-all; to all the cells makes your code work (almost, since all characters are not of the same width)
See https://jsfiddle.net/3wn1zzfn/
Your problem is that when it is not possible to fit all cells in a table, the width: 150px; is overridden, and widths are now based on length of the line.
The problem here is that you are applying display: block, you shouldn't use it on tables. Also remove px values on tables. use %, or remove it at all
Remove these lines of code:
table th,
table td {
/*width: 150px*/
}
table thead tr {
/*display: block;
position: relative;*/
}
table tbody {
/*display: block;*/
overflow: auto;
width: 100%;
height: 300px;
}
Here a codepen to show it:
http://codepen.io/sandrina-p/pen/qNYork?editors=1100
--EDIT--
before -1 please can you tell me what's wrong with my solution, to improve it?

HTML shrink td to fit image size

I am laying out a website with a table, and the logo goes in the top row of the table. The logo is a mostly transparent image with a green background, and it is in a table with a red background. However, the table cell is not shrinking to fit the image vertically and so it is showing some of the background red below the image when I don't want it to. I have tried setting the margin and padding all to 0, setting cell-spacing and cell-padding to 0, and removing borders, but none of it has worked.
My browser's page inspector tool shows that the td element is responsible for extending the height of the cell, not the tr or table
What am I missing? I feel like it is something really simple.
HTML:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="styles2.css" />
</head>
<body>
<div id="wrapper">
<table id="layoutTable" >
<tr>
<td class="layoutTabletd">
<img id="logoImage" src="res/logobar2.png"/>
</td>
</tr>
</table>
</div>
</body>
</html>
CSS:
#wrapper
{
width: 1000px;
margin-left: auto;
margin-right: auto;
}
#layoutTable
{
background-color: #FF0000;
margin: 0px;
padding: 0px;
border-collapse: collapse;
}
#layoutTable tr td.layoutTabletd
{
border: 1px solid black;
padding: 0px;
margin: 0px;
}
#logoImage
{
background-color: #00FF00;
margin-left: auto;
margin-right: auto;
margin-top: 0px;
margin-bottom: 0px;
padding: 0px;
}
Result:
Solved: http://jsfiddle.net/r0801v5v/
#layoutTable
{
line-height:0;
background-color: #FF0000;
margin: 0px;
padding: 0px;
border-collapse: collapse;
}
Notice the added line-height:0; - I am not exactly sure why this happens but I've seen it before. Hope I helped.

width or height of child element doesn't change in CSS

Here is my DOM:
<html>
<body>
<table>
<tr>
<td>
hello
</td>
</tr>
</table>
</body>
</html>
and my CSS:
html, body {
height: 100%;
width: 100%;
}
table {
height: 100%;
width: 100%;
}
td {
border: 1px solid gray;
height: 10%;
width: 10;
}
What I want to do is to re-size the height and width of the TD element using percentage. But this code doesn't work. I understand that the size of a child element will inherit the size of it's parent element. So TD will inherit the size from TABLE and then TABLE from BODY or HTML parent elements. My code doesn't do that. But if I do width: 10%; on TABLE, then it gets 10% of the width of the BODY/HTML element. Same as with the height: 10%. But why doesn't it work on TD tag?
td tags are forced to take up all of the remaining space in their parent.
So, your width: 10%; is completely ignored by the layout.
See this non-working JSFiddle Demo.
But, if we add some display: inline-block; to the td, then it fixes the problem.
See this (now) working JSFiddle Demo.
I suggest you add another td tag, and give it a width of 90%
<table>
<tr class="tr1">
<td class=td1>
hello
</td>
<td class="td2"></td>
</tr>
<tr class="tr2">
<td></td>
</tr>
</table>
CSS:
html, body {
height: 100%;
width: 100%;
margin:0;
}
table {
height: 100%;
width: 100%;
}
td.td1 {
border: 1px solid gray;
height: 10%;
width: 10%;
}
td.td2{
border: 1px solid gray;
width: 90%;
}
tr.tr1{
height:10%;
}
tr.tr2{
height:90%;
}
For the height, you will need to add another tr row, and give it a 90%. Give the first row a 10% height like you wanted to do with the td - http://jsfiddle.net/R5uRW/6/

css - stretched and evenly spaced horizontal menu

I hope, you can help me, I have a horizontal menu, my problem is the following:
The first is normal stretch with table, the second is what I want: stretch + even gaps between texts.
I achieved this with additional non breaking spaces, but it works only by fixed menu widths, so if I change the menu width I have to change the count of the nbsp characters. Is there any way to do this with css, and without those non breaking spaces?
The count of the menupoints and the menu width can change, so I need an automatical solution without javascript. No settings by individual columns, unless you can give me an algorithm which I can run on server side.
I don't think this is possible with css only, but I'm not a css guru, that's why I asked....
<style>
* {
margin: 0px;
padding: 0px;
font-size: 16px;
}
table {
width: 400px;
}
td {
border: 1px solid blue;
text-align: center;
}
</style>
<table>
<tr>
<td>aa</td>
<td>aaaaaaaaaaaaa</td>
<td>aaaaaaaaa</td>
</tr>
</table>
<table>
<tr>
<td> aa </td>
<td> aaaaaaaaaaaaa </td>
<td> aaaaaaaaa </td>
</tr>
</table>
Not sure of all the parameters here ("stretch" is not very clear), but wouldn't some left and right padding on the links do it? Because this is a menu, I won't use a table but a <ul> instead. There are plenty of variations on this if it's not what you want:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<style media="all">
ul, li {margin: 0; padding: 0;}
ul {list-style: none; display: table; border-spacing: 5px; }
li {display: table-cell; background: #f7f7f7; border: 1px solid blue; }
li a {padding: 0 30px;}
</style>
</head>
<body>
<ul>
<li>aa</li>
<li>aaaaaaaaaaaaa</li>
<li>aaaaaaaaa</li>
</ul>
</body>
</html>
Edit: The below answer does not work well with Internet Explorer versions as recent as IE 11. Its algorithm for cell sizing appears to work differently than other browsers.
While this will require some cross-browser testing, here's what I've been using:
http://jsfiddle.net/aaronadams/j3cEQ/
HTML:
<p>Default spacing:</p>
<ul>
<li>aa</li>
<li>aaaa aaaa aaaa</li>
<li>aaa aaa aaa</li>
<li>aa aa</li>
</ul>
<p>Even spacing:</p>
<ul class="even">
<li>aa</li>
<li>aaaa aaaa aaaa</li>
<li>aaa aaa aaa</li>
<li>aa aa</li>
</ul>
CSS:
ul {
display: table;
margin: 0 auto;
padding: 0;
width: 100%;
max-width: 30em;
text-align: center;
}
li {
display: table-cell;
margin: 0;
padding: 0 0.125em;
white-space: nowrap;
}
.even li {
width: 1%;
}
So far, this is providing me with a menu that works really well across all screen sizes; on mobile it shrinks to screen width, on desktop it grows up to a certain size, and the links are always evenly spaced.
Credit here for the inspiration: https://stackoverflow.com/a/16509901/802414
You can set the width for the individual columns.
JSFiddle
HTML
<table>
<tr>
<td class="first">aa</td>
<td class="second">aaaaaaaaaaaaa</td>
<td class="third">aaaa aaaaaaaaaaaaa</td>
</tr>
</table>
CSS
table {
width: 400px;
}
td {
border: 1px solid #d3d3d3;
text-align: center;
}
.first {
width: 30%;
}
.second {
width: 45%;
}
.third {
width: 30%;
}
JSFIDDLE
You can set the "padding left and right for individual column
HTML
<table>
<tr>
<td class="first">aa</td>
<td class="second">aaaaaaaaaaaaa</td>
<td class="third">aaaa aaaaaaaaaaaaa</td>
</tr>
</table>
CSS
table { width: 400px; }
td { border: 1px solid #d3d3d3; text-align: center;}
.first { padding: 0 3em; }
.second { padding: 0 2em; }
.third { padding: 0 4em; }
This can be achieved with CSS by making the parent element text-align: justify, and the child elements display:inline-block; However, justified text only works properly when there's at least 2 lines. The pseudo :after element is used to force an extra (very tiny) line:
#container {
height: 125px;
text-align: justify;
border: 10px solid black;
font-size: 0.1px; /* IE 9/10 don't like font-size: 0; */
min-width: 600px;
}
#container div {
width: 150px;
height: 125px;
display: inline-block;
background: red;
}
#container:after {
content: '';
width: 100%; /* Ensures there are at least 2 lines of text, so justification works */
display: inline-block;
}
Credit to https://css-tricks.com/equidistant-objects-with-css/ for this technique.