HTMLTable: Empty link element should take up whole cell space - html

I am using a (bootstrap) table where I put a link inside one of the cells, where it might happen, that the actual link text is empty, thus not showing the link element (or better to say the user can't click it). Now the goal is, that the link element should take up the whole cell space regardless of whether there is some text in the link or not.
<table class="table table-bordered table-striped">
<tr>
<td><a ...>Text that might be empty</a></td>
...
I have tried setting the display property of the a-tag to inline-table which worked for the most browsers except IE. Is there a nice, clean and crossbrowser compatible way to achieve this?

Give the anchor a display: block. It then will take the full width of its parent.
I've made you this demo. By clicking the button, you'll see how it works.
Note, that the anchor should at least have 'something' in it.
$('button').click(function() {
$('a').toggleClass('block');
});
td {
border: 1px solid red;
}
tr, td {
height: 100%;
}
a {
background: blue;
}
a.block {
display: block;
height: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<td> </td>
<td>Text<br />text</td>
</tr>
<tr>
<td>Text text</td>
<td>Text text</td>
</tr>
</table>
<button>Toggle block</button>

Set min-width for the column
<td style="min-width:50px"><a ...>Text that might be empty</a></td>

This will work with/without text.
.hasLink{
position: relative;
height: 38px;
}
.hasLink a{
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
font-size: 0px; //if you don't want to show any text
padding: 8px 0 0 5px;
}
<tr>
<td class="hasLink"></td>
<td></td>
</tr>

Related

Align background image to the right of a table td element

I have a table with td elements holding text, left-aligned as normal.
Under certain conditions, I am adorning my td elements with a background image (denoted by a tick).
My css element to attempt to achieve this is:
td.entered {
background: url(../images/tick.png) no-repeat;
float: right;
}
<table>
<tr>
<td class "entered">Here is some text</td>
</tr>
</table>
However, no matter how I adjust this CSS, I don't get what I want, and the tick image appears in the centre of the td.
Is there a way to make this image float on the right, so that it interferes less with the text in that cell?
Perhaps this?
td.entered {
width: 200px;
background: url("https://www.freeiconspng.com/thumbs/check-tick-icon/tick-mark-icon-png-7.png") right -1px no-repeat ;
background-size: 25px;
}
<table>
<tr>
<td class="entered">Here is some text</td>
</tr>
</table>
Without images
td.entered {
width: 200px;
}
span.ticked:after {
content: "✓";
display: inline-block;
float: right
}
<table>
<tr>
<td class="entered">Here is some text<span class="ticked"></span></td>
</tr>
</table>
Dynamic demo
JavaScript to show what the cell looks like before and after the span has ticked
document.querySelector(".entered").addEventListener("click",function() {
this.querySelector("span").classList.add("ticked");
})
td.entered {
width: 200px;
}
span.ticked:after {
content: "✓";
display: inline-block;
float: right
}
<table>
<tr>
<td class="entered">Here is some text<span></span></td>
</tr>
</table>

Perfectly align text to the top of table cell

How can i perfectly align text to the top of a table cell? By perfectly, I mean that the top of the letters touch the border of the table cell.
An additional difficulty in my case is that I need to use a large line height (approximately double the font height). As a result, there's is a considerable space between the top of the letters and the cell border because the difference between the font height and the line height is distributed equally to both the top and bottom of the text (so called half-leading).
I've setup a JSFiddle.
<table>
<tbody>
<tr>
<td> </td>
<td>NOT PROPERLY ALIGNED TO THE TOP</td>
</tr>
</tbody>
</table>
table {
width: 100%;
table-layout: fixed;
border-collapse: collapse;
padding: 0;
margin: 0;
}
td {
height: 200px;
vertical-align: top;
font-size: 18px;
line-height: 40px;
border: solid 1px black;
background-color: #ddd;
}
How about wrapping necessary text in some spans and adding negative position/margin, like
span {
position: relative;
top: -12px;
}
Fiddle
But for a good readability, you'd rather don't need to remove space at top (imho)
Look, the text at left side looks better.
If you changed your html to:
<table>
<tbody>
<tr>
<td> </td>
<td><span>NOT PROPERLY ALIGNED TO THE TOP</span></td>
</tr>
</tbody>
</table>
adding <span> tags
Then you can go:
td span {
margin-top: -15px;
}
Hope this helps
Demo
The issue is because of the line-height
You can change the line-height of the first line by using the selector :first-line like
td:first-line {
line-height: 10px;
}
I have a solution but it goes with JS, not pure CSS only.
HTML (added the 'span' tag inside 'td'):
<table>
<tbody>
<tr>
<td> </td>
<td>
<span id="myText">PROPERLY ALIGNED TO THE TOP</span>
</td>
</tr>
</tbody>
</table>
JS:
$(document).ready(function(){
var span = $("#myText");
var lineHeight = parseInt(span.css("line-height"));
var fontSize = parseInt(span.css("font-size"));
var shift = (lineHeight-fontSize)/2;
var shiftPx = "-"+shift+"px";
//alert(lineHeight);
//alert(fontSize);
span.css({
"position":"relative",
"top":shiftPx
});
});
Full jsfiddle: http://jsfiddle.net/jondinham/p8g1cx6b/

Overflow:hidden not working in Firefox?

I have a table with rounded corner, and I've put an overflow: hidden CSS command on it so that the corners of the individual cells don't protrude out. It works fine on Chrome, but not on Firefox. Can someone tell me what's wrong?
<style>
table {
border-spacing: 0px;
border: 1px solid #222;
border-radius:8px;-moz-border-radius:8px;-webkit-border-radius:8px;
overflow: hidden;
}
th {
height: 30px;
color: #fff;
background: #222;
text-align: left;
}
tr:nth-child(even) {
background: #245876;
color: #fff;
border: none;
height: 25px;
}
tr:nth-child(odd) {
height: 23px;
}
.pos {
width: 50px;
}
.name {
width: 175px;
}
</style>
<table>
<thead>
<tr>
<th class="pos"></th>
<th class="name">Name</th>
<th class="amount">Amount</th>
</tr>
</thead>
<tbody>
<tr>
<td class="pos">1</td>
<td class="name">Bob</td>
<td class="amount">1324353</td>
</tr>
<tr>
<td class="pos">2</td>
<td class="name">John</td>
<td class="amount">10611</td>
</tr>
<tr>
<td class="pos">3</td>
<td class="name">Bill</td>
<td class="amount">3270</td>
</tr>
<tr>
<td class="pos">4</td>
<td class="name">Brian</td>
<td class="amount">1950</td>
</tr>
<tr>
<td class="pos">5</td>
<td class="name">Dan</td>
<td class="amount">1760</td>
</tr>
</tbody>
</table>
The spec does not require the behavior you are looking for: "The ‘border-radius’ properties do apply to ‘table’ and ‘inline-table’ elements. When ‘border-collapse’ is ‘collapse’, the UA may apply the border-radius properties to ‘table’ and ‘inline-table’ elements, but is not required to." (http://dev.w3.org/csswg/css-backgrounds/#border-radius-tables)
It is possible it simply will not work in Firefox. If that's the case, you could apply border-radius to the header cells (:first-child and :last-child in the header row), but it doesn't always line up properly. A bit of a PITA, I know.
thead tr th:first-child { border-radius:8px 0 0 0; }
thead tr th:last-child { border-radius:0 8px 0 0; }
This might help. How to make CSS3 rounded corners hide overflow in Chrome/Opera
Add where you want:
-moz-overflow: hidden;
I like Pete Scott's answer. But depending on your design, you can create the radius effect on a table by wrapping the table itself in a containing element that has the radius left and right, overflow hidden. Then, position relative the table, and -*px to create the required visual effect. But without seeing the desired end result, I am unable to provide an example.
It's possible to change the effect of overflow on the table element with the following trick: change the display of the table, e.g., to inline-block (this value preserves the shrink-fit width of the table and shouldn't break the layout assuming the table is surrounded by block elements). The resulting rendering will be equivalent as if the table has the div wrapper with border-radius and overflow, which renders in Firefox without problems. Here is the JSbin example.

Linethrough/strikethrough a whole HTML table row

After some research, I couldn't find an answer to this question. There was this but it didn't really answer my question. I would like to "strikethrough" a complete HTML table row in CSS, not just the text in it. Is it at all possible? From the example that I linked, it seems tr styling doesn't even work in Firefox. (And anyway, text-decoration only applies on text afaik)
Oh yes, yes it is!
CSS:
table {
border-collapse: collapse;
}
td {
position: relative;
padding: 5px 10px;
}
tr.strikeout td:before {
content: " ";
position: absolute;
top: 50%;
left: 0;
border-bottom: 1px solid #111;
width: 100%;
}
HTML:
<table>
<tr>
<td>Stuff</td>
<td>Stuff</td>
<td>Stuff</td>
</tr>
<tr class="strikeout">
<td>Stuff</td>
<td>Stuff</td>
<td>Stuff</td>
</tr>
<tr>
<td>Stuff</td>
<td>Stuff</td>
<td>Stuff</td>
</tr>
</table>
http://codepen.io/nericksx/pen/CKjbe
My answer (below) said that it is not possible. I was wrong, as pointed out by #NicoleMorganErickson. Please see her answer (and upvote it!) for how to do it. In short, you use :before pseudo-class to create an element that draws a border across the middle of the cell, above the content:
table { border-collapse:collapse } /* Ensure no space between cells */
tr.strikeout td { position:relative } /* Setup a new coordinate system */
tr.strikeout td:before { /* Create a new element that */
content: " "; /* …has no text content */
position: absolute; /* …is absolutely positioned */
left: 0; top: 50%; width: 100%; /* …with the top across the middle */
border-bottom: 1px solid #000; /* …and with a border on the top */
}
(original answer)
No, it is not possible using only CSS and your semantic table markup. As #JMCCreative suggests, it is possible visually using any number of ways to position a line over your row.
I would instead suggest using a combination of color, background-color, font-style:italic and/or text-decoration:line-through to make the entire row obviously different. (I'd personally strongly 'fade out' the text to a color much closer to the background than normal text and make it italic.)
tr {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2NkYGCQBAAAIwAbDJgTxgAAAABJRU5ErkJggg==');
background-repeat: repeat-x;
background-position: 50% 50%;
}
I used http://www.patternify.com/ to generate the 1x1 image url.
Edit
In a recent Bootstrap 4.3 ServiceNow Angular.js project, I found myself having to make some changes, and instead used the following CSS, similar to the experience of Revoman:
tr.strikeout td.strike-able:before {
content: " ";
position: absolute;
display: inline-block;
padding: 12px 10px;
left: 0;
border-bottom: 2px solid #d9534f;
width: 100%;
}
Original Post
I like Nicole Morgan Erickson's answer, but it might cause side effects if your implement his solution verbatim. I've add some small tweaks to keep this kosher, below... so that we're not globally modifying every table or every td with this CSS.
I also wanted a button on the row to strike out the row, but I didn't want to strike out the column with the button, for visibility sake. I just wanted to strike out the rest of the row. For this, I made it so that every column that wants to be capable of showing the strike out must declare such by also being marked with a class. In this iteration, you'd need to mark the table as strike-able, and also mark each td as strike-able; but you gain safety by not side effecting any non-strike-able tables, and you gain control of which columns to strike out.
CSS:
table.strike-able {
border-collapse: collapse;
}
table.strike-able tr td {
position: relative;
padding: 3px 2px;
}
table.strike-able tr th {
position: relative;
padding: 3px 2px;
}
table.strike-able tr.strikeout td.strike-able:before {
content: " ";
position: absolute;
top: 50%;
left: 0;
border-bottom: 2px solid #d9534f;
width: 100%;
}
Usage:
<table class="strike-able" id="Medications" data-item-count="#Model.Medications.Count">
<tr>
<th>
Some Column
</th>
<th>
Command Column
</th>
</tr>
<tr class="strikeout">
<td class="strike-able"></td>
<td>Button that Toggles Striking Goes Here (active)</td>
</tr>
<tr>
<td class="strike-able"></td>
<td>Button that Toggles Striking Goes Here</td>
</tr>
</table>
Lastly, since I'm using this with Bootstrap, and treating the deletions as a dangerous thing to do, I've formatted the colors a little to match my use.
EDIT: As pointed out by #Mathieu M-Gosselin in the comments, this actually puts the line behind the text. That said, if your line is the same color as your text or you are using a small-ish font, this still works pretty well.
For what it's worth, here's a pretty effective way to do it in pure CSS without using pseudo elements. You can change the thickness of the strikethrough line by adjusting the background-size.
table {
border-collapse: collapse;
}
td {
width: 100px
}
.strikethrough {
background: repeating-linear-gradient(
180deg,
red 0%,
red 100%
);
background-size: 100% 2px;
background-position: center;
background-repeat: no-repeat;
}
<table>
<tr>
<td>Foo</td>
<td>Bar</td>
<td>Baz</td>
</tr>
<tr class="strikethrough">
<td>Foo Strike</td>
<td>Bar Strike</td>
<td>Baz Strike</td>
</tr>
</table>
#NicoleMorganErickson, I like your answer, but I could not get the strikeout to affect only the applied row. Also, I needed it to be applied multiple rows so I modified your solution down into a single class.
CSS:
tr.strikeout td:before {
content: " ";
position: absolute;
display: inline-block;
padding: 5px 10px;
left: 0;
border-bottom: 1px solid #111;
width: 100%;
}
http://codepen.io/anon/pen/AaFpu
Yes you can. In the first cell of the row you create a div containing a HR. Float the div to the left and specify its width as a % of its containing element, in this case the table cell. It'll stretch as wide as you want across the table cells in that row, even beyond the width of the table if you want.
This works for me:
<style>
.strikeThrough {
height:3px;
color:#ff0000;
background-color:#ff0000;
}
.strikeThroughDiv {
float:left;
width:920%;
position:relative;
top:18px;
border:none;
}
</style>
<table width="900" border="1" cellspacing="0" cellpadding="4">
<tr valign="bottom">
<td>
<div class="strikeThroughDiv"><hr class="strikeThrough"/></div>
One
</td>
<td>
<label for="one"></label>
<input type="text" name="one" id="one" />
</td>
<td>
<label for="list"></label>
<select name="list" id="list">
<option value="One">1</option>
<option value="Two">2</option>
<option value="Three" selected>3</option>
</select>
</td>
<td>
Four
</td>
<td>
Five
</td>
</tr>
</table>
To control the width of your line you have to specify the width of the table cell containing the HR. For styling HR elements they say you shouldn't make it less than 3px in height.
Here's a very simple way that worked for me:
<table>
<tbody style="text-decoration: line-through">
-- Various table body stuff
</tbody> </table>
Not sure but it seems there were other answers mentioning simple and straightforward pure CSS solution...
#Ben Slade's answer is the closest of all, but still...
Just use text-decoration: line-through in your CSS! Add corresponding class and then use <tr class="strikethrough">!
.strikethrough {
text-decoration: line-through;
}
table,
th,
td {
border: 1px solid black;
}
<table>
<tr>
<th>Company</th>
<th>Contact</th>
<th>Country</th>
</tr>
<tr class="strikethrough">
<td>Centro comercial Moctezuma</td>
<td>Francisco Chang</td>
<td>Mexico</td>
</tr>
<tr>
<td>Alfreds Futterkiste</td>
<td>Maria Anders</td>
<td>Germany</td>
</tr>
</table>

Make link in table cell fill the entire row height

I have a table of data and each cell is a link. I want to allow the user to click anywhere in the table cell and have them follow the link. Sometimes the table cells are more than one line but not always. I use td a {display: block} to get the link to cover most of the cell. When there is one cell in a row that is two lines and the others are only one line the one liners don't fill the entire vertical space of the table row. Here is the sample HTML and you can see it in action here http://www.jsfiddle.net/RXHuE/:
<head>
<style type="text/css">
td {width: 200px}
td a {display: block; height:100%; width:100%;}
td a:hover {background-color: yellow;}
</style>
<title></title>
</head>
<body>
<table>
<tbody>
<tr>
<td>
<a href="http://www.google.com/">Cell 1<br>
second line</a>
</td>
<td>
Cell 2
</td>
<td>
Cell 3
</td>
<td>
Cell 4
</td>
</tr>
</tbody>
</table>
</body>
Set an arbitrarily large negative margin and equal padding on the block element and overflow hidden on the parent.
td {
overflow: hidden;
}
td a {
display: block;
margin: -10em;
padding: 10em;
}
http://jsfiddle.net/RXHuE/213/
You need a small change in your CSS. Making td height:100%; works for IE 8 and FF 3.6, but it doesn't work for Chrome.
td {
width: 200px;
border: solid 1px green;
height: 100%
}
td a {
display: block;
height:100%;
width:100%;
}
But making height to 50px works for Chrome in addition to IE and FF
td {
width: 200px;
border: solid 1px green;
height: 50px
}
td a {
display: block;
height:100%;
width:100%;
}
Edit:
You have given the solution yourself in another post here; which is to use display: inline-block;.
This works when combined with my solution for Chrome, FF3.6, IE8
td {
width: 200px;
border: solid 1px green;
height: 100%}
td a {
display: inline-block;
height:100%;
width:100%;
}
Update
The following code is working for me in IE8, FF3.6 and chrome.
CSS
td {
width: 200px;
border: solid 1px green;
height: 100%;
}
td a {
display: inline-block;
height:100%;
width:100%;
}
td a:hover {
background-color: yellow;
}
HTML
<table>
<tbody>
<tr>
<td>
<a href="http://www.google.com/">Cell 1<br>
second line</a>
</td>
<td>
Cell 2
</td>
<td>
Cell 3
</td>
<td>
Cell 4
</td>
</tr>
</tbody>
</table>
The example lays here
Little late to the party, but there's a nice solution I just discovered.
You can use a combination of relative and absolute positioned elements, along with a pseudo element to get the effect you're looking for. No extra markup needed!
Change the table cell (<td>), to be position: relative;, and create a ::before or ::after pseudo element on the <a> tag, and set it to position: absolute;, and also use top: 0; left: 0; right: 0; bottom: 0;.
Because the pseudo element is attached to the anchor tag, and you're telling it to take up the entire table cell, it will force the anchor tag to be at least that size, whilst not affecting the actual content of the anchor tag itself (thereby retaining its vertically centered alignment).
For example
table {
border-collapse: collapse;
table-layout: fixed;
}
td {
position: relative;
width: 200px;
padding: 0.5em 1em;
border: 2px solid red;
background-color: lime;
}
td a {
/* FONT STYLES HERE */
text-decoration: none;
}
td a::after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 0;
}
<table>
<tbody>
<tr>
<td>
<a href="http://www.google.com/">Cell 1<br>
second line</a>
</td>
<td>
Cell 2
</td>
<td>
Cell 3
</td>
<td>
Cell 4
</td>
</tr>
<tr>
<td>
Cell 5
</td>
<td>
<a href="http://www.google.com/">Cell 6<br>
second line</a>
</td>
</tr>
</tbody>
</table>
Hope this helps!
Following hack works [Tested on Chrome / Firefox / Safari]
Have the same padding for td and anchor elements. And for anchor also have margin which is equal to -ve of padding value.
HTML
<table>
<tr>
<td><a>Hello</a></td>
</tr>
</table>
CSS:
td {
background-color: yellow;
padding: 10px;
}
a {
cursor:pointer;
display:block;
padding: 10px;
margin: -10px;
}
Working Fiddle :http://jsfiddle.net/JasYz/
Try display: block:
td a {display: block; height:100%;}
[EDIT] WTF ... I can confirm this doesn't work in FF 4 and Chrome. This works:
td a {display: block; height: 2.5em; border: 1px solid red;}
That suggests that height:100%; isn't defined in a table cell. Maybe this is because the cell gets its size from the content (so the content can't say "tell me your size" because that would lead to a loop). It doesn't even work if you set a height for the cells like so:
td {width: 200px; height: 3em; padding: 0px}
Again the code above will fail. So my suggestion is to use a defined height for the links (you can omit the width; that is 100% by default for block elements).
[EDIT2] I've clicked through a hundred examples at http://www.cssplay.co.uk/menus/ but none of them mix single line and multi-line cells. Seems like you hit a blind spot.
I will post the same answer here, as I did on my own question.
Inspired by Jannis M's answer, I did the following:
$(document).ready(function(){
$('table tr').each(function(){
var $row = $(this);
var height = $row.height();
$row.find('a').css('height', height).append(' ');
});
});
I added a since empty links (not containing text nodes) can not be styled(?).
See my updated fiddle.
Only problem here is that using display: block forces the browser to ignore the vertical align: center...
oops.
I jury rigged it to look right for one cell with height:60 and a font that occupied 20 pixels by adding a br... Then I realized that I had some items with 2-line text. Dang.
I ended up using the javascript. The javascript doesn't give the nice mousey pointy clicker thing, but the line of text does, so it will actually trigger a visual response, just not where I want it to... Then the Javascript will catch all the clicks that 'miss' the actual href.
Maybe not the most elegant solution, but it works well enough for now.
Now if I could only figure out how to do this the right way....
Any ideas on how to add the mouse icon change to a hand for the area covered by the onclick? Right now, the click to page works, but the icon only changes when it hits the href which only affects the text.
Why don't you just get rid of the <a> altogheter and add an onClick to the <td> directly?
<head>
<style type="text/css">
td {
text-align:center;
}
td:hover {
cursor:pointer;
color:#F00;
}
</style>
<title></title>
</head>
<body>
<table>
<tbody>
<tr>
<td onclick="location.href='http://www.google.com/';">Cell 1<br />second line</td>
<td onclick="location.href='http://www.google.com/';">Cell 2</a></td>
<td onclick="location.href='http://www.google.com/';">Cell 3</td>
<td onclick="location.href='www.google.com';">Cell 4</td>
</tr>
</tbody>
</table>
This way you cut out the middle man.
PS: i know this was asked and answered many years ago, but none of the answers above solved the problem in my case. Hope this helps someone.
For me the only solution is to replace <table> <tr> with <div>s and style them using display:table and display:table-row accordingly.
Then you can replace <td> with just <a> and style it with display:table-cell.
Work perfectly even on varying heights of <td> contents.
so original html without anchors:
<table>
<tr>
<td>content1<br>another_line</td>
<td>content2</td>
</tr>
</table>
now becomes:
a:hover
{
background-color:#ccc;
}
<div style="display:table; width:100%">
<div style="display:table-row">
content1<br>another_line
content2
</div>
</div>
I have used this solution: works better then the rest in my case.
CSS:
.blocktd {width: 100%; height: 100%; padding: 0px; overflow: hidden}
a.blocktd {margin: 0em; padding: 50px 20px 50px 20px; display: block;}
a.blocktd:hover {border: 4px solid #70AEE8; border-radius: 10px; padding: 46px 16px 46px 16px; transition: 0.2s;}
And in HTML: ...