Make table cells square - css

How to ensure that each cell of table should become square without using fixed sizes? And be responsive when they change width.
table {
width: 90%;
}
td {
width: 30%;
}
tr {
/** what should go here? **/
}
<table>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>4</td>
<td>5</td>
<td>6</td>
</tr>
<tr>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
<table>

You can use the technique described in: Grid of responsive squares.
Adapted to your usecase with a table and square table cells, it would look like this:
table {
width: 90%;
}
td {
width: 33.33%;
position: relative;
}
td:after {
content: '';
display: block;
margin-top: 100%;
}
td .content {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: gold;
}
<table>
<tr>
<td><div class="content">1</div></td>
<td><div class="content">1</div></td>
<td><div class="content">1</div></td>
</tr>
<tr>
<td><div class="content">1</div></td>
<td><div class="content">1</div></td>
<td><div class="content">1</div></td>
</tr>
<tr>
<td><div class="content">1</div></td>
<td><div class="content">1</div></td>
<td><div class="content">1</div></td>
</tr>
<table>
FIDDLE demo

Here is my code: http://jsfiddle.net/vRLBY/1/
The key is to use:
td { width: 33%; padding-bottom: 33%; height: 0; }
td div { position: absolute }
because padding-bottom is defined in terms of the width. More information: http://absolide.tumblr.com/post/7317210512/full-css-fluid-squares
Note: Previously I posted a not working code (see here). Thanks to #web-tiki for reporting the bug ;-)

If someone's looking for a solution that does not require fixed width property (even in percentage), here's what I came up with based on above answers and the link from approved answer:
td {
height: 0;
&:after, &:before {
content: '';
display: block;
padding-bottom: calc(50% - 0.5em);
}
}
It's kinda lame but it kills two birds with one stone:
does the trick
makes content aligned vertically

Related

How to make head of css table sticky

I have a css table, the first 2 columns are already sticky and everything works fine, but I want the table head to be sticky as well.I just cant make it work.
I have already tried using a class for every with: position: sticky, top: 0.
this code makes the first 2 columns sticky
table {
table-layout: fixed;
width: 100%;
}
.fixed{
position: sticky;
left: 0;
}
.fixed2 {
position: sticky;
left: 120px;
}
what I want is the thead to be sticky as well.
Any help would be greatly appreciated. Thanks!
css
thead th { position: sticky; top: 0; }
html
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>#mdo</td>
</tr>
</tbody>
</table>
Give table-fixed class to table tag and try this:
.table-fixed{
width: 100%;
tbody{
height:200px;
overflow-y:auto;
width: 100%;
}
thead,tbody,tr,td,th{
display:block;
}
tbody{
td{
float:left;
}
}
thead {
tr{
th{
float:left;
}
}
}
}

webkit-filter changing z-index stacking order

Why does applying a webkit filter changes the layers order?
See this minimal example:
setInterval(function(){
t.classList.toggle('grayed');
}, 1000)
.floater {
position: fixed;
top: 5vh;
left: 5vw;
width: 90vw;
height: 90vh;
z-index: 99;
background: yellow;
display: none;
}
td:hover .floater{
display: initial;
}
.grayed td{
-webkit-filter: grayscale(0.5);
}
td{
padding: 1em;
text-align: center;
background: blue;
}
<table id="t">
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>4</td>
<td>5<br>
(Mouse over this)
<div class="floater">HELLO</div>
</td>
<td>6</td>
</tr>
<tr>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
</table>
The order changes because when the effect is rendered it gets moved to a different stacking contexts (or "layer"). The solution I found was to place whatever should show in front after the element with this effect.
Hover over the buttons on the left and right corners.
http://aminhafamilia.com.br/layout-options/4.html
http://aminhafamilia.com.br/layout-options/4a.html
Page 4.html displays correctly and page 4a.html does not. the only difference is that the text that I want to show on top is actually after the header (which has the filter). Note that no z-index can fix it because they are not in the same stacking context. Moving it down changes the stacking context.
Child's z-index is set to the same stacking index as its parent, hence why it's not working.
If you are willing to take the floater out of it's table parent, you could try the below JS approach with mouseover & mouseout (to close).
setInterval(function() {
t.classList.toggle('grayed');
document.querySelector('.floater').classList.toggle('grayed');
}, 1000)
document.querySelector('.toHover').addEventListener('mouseover', function() {
document.querySelector('.floater').classList.add('open');
})
document.querySelector('.floater').addEventListener('mouseout', function() {
document.querySelector('.floater').classList.remove('open');
})
.floater {
position: fixed;
top: 5vh;
left: 5vw;
width: 90vw;
height: 90vh;
z-index: 1;
background: yellow;
display: none;
}
.grayed td {
-webkit-filter: grayscale(0.5);
}
.grayed {
-webkit-filter: grayscale(0.5);
}
.open {
display: initial;
}
td {
padding: 1em;
text-align: center;
background: blue;
}
<table id="t">
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>4</td>
<td class="toHover">5<br> (Mouse over this)
<div>HELLO</div>
</td>
<td>6</td>
</tr>
<tr>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
</table>
<div class="floater">HELLO</div>

Keep aspect ratio of table

I have a table representing coordinates.
How can I have the size dynamically changing, so it always fits the parent div (width: 100%), like an image would?
Right now I use #media queries, which are hardcoded.
But there must be a better way.
.hitbox {
width: 25%; /* of page */
}
#media (min-width: 702px) and (max-width: 800px) {
.hitbox .tablewrapper {
font-size: 9px;
}
}
#media (min-width: 800px) and (max-width: 840px) {
.hitbox .tablewrapper {
font-size: 10px;
}
}
#media (min-width: 840px) and (max-width: 915px) {
.hitbox .tablewrapper {
font-size: 11px;
}
}
edit:
The problem if the table needs to get even smaller then the text containing is fixed text size.
JSFiddle
This works fine.
But smaller then that, It doen't work.
It should make the font smaller, or at least cut each of the the cells (not the table).
edit 2:
The whole table should be visible all the time, it is not important to read the text, but to see the pattern (with colors gray or red) it creates.
edit 3:
The importance are the colors here, not the labels, so cutting the table and making it scrolling is not a solution here. It is required that like a heat map it is always completely visible.
Use the viewport-relative units for your font-size.
1 vw unit is equal to 1% of the the width of the initial
containing block.
Combine it with proper widths for the parent div (upto the body and html), and it should give you the desired result. The font-size will then dynamically scale depending on the screen (viewport) size. If you reduce the viewport size, the font-size will decrease and vice-versa.
For example:
td {
width: calc(100% / 12); padding: 2px;
overflow: hidden; background: #bababa;
font-size: 1.5vw; /* <---- the viewport relative font-size */
}
Demo Fiddle 1: https://jsfiddle.net/abhitalks/ucoLcm50/9/
Demo Snippet 1 (click full-screen to see the effect):
* { box-sizing: border-box; padding: 0; margin: 0; }
html, body { width: 100%; }
div { background-color: red; width: 50%; min-width: 160px; }
table { width: 100%; font-family: monospace; }
td {
width: calc(100% / 12); padding: 2px;
overflow: hidden; background: #bababa;
font-size: 1.5vw; /* <---- the viewport relative font-size */
}
<div>
<table>
<tr>
<td>A1</td><td>A2</td><td>A3</td><td>A4</td>
<td>A5</td><td>A6</td><td>A7</td><td>A8</td>
<td>A9</td><td>A10</td><td>A11</td><td>A12</td>
</tr>
<tr>
<td>B1</td><td>B2</td><td>B3</td><td>B4</td>
<td>B5</td><td>B6</td><td>B7</td><td>B8</td>
<td>B9</td><td>B10</td><td>B11</td><td>B12</td>
</tr>
</table>
</div>
An alternative (and a better) solution would be to keep the font-size fixed but overflow the containing div based on a min-width. This will keep the table data readable and also allow a scrollable table when there is a space constraint.
For example:
div {
width: 50%; min-width: 180px;
overflow-y: hidden; overflow-x: auto;
}
Demo Fiddle 2: https://jsfiddle.net/abhitalks/pu2yh0fc/1/
Demo Snippet 2:
* { box-sizing: border-box; padding: 0; margin: 0; }
html, body { width: 100%; }
div {
background-color: red; width: 50%; min-width: 180px;
overflow-y: hidden; overflow-x: auto;
}
table { min-width: 100%; font-family: monospace; }
td {
min-width: calc(100% / 12); padding: 2px;
overflow: hidden; background: #bababa;
font-size: 1em;
}
<div>
<table>
<tr>
<td>A1</td><td>A2</td><td>A3</td><td>A4</td>
<td>A5</td><td>A6</td><td>A7</td><td>A8</td>
<td>A9</td><td>A10</td><td>A11</td><td>A12</td>
</tr>
<tr>
<td>B1</td><td>B2</td><td>B3</td><td>B4</td>
<td>B5</td><td>B6</td><td>B7</td><td>B8</td>
<td>B9</td><td>B10</td><td>B11</td><td>B12</td>
</tr>
</table>
</div>
set the table to width: 100%, and the TDs in the table to 1/12 width (8.3%), then the TDs should resize relative to the table.
table{
width: 100%;
}
td {
width:8.3%;
overflow: hidden;
background: #bababa;
}
<div>
<table>
<tr>
<td>A1</td>
<td>A1</td>
<td>A1</td>
<td>A1</td>
<td>A1</td>
<td>A1</td>
<td>A1</td>
<td>A1</td>
<td>A1</td>
<td>A1</td>
<td>A1</td>
<td>A1</td>
</tr>
<tr>
<td>B1</td>
<td>B1</td>
<td>B1</td>
<td>B1</td>
<td>B1</td>
<td>B1</td>
<td>B1</td>
<td>B1</td>
<td>B1</td>
<td>B1</td>
<td>B1</td>
<td>B1</td>
</tr>
</table>
</div>
see:
https://jsfiddle.net/ucoLcm50/1/
How can I have the size dynamically changing, so it always fits the parent div (width: 100%), like an image would?:
See Jonathans Solution, Instead of (1/12) I'll suggest it should be (100/no-of-columns[td's] )% .
should make the font smaller, or at least cut the cells:
add overflow: hidden; in your div's css (So that it'll hide[cut] cells going out of that div):
div {
background-color: red;
width: 50%;
overflow:hidden;
}
table{
width:100%;
}
td {
width:8.3%;
overflow: hidden;
background: #bababa;
}
<div>
<table>
<tr>
<td>A1</td>
<td>A1</td>
<td>A1</td>
<td>A1</td>
<td>A1</td>
<td>A1</td>
<td>A1</td>
<td>A1</td>
<td>A1</td>
<td>A1</td>
<td>A1</td>
<td>A1</td>
</tr>
<tr>
<td>B1</td>
<td>B1</td>
<td>B1</td>
<td>B1</td>
<td>B1</td>
<td>B1</td>
<td>B1</td>
<td>B1</td>
<td>B1</td>
<td>B1</td>
<td>B1</td>
<td>B1</td>
</tr>
</table>
</div>
Fiddle
Hope it Helps..

Why is my calc() failing when used in a table in all browsers except Chrome?

I'm using calc to specify the width of a table's cells. This works in Chrome, but no other browsers.
Caniuse doesn't mention any issues relating to calc in other browsers.
HTML:
<table>
<thead>
<tr>
<th class="first">One</th>
<th class="second">Two</th>
<th class="third">Three</th>
<th class="fourth">Four</th>
</tr>
</thead>
<tbody>
<tr>
<td class="first"></td>
<td class="second"></td>
<td class="third"></td>
<td class="fourth"></td>
</tr>
</tbody>
</table>
CSS (though I'm using Sass):
table {
width: 1200px;
margin: 20px auto 0;
table-layout: fixed;
}
th:nth-child(2n) {
background: grey;
}
th.first {
width: calc(100% * 0.1);
}
th.second {
width: calc(100% * 0.4);
}
th.third {
width: calc(100% * 0.25);
}
th.fourth {
width: calc(100% * 0.25);
}
As you can see, IE11 resolves all cells to the same width:
There is a CodePen here.

table <td> tags not having a uniform and even size

I have a html table I am trying to build as formatting for a website banner and menu links. The menu links tags however won't stay at an even size no matter how much size and margin fiddling I do.
<table id="format_table">
<tr>
<th colspan=100>
LOGO
</th>
</tr>
<tr align="center">
<td>Home</td>
<td>Etc</td>
<td>Etc</td>
<td>Etc</td>
</tr>
<tr>
<td>
#RenderBody()
</td>
</tr>
</table>
table
{
background-color: White;
border: 1;
border-width: 1;
margin-left: auto;
margin-right: auto;
width: 85%;
}
th
{
text-align:center;
margin-left: auto;
margin-right: auto;
width: 80%;
}
td
{
text-align: center;
margin-left: auto;
margin-right: auto;
padding: 0 5 0 5px
}
Try this one:
td { width:100px; height:50px; }

Resources