This one is driving me mad, unfortunately I'm not very good in CSS yet.
How can I get a horizontally and vertically centered text-link into a table cell which is fully clickable?
I researched, tried several solutions, none of them worked. Here is my best approach so far:
HTML
<table class="dataTable">
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>
I wanne be centered!
</td>
<td>
Me too!
</td>
</tr>
</tbody>
</table>
CSS
.dataTable td a {
width: 100%;
height: 100%;
text-align: center;
vertical-align: middle;
display:block;
text-decoration: none;
}
.dataTable td {
display:inline-block;
}
This one gives me centered text, but the link only covers the width of the cell, not the height. If I change the css for the link to display:inline-block, then the full cell is clickable, but the text is not vertically centered anymore.
I need both. Help!
i think you should remove this :
.dataTable td {
display:inline-block;
}
see this fiddle
I think that's what you want:
.dataTable {
text-align: center;
}
.dataTable a {
display: inline-block;
width: 100%;
height: 100%;
}
/* Just for better visualization */
.dataTable td {
background: red;
}
<table class="dataTable">
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>
I wanne be centered!
</td>
<td>
Me too!
</td>
</tr>
</tbody>
</table>
If you want to increase td's height, you should do it by modifying a's height. Otherwise, the link will not occupy the whole cell's height. You can achieve that with height property or also with line-height.
.dataTable {
text-align: center;
}
.dataTable a {
display: inline-block;
width: 100%;
height: 100%;
line-height: 5; /* To get a 5 text lines high cell */
}
.dataTable td {
/* Just for better visualization */
background: red;
}
<table class="dataTable">
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>
I wanne be centered!
</td>
<td>
Me too!
</td>
</tr>
</tbody>
</table>
Wrap your text in a
div style="padding-top:5px;".
That will center it approximately.
Related
I have a problem that I do not understand regarding scaling of child elements inside html tables.
To start from the beginning, my goal is to have a table and to overlay the table body with a div using z-index. With the proper color this then looks like the table is inactive and it can not be clicked.
Below you find a minimal example of how this looks like due to some other requirement. As you can see, the overlay div always scales to the full table and not only a part of it. No matter if it is a child of tbody nor of one cell (as it is right now in the example code - I thought maybe a div is not allowed as a direct child of tbody but instead I could put one overlay div in each table cell).
table {
border: 1;
border-color: blue;
}
#content {
position: relative;
}
#content * {
position: inherit;
}
#overlay {
top: 0;
left: 0;
/*bottom: 0;
right: 0;*/
position: absolute !important;
background: rgba(0, 0, 0, .4);
z-index: 3;
width: 100%;
height: 100%
}
<div id="content">
<div>
Some stuff before
</div>
<br>
<table>
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div>
Cell
</div>
<div id="overlay"></div>
</td>
<td>Cell</td>
</tr>
<tr>
<td>Cell</td>
<td>Cell</td>
</tr>
<tr>
<td>Cell</td>
<td>Cell</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>Footer 1</td>
<td>Footer 2</td>
</tr>
</tfoot>
</table>
<br>
<div>
Some stuff after
</div>
</div>
I do not understand why this happens which makes it hard for me to think of a fix and I hope somebody can help me with that and provide an explanation.
Cheers
Your table cells also need to be set to position: relative. Instead of #content * directly set them using td or at least #content td.
td {
position: relative;
}
#overlay {
top: 0;
left: 0;
position: absolute;
background: rgba(0, 0, 0, .4);
z-index: 3;
width: 100%;
height: 100%
}
<div id="content">
<table>
<thead>
<tr>
<th>Header 1</th>
<th>Header 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div>
Cell
</div>
<div id="overlay"></div>
</td>
<td>Cell</td>
</tr>
<tr>
<td>Cell</td>
<td>Cell</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>Footer 1</td>
<td>Footer 2</td>
</tr>
</tfoot>
</table>
</div>
So why does this work?
Short answer: position is not inheritable and Chrome has some problems with table tags.
But that's only half the truth. All major browsers (Tested with Chrome, Firefox and IE11) allow most (or probably even all) properties to inherit from their parent. When you test your snippet in Firefox or IE11 you will see that it indeed works. So why not in Chrome then?
It turns out that Chrome has some issues with the table-* display modes and the table-tags themselves. It always uses the default position value (which is static) when being inherited. Even if the closest parent has position: relative set, it won't work as illustrated in the next code snippet.
So to conclude: It's best to always explicitly set position: relative and in most cases avoid using inherit all together.
main {
position: relative;
border: 2px solid #000;
width: 200px;
margin-bottom: 20px;
}
table, .fake-table {
min-height: 50px;
margin: 10px;
}
table, tr, td, .fake-table div {
position: inherit;
}
.relative {
position: relative;
}
em {
position: absolute;
left: 0;
top: 0;
width: 100%;
min-width: 100px;
height: 100%;
background: rgba(166, 199, 252, .9);
text-shadow: 0 0 10px #fff;
}
.fake-table .table {
display: block;
}
.fake-table .row {
display: flex;
justify-content: flex-start;
}
.fake-table .cell {
display: inline-block;
min-width: 40px;
}
<main>
<table>
<tr>
<td>...</td>
<td>
cell
<em>Starting point (inherited table)</em>
</td>
</tr>
</table>
</main>
<main>
<table>
<tr class="relative">
<td>...</td>
<td>
cell
<em>Parent is set to relative</em>
</td>
</tr>
</table>
</main>
<main class="fake-table">
<table class="table">
<tr class="row">
<td class="cell">...</td>
<td class="cell">
cell
<em>Table tags in different display mode</em>
</td>
</tr>
</table>
</main>
<main class="fake-table">
<div class="table">
<div class="row">
<div class="cell">...</div>
<div class="cell">
cell
<em>Table using flex (behaves correctly)</em>
</div>
</div>
</div>
</main>
<main>
<table>
<tr>
<td>...</td>
<td class="relative">
cell
<em>Expected rendering</em>
</td>
</tr>
</table>
</main>
I have a simple HTML table as below.
This is a responsive table and shrinks down when the browser is shrunk.
I want to set the minimum width of the column to be as wide as the header text.
What is the best way to do this in CSS?
<table>
<thead class="ui-datatable-thead">
<tr class="ui-state-default">
<th class="ui-state-default">COL HEADER</th>
</tr>
</thead>
<tbody class="ui-datatable-data ui-widget-content">
<tr class="ui-widget-content ui-datatable-odd">
<td>DATA</td>
</tr>
</tbody>
</table>
I have looked at some other answers but haven't found a solution yet.
table {
display: table;
width: 100%;
table-layout: fixed;
margin-bottom: 20px;
}
th,td {
display: table-cell;
border: 1px dotted red;
padding: 4px 6px;
width: 2%;
margin-bottom: 0;
}
<table>
<thead class="ui-datatable-thead">
<tr class="ui-state-default">
<th class="ui-state-default">COL HEADER 1</th>
<th class="ui-state-default">COL HEADER 2</th>
<th class="ui-state-default">COL HEADER 3</th>
</tr>
</thead>
<tbody class="ui-datatable-data ui-widget-content">
<tr class="ui-widget-content ui-datatable-odd">
<td>DATA 1</td>
<td>DATA 2</td>
<td>DATA 3</td>
</tr>
</tbody>
</table>
All you need to set the cell width th & td table-layout to 'fixed'.Just like i mentioned in css code. If total size of table is 500px and there are 5 columns then each column will have 100px.
table{
border: 1px solid black;
table-layout: fixed;
width: 500px;
}
th, td {
border: 1px solid black;
width: 100px;
}
You need to fix the size of the heading's TD. so body's TD will automatically take width as applied in heading's TD.
Suppose I have a table with 100vh height, how to set minimum height for thead according to inside and maximum tbody?
<table style="height: 100vh;">
<thead>...</thead>
<tbody>...</tbody>
</table>
Is this what you look for?
Updated
Did a few tests and noticed giving height to the body didn't work properly cross browser, which below update does (tested on Chrome, Firefox, Edge, IE11)
html, body {
margin: 0;
}
table {
width: 100%;
height: 100vh;
}
table thead tr {
height: 80px; /* on table elements, height works kind of like min-height */
background: yellow;
}
table tbody tr {
background: lime;
}
<table>
<thead>
<tr>
<td>
HEAD<br>
</td>
</tr>
</thead>
<tbody>
<tr>
<td>
BODY
</td>
</tr>
</tbody>
</table>
you can follow the hack to achieve your goal.
Use least height for thead, but not 0.Use 0% for tbody
html,body{
margin:0;
}
table{
width:100%;
height: 100vh;
border: 1px solid black;
}
thead{
background: red;
height:1px;
}
tbody{
background: blue;
height:0%;
}
<table>
<thead>
<tr>
<td colspan="4">
<img src="http://dummyimage.com/100x100/eb00eb/fff">
</td>
</tr>
</thead>
<tbody>
<tr>
<td>BODY</td>
<td>BODY</td>
<td>BODY</td>
<td>BODY</td>
</tr>
</tbody>
</table>
I have a situation similar to the one represented in this fiddle,
where there is a table with
table {
width: 100%;
margin-right: 30px;
}.
inside a div.
The problem is that when I apply the margin to the table, it goes out of its parent div. How can I avoid that?
Add a padding-right on the div instead :
div {
padding-right: 30px;
}
table {
width: 100%;
}
demo
The width applies to the actual content of the element, so you have a table with 100% wide content, and on left of that you add some margins pushing the width over 100%, thus the right side of the table extends beyond the parent's right edge. Probably you should go with padding on the parent instead of margin on the table, or an additional wrapper with just the margin.
table {
width: 100%;
border:1px solid green;
border-collapse: collapse;
}
.inner{
margin-left:100px;
}
<div>
<div class="inner">
<table border="1">
<thead>
<tr>
<th>HEADER 1</th>
<th>HEADER 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>11</td>
<td>12</td>
</tr>
<tr>
<td>21</td>
<td>22</td>
</tr>
</tbody>
</table>
</div>
</div>
Is it possible to have a table with width 100% (so the table fits the screen size), where the first and the last column have a fixed width, and the columns between take the rest, both 50%.
Like:
+--------------------+--------------------------------------+--------------------------------------+------------+
| width:300px; | with dynamic, equals next column | width dynamic, equals prevous column | width:50px;|
+--------------------+--------------------------------------+--------------------------------------+------------+
+--------------------+--------------------------------------+--------------------------------------+------------+
+--------------------+--------------------------------------+--------------------------------------+------------+
+--------------------+--------------------------------------+--------------------------------------+------------+
Try this:
As you can see the two centre column remain equal sized, due to the table-layout:fixed, even when the content is of different length. Try adding more and less content to the two centre columns.
JSFiddle: http://jsfiddle.net/RtXSh/
CSS
table {
width:100%;
border-collapse:collapse;
table-layout:fixed;
}
td {
border: 1px solid #333;
}
HTML
<table>
<tr>
<td style="width:300px;">
test
</td>
<td>
test test tes test test
</td>
<td>
test
</td>
<td style="width:50px;">
test
</td>
</tr>
</table>
Try using the pseudo element first-child and last-child
If I'm not mistaken the other columns will align equally by themselves. You might need to use the !important statement behind the first-child and last-child widths.
table{ table-layout: fixed; width: 100%; }
td { border: 1px solid black; }
td:first-child{ width: 100px; }
td:last-child{ width: 100px; }
<table>
<tr>
<td>100px</td>
<td>some text</td>
<td>some text</td>
<td>100px</td>
</tr>
</table>
However, as nurettin pointed out, if you use a thead and tbody section you have to style the header. Styling the td:first-child and td:last-child will not work.
table{ table-layout: fixed; width: 100%; }
td { border: 1px solid black; }
th:first-child{ width: 100px; }
th:last-child{ width: 100px; }
<table>
<thead>
<tr>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 3</th>
<th>Column 4</th>
</tr>
</thead>
<tbody>
<tr>
<td>100px</td>
<td>some text</td>
<td>some text</td>
<td>100px</td>
</tr>
</tbody>
</table>
In my opinion, the simple, nice and easy way is that don't use the px and % together. If you are using table width 100%, then define width of first and last column in % as well. If you are interested in that, here is how you can do:
CSS:
.mytable {
width:100%;
border: 1px solid green;
}
.left{
width:30%;
border-right:1px dashed blue;
}
.mid1{
width:30%;
border-right:1px dashed blue;
}
.mid2{
width:30%;
border-right:1px dashed blue;
}
.right{
width: 10%;
border-left:1px dashed blue;
}
HTML:
<table class="mytable">
<tr>
<td class="left">Left Column, 30%</td>
<td class="mid1">Mid 1, 30% </td>
<td class="mid2">Mid 2, 30% </td>
<td class="right">Right, 10%</td>
</tr>
</table>
This can be handled by adding the style table-layout:fixed to the table element, and simply not specifying any width value for the columns you wish to evenly divide the width remaining after the fixed columns have been accounted for.
Further, using combinations of <colgroup> can provide robust variable-width scenarios.
I've created an example at JSFiddle: https://jsfiddle.net/3bgsfnuL/1/
<div style="position:relative; height:500px; width:100%;">
<table style="height:100%; width:100%; table-layout:fixed; text-align:center; border-collapse:collapse;">
<colgroup colspan="1" style="width:200px"></colgroup>
<colgroup colspan="3">
<col/>
<col style="width:30px"/>
<col/>
</colgroup>
<colgroup colspan="1" style="width:200px"></colgroup>
<tbody>
<tr>
<td style="background-color:silver;">left fixed</td>
<td style="border-right:1px solid black;">col 1</td>
<td style="background-color:red; color:white; border:1px solid black;">col 2</td>
<td style="border-left:1px solid black;">col 3</td>
<td style="background-color:silver;">right fixed</td>
</tr>
</tbody>
</table>
</div>
Nobody mentioned this one here <th> trick:
table{ table-layout: fixed; width: 100%; }
th:first-child{ width: 300px; }
<table>
<thead>
<tr>
<th>yourfirst300pxcolumn</th>
<th>fixedwidth</th>
<th>fixedwidth also</th>
</tr>
</thead>
<tbody>
<tr><td>300</td><td>something</td><td>something else</td></tr>
</tbody>
</table>
Note that in HTML5/CSS3, you can use grid layout to have more control over your tables. It's not that useful for this specific example, with pixel widths, where you can use table-layout:fixed as in Bazzz's answer, but it is useful if you want to use something like min-content.
The following works out of the box on Chrome and Firefox, but not in Safari:
table {
width: 100%;
display: grid;
grid-template-columns: 300px 1fr 1fr 50px;
/* Or, more usefully: */
/* grid-template-columns: min-content 1fr 1fr min-content; */
}
td {
display: block;
}
/* ignore <tr> when laying out the grid; just lay out the cells */
tr {
display: contents;
}
/* browsers can inject <tbody> into the DOM even if it's not in the HTML */
tbody {
display: contents;
}
(Note though that the table border-collapse property doesn't work in this layout, so you may have to fiddle with CSS pseudo-classes like :last-child in order to get your borders to behave the way you want.)
In Safari this doesn't work -- the rows don't break properly. (Although it does work if you use nested <div> elements instead of a <table> and apply similar styles.) However, a simpler layout with just one dynamic 1fr column does work in Safari:
table {
display: grid;
grid-template-columns: 300px 1fr 50px;
}
tbody {
display: contents;
}
tr {
display: contents;
}
td {
border: 1px solid #c0c0c0;
}
What about using jQuery for this and calling javascript function once your table is created or some other event (like click) happens?
See here (I created jsfiddle playground for this)
What it does is that it checks the width of fixed elements (width of the whole table, first and last cell). Then it calculates and assigns the width for the rest of the cells which should have the remaining width divided between them (based on how many there are and how much space is left). Of course this is just quick example of possible solution. It needs polishing (checking null objects, if remaining width is greater than 0, ...)