I have a table of data, with some columns more important than the others and need a way to visually distinguish them.
<table>
<thead>
<tr>
<th>A header</th>
<th class="important" colspan="2">An important header!</th>
<th class="important" >Also important</th>
<th>Boring header</th>
</tr>
<tr>
<th>Sub header</th>
<th>Part 1</th>
<th>Part 2</th>
<th>Sub header</th>
<th>Sub header</th>
</tr>
</thead>
<tbody>
<!-- lots of data here -->
</tbody>
</table>
What I want to do is make them some of the columns/headers a little taller than the rest, like this:
I've tried setting the height of the <th> cell, but that doesn't work properly. There are some elements inside the headers and trying to create a :before pseudo element, and then fixing its height isn't seeming to work.
I even tried adding <col> definitions, but they seemed to have trouble with the colspan cell I hate, but I could have been doing it wrong.
<table>
<col> <!-- I can style this maybe? -->
<thead>
In the first instance I'd prefer a CSS solution, and can easily add classes or ids as needed. I'd rather not add additional markup, but will relent if required. Using Javascript to extra inject elements is not an option!
Any ideas on how to create a table header cell that is taller than the rest of the cells using CSS?
The table sizing algorithm will force all the table cells in a row to take on the same height, no way around that.
One way of doing it requires extra markup. Wrap your content in a wrapper and take it out of the normal content flow using absolute positioning. You will need to adjust any border properties on the table cells and add them to the child wrapper blocks.
Finally, you need to a top margin/padding to the table to provide room for the extra tall headers.
At least it is a proof of concept, perhaps a place to start.
table {
margin-top: 75px;
}
th {
border: 1px dotted gray;
position: relative;
}
.important div {
height: 75px;
position: absolute;
width: inherit;
bottom: 0;
border: 1px dotted gray;
}
<table>
<thead>
<tr>
<th>A header</th>
<th class="important" colspan="2"><div>An important header!</div></th>
<th class="important" >Also important</th>
<th>Boring header</th>
</tr>
<tr>
<th>Sub header</th>
<th>Part 1</th>
<th>Part 2</th>
<th>Sub header</th>
<th>Sub header</th>
</tr>
</thead>
<tbody>
<!-- lots of data here -->
</tbody>
</table>
The idea is to remove the top-left and top-right cell borders and create them by using pseudo elements. Markups remain the same, even class="important" won't be needed.
http://jsfiddle.net/of79mcoj/
table {
border-collapse: collapse;
}
th {
border: 1px solid black;
padding: 30px 20px;
}
tr:first-child th:first-of-type,
tr:first-child th:last-of-type {
position: relative;
border-top: 0;
padding-top: 60px;
}
tr:first-child th:first-of-type {
border-left: 0;
}
tr:first-child th:last-of-type {
border-right: 0;
}
tr:first-child th:first-of-type::before,
tr:first-child th:last-of-type::before {
content: "";
display: block;
position: absolute;
border: 1px solid black;
border-bottom: 0;
left: 0;
bottom: 0;
width: 100%;
height: 70%;
}
tr:first-child th:first-of-type::before {
border-right: 0;
}
tr:first-child th:last-of-type::before {
border-left: 0;
}
Well, I can only think of absolute positioning a pseudo element, and set line-height to 0 to achieve what you want, won't work on IE 7 though
have a look here Fiddle (haven't tested on IE 8)
th.important {
border-top: 0;
vertical-align: top;
line-height: 0;
}
th.important:before {
height: 30px;
content: "";
display: block;
position: absolute;
top:-30px;
left:-1px;
right: -1px;
border: 1px solid #000;
border-bottom: 0;
}
Notice: I have to apply some margin on the table so that the absolute pseudo elements are in view.
Related
I am trying to achieve this table look
How can I make the first heading to fill the entire width? Something like flex: 1 would do. Also, how can I add border to only elements in the table like on the picture, instead of entire table?
.center {
text-align: center;
}
table {
border: 1px solid black;
}
<table style="width:100%">
<tr>
<th style="text-align:left">Month</th>
<th style="text-align:center">Savings</th>
<th style="text-align:center">Savings</th>
<th style="text-align:center">Savings</th>
<th style="text-align:center">Savings</th>
</tr>
<tr>
<td>January</td>
<td class="center">$100</td>
</tr>
<tr>
<td>February</td>
<td class="center">$80</td>
</tr>
</table>
I need this to look like
Image
You can do like below:
.center {
text-align: center;
}
td,
th {
padding: 3px 5px; /* control the spacing */
}
table {
border-collapse: collapse; /* this is mandatory to correctly use border */
border-bottom: 1px solid black; /* only border bottom here */
}
th:first-child {
width: 100%; /* take as much space as possible */
}
tr:nth-child(2) {
border-top: 1px solid black; /* border top to second tr */
}
tr:not(:first-child) {
/* right and left to all except the first one */
border-left: 1px solid black;
border-right: 1px solid black;
}
<table style="width:100%">
<tr>
<th style="text-align:left">Month</th>
<th style="text-align:center">Savings</th>
<th style="text-align:center">Savings</th>
<th style="text-align:center">Savings</th>
<th style="text-align:center">Savings</th>
</tr>
<tr>
<td>January</td>
<td class="center">$100</td>
</tr>
<tr>
<td>February</td>
<td class="center">$80</td>
</tr>
</table>
For styling the first raw(table header) there are many solutions fastest one by selecting table first raw
table tr:first-child{
border: 1px solid black;
}
I recommend you to read this article first: A Complete Guide to the Table Element
**** UPDATED ****
I found out if I just leave off the last width then it auto fills to the end of the table... why? No idea, but I guess its just how it works?
Here is my fiddle:
JSFIDDLE
<div>
<table>
<colgroup>
<col>
<col>
<col>
</colgroup>
<thead>
<tr>
<th>Test1</th>
<th>Test2</th>
<th>Test3</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>Yes</td>
<td>No</td>
<td>Maybe</td>
</tr>
</tbody>
</table>
</div>
CSS
div {
width: 300px;
outline: 3px solid red;
}
tr {
border: 1px solid gray;
}
th, td { outline: 1px solid red;}
table {
border: 1px solid gray;
width: 100%;
border-collapse: collapse;
table-layout: fixed;
box-sizing: border-box;
}
th, td {
padding: 5px;
}
col:first-child { width: 35px; }
col:nth-child(2) { width: 35%; }
col:last-child { width: calc(65% - 35px); }
There is a difference in safari vs chrome. I think in Safari it doesn't calculate the last one because I even changed it to 25% - 35 and it still filled the width. More than anything I just want to see where the differences are documented. Or if someone wants to explain how they treat them so I don't make this mistake again (btw, the original code works great in chrome... but noticed today in safari the last column was completely collapsed which is what got me investigating)
I have the following problem: When I translate the header cells from a table and the table is set to border-collapse:collapse then the cells will be moved but not their borders. I created a test:
Markup:
<table>
<thead>
<th>Test 1</th>
<th>Test 2</th>
<th>Test 3</th>
</thead>
<tbody>
<tr>
<td>asdasd</td>
<td>adasdasd</td>
<td>adasdasd</td>
</tr>
</tbody>
</table>
Style:
table{
border-spacing: 0;
border-collapse: collapse;
background: #efefef;
}
th {
background:#ccc;
border-right: 1px #000 solid;
transform: translate(-10px, 0);
}
http://jsfiddle.net/rs0h9tbu/2
If I change border-collapse to separat everything works fine.
Is it a bug, or can anybody explain that behaviour?
This is the behaviour of the collapsing border model. When border-collapse is set to collapse, then the cells share the border with that of the edge element which is the table. If it is set to separate, then the cells have their own border.
From this ref: https://developer.mozilla.org/en/docs/Web/CSS/border-collapse
The border-collapse CSS property determines whether a table's borders
are separated or collapsed. In the separated model, adjacent cells
each have their own distinct borders. In the collapsed model, adjacent
table cells share borders.
And from this spec: http://www.w3.org/TR/CSS2/tables.html#border-conflict-resolution
In the collapsing border model, borders at every edge of every cell
may be specified by border properties on a variety of elements that
meet at that edge (cells, rows, row groups, columns, column groups,
and the table itself)
This is why when you translate the cells, only the cells move because they are not having their own borders and only sharing the borders of the edge-element (i.e. table).
If you really really need to transform and move the th cells, then keep the border-collapse as separate and control the borders on td/th individually.
Something like this:
table {
border-spacing: 0px;
border: 1px solid #333;
background: #efefef;
border-collapse: separate;
}
th,td { border: 1px solid #333; }
td { border-right: 0px; }
td:first-child { border-left: 0px; }
tbody > tr:last-child > td { border-bottom: 0px; }
th { background: #ccc; transform: translate(50px, 50px); }
<table>
<thead>
<tr>
<th>Test 1</th>
<th>Test 2</th>
<th>Test 3</th>
</tr>
</thead>
<tbody>
<tr>
<td>asdasd</td>
<td>adasdasd</td>
<td>adasdasd</td>
</tr>
</tbody>
</table>
I can use the CSS property border-collapse to combine the borders of adjacent table cells. And I can use empty-cells to hide table cells that have no content. But when I use both, the empty-cells property has no effect and empty cells are always visible. At least there's a border around each of them, even where multiple adjacent rows and columns are empty.
Here's an example:
<!doctype html>
<html>
<head>
<style>
table
{
border-collapse: collapse;
border-spacing: 0;
}
th,
td
{
empty-cells: hide;
border: solid 1px black;
padding: 2px 4px;
}
</style>
</head>
<body>
<table>
<tr>
<th></th>
<th></th>
<th>Header 3</th>
</tr>
<tr>
<th></th>
<th></th>
<th>Header 3</th>
</tr>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
<td></td>
</tr>
<tr>
<td>Cell 1</td>
<td>Cell 2</td>
<td></td>
</tr>
</table>
</body>
</html>
As #Bolt explained why this happens, I will provide a solution for this, you can use the below snippet in your CSS to hide the empty cells
th:empty, td:empty {
border: 0;
}
Demo
Using :empty pseudo, I set the border: 0; so physically the element is present on the page, we just target the styles of the empty cells and set the borders to 0.
I didn't used display: none; as it will spoil your table layout, so using the above snippet is enough if you want to keep the border collapsed.
Note: The selector am using is a general selector and will target globally, if you want to target the element specifically, consider using a class instead like
.table_class_name th:empty,
.table_class_name td:empty {
/* Styles goes here */
}
This is a trick that I found, you can use border-collapse as separate. then you define border-spacing to 0px into your table then define the padding in your td to 0px.
table
{
empty-cells: hide;
border-collapse: separate;
border-spacing: 0px;
}
td
{
border: thin solid black;
text-align: right;
padding: 0px;
}
th
{
border: thin solid black;
background-color: yellow;
}
I want to highlight the borders of cells having the class active.
The problem is the table's border-collapse property is set to collapse, which will hide the top and left border of cells(except for left most and top row cells). This is causing an issue whereby the highlight class(active) is not highlighting the top and left borders.
You can find the problem here.
HTML
<div style="padding: 10px">
<table>
<tr>
<td>1.1</td>
<td>1.2</td>
<td>1.3</td>
<td>1.4</td>
<td>1.5</td>
</tr>
<tr>
<td>2.1</td>
<td>2.2</td>
<td class="active">2.3</td>
<td>2.4</td>
<td>2.5</td>
</tr>
<tr>
<td>3.1</td>
<td>3.2</td>
<td>3.3</td>
<td>3.4</td>
<td>3.5</td>
</tr>
<tr>
<td>4.1</td>
<td>4.2</td>
<td>4.3</td>
<td>4.4</td>
<td>4.5</td>
</tr>
<tr>
<td>5.1</td>
<td>5.2</td>
<td>5.3</td>
<td>5.4</td>
<td>5.5</td>
</tr>
</table>
</div>
CSS
table {
table-layout: fixed;
border-spacing: 0;
border-collapse: collapse;
}
td {
border: 1px solid lightgrey;
height: 60px;
width: 60px;
text-align: center;
vertical-align: middle;
}
td.active {
border: 1px solid blue;
}
td.brdr-b-hide {
border-bottom: none;
}
td.brdr-r-hide {
border-right: none;
}
Javascript
$('table').on('click', 'td', function(e){
var target = $(e.currentTarget);
if(e.ctrlKey && target.hasClass('active')){
target.removeClass('active');
} else if(e.ctrlKey) {
target.addClass('active');
} else {
$('table td.active').removeClass('active');
target.addClass('active');
}
});
One of the solutions I'm working on is to hide the border-right of the cell in the left of the active cell and the border-bottom of the cell at the top.
I'm not so happy with the solution since the active class is applied and removed when a cell is clicked. Here my solution need to find the prev cell and the top cell and apply/remove the corresponding classes to/from them.
You can find the proposed solution here.
My question is, is there a better way to handle this problem?
Define border-style:double. Write like this:
td.active {
border: 1px solid blue;
border-style:double;
}
Check this http://jsfiddle.net/2ahfP/18/
Try this instead:
td.active {
outline: 1px solid blue;
}
The difference between outline and border is that outline won't add to the elements total width or height. Also the border-collapse property won't affect the outline.