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;
}
Related
I want the whole of a row in the thead to have a specified border but it is not working as expected when I am using border styling attribute. But it is working using outline attribute. Here is a code snippet:
table.table, table.table * {
border: none !important;
}
table.price-table thead tr {
border: 10px solid blue;
outline: thin solid red;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"/>
<table class="table price-table">
<thead>
<tr>
<th>Ticket Type</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<tr data-ticket-id=1>
<td class="category-ticket">Adult</td>
<td class="price-ticket">RM 20</td>
</tr>
<tr data-ticket-id=3>
<td class="category-ticket">Child</td>
<td class="price-ticket">RM 15</td>
</tr>
</tr>
</tbody>
</table>
Using border: none !important; overrides your second border declaration. The use of !important is not recommended unless it is strictly necessary. It makes maintainability a lot harder. For more information see here.
Remove following css:
table.table, table.table * {
border: none !important;
}
The above css will effect to not display border. Because you have given table.table * So, it will target all the elements of the table. and you have given !important so, no other css will override the none css.
table.price-table thead tr {
border: 10px solid blue;
outline: thin solid red;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"/>
<table class="table price-table">
<thead>
<tr>
<th>Ticket Type</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<tr data-ticket-id=1>
<td class="category-ticket">Adult</td>
<td class="price-ticket">RM 20</td>
</tr>
<tr data-ticket-id=3>
<td class="category-ticket">Child</td>
<td class="price-ticket">RM 15</td>
</tr>
</tr>
</tbody>
</table>
Your this styling
table.table, table.table * {
border: none !important;
}
is over-riding all elements border styling to none beacuse of * you used. So if you want to apply please change this property to something you want.
And please avoid using !important unless it is too important and you want to over-write some library or framework default styling.
Try this as your css:
table.table, table.table * {
}
table.price-table thead tr {
border: 1px solid red;
outline: thin solid red;
}
check it working: https://jsfiddle.net/Aschab/6p6kht43/
As an advice, if you need !important for your css to work, you're doing it wrong. Think outside the box
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 have a simple example table with 3 rows and 5 columns styled with a border-collapse: collapse border.
The problem here is that I have a colspan=4 td in the second row, with IE11 (11.0.9600.17691) not showing the right border of that row.
You can see this example here: http://jsfiddle.net/j6u026oz/2/
I've tried putting an extra right border to the tr and th elements but it doesn't work.
Adding an extra th next to the colspan=4 element could solve this issue but I'd prefer to solve this problem with CSS if it's possible, as touching the HTML structure would imply a lot of changes in the project I'm working in.
Thank you!
You could add the extra column by CSS, using ::after pseudo-element:
Updated example
table {
border-collapse: collapse;
border: 1px solid black;
}
tbody > tr:first-child:after {
content: "";
display: table-cell;
}
<table>
<thead>
<tr>
<th>A</th>
<th>B</th>
<th>C</th>
<th>D</th>
<th>E</th>
</tr>
</thead>
<tbody>
<tr>
<th colspan="4">colspan4</th>
</tr>
<tr>
<td>td1</td>
<td>td2</td>
<td>td3</td>
<td>td4</td>
<td>td5</td>
</tr>
</tbody>
</table>
remove
border-collapse: collapse;
from your css file.
use the code as below
table{
border: 1px solid black;
}
Use "outline" instead of "border".
table{
border-collapse: collapse;
border: 1px solid black;
outline: 1px solid red; /* ---- this lil' guy ---- */
}
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.
I want the headings of the table to have a red solid border and the rest of the table a dotted black border.
Using the code below, all is correct but the left and right side of the TH being black dotted. Is there any way to override the <table> borders within a TH style declaration?
This is what I want to achieve:
<style type="text/css">
table {
border-style:none dotted dotted dotted;
border-collapse: collapse;
}
table th {
border: 2px solid red;
}
</style>
<table >
<thead>
<tr>
<th>title 1</th>
<th>title 2</th>
<th>title 3</th>
</tr>
</thead>
<tbody>
<tr>
<td>text</td>
<td>text</td>
<td>text</td>
</tr>
<tr>
<td>text</td>
<td>text</td>
<td>text</td>
</tr>
<tr>
<td>text</td>
<td>text</td>
<td>text</td>
</tr>
</tbody>
</table>
A simple solution is to set the th border width equal to or larger than the table border width, if this is acceptable. For example, add
table { border-width: 2px; }
to make them equal. In your example, the width is the initial value, medium, which normally maps to 3px or 4px in browsers.
Otherwise, a different strategy is needed (see Zolthan Toth’s answer), a strategy where no left or right border is set on the table element.
The reason is that according to the [border conflict resolution][1] rules, the wider border wins (and for equal-width borders, solid beats dotted).
Try this - http://jsfiddle.net/eaTLp/
table {
border-style:none none dotted;
border-collapse: collapse;
}
table th {
border: 2px solid red;
}
table td:first-child {
border-left: dotted;
}
table td:last-child {
border-right: dotted;
}
You're giving the dotted border only to the bottom of the table. On the left and right you're selecting the first and last <td> in every row by :first-child and :last-child and assign them the left and right border respectively.