I have the following HTML table:
table th {
border: 1px solid black;
z-index: 1;
}
.a {
max-width: 100px;
overflow: hidden;
white-space: nowrap;
background: white;
}
.b {
white-space: nowrap;
}
.a:hover {
overflow: visible;
z-index: 2;
}
.c {
background: green;
}
<table>
<tr>
<th class=a><span class=c>a very long text that overflows</span></th>
<th class=b>some other text that is very long and should only be partly obscured</th>
</tr>
</table>
What I want to accomplish is that the text in field a ("a very long text that overflows") becomes visible on hover. The table structure should not change.
And indeed it becomes visible, but the text that should be behind it (from field b) partly obscures it. The added span and z-indexes have also no effect. (Tested in Firefox and Chrome)
What I would like is that the text in field a becomes visible and obscures as much of field b as necessary.
Also available in JSFiddle: https://jsfiddle.net/tdn15kh8/7/
Add position: relative; to th that contains overflowing text:
table th {
border: 1px solid black;
z-index: 1;
}
.a {
max-width: 100px;
overflow: hidden;
white-space: nowrap;
background: white;
position: relative;
}
.b {
white-space: nowrap;
}
.a:hover {
overflow: visible;
z-index: 2;
}
.c {
background: lightgreen;
padding-right: .5rem;
}
<table>
<tr>
<th class=a><span class=c>a very long text that overflows</span></th>
<th class=b>some other text that is very long and should only be partly obscured</th>
</tr>
</table>
Check this MDN article to understand stacking context.
For z-index to work, it need a position aswell.
.a:hover {
overflow: visible;
position: relative;
z-index: 2;
}
Fiddle example here
Add position: relative to the .a. The z-index need position:relative or absolute.
There is also data attribute solution, that let you pass text from data attribute to ::after pseudo-class. It looks like this:
table{width: 300px;}
table th{border: 1px solid black;z-index: 1;}
.a{max-width: 100px;overflow: hidden;white-space: nowrap;background: white;}
.b{white-space: nowrap;}
.c{position: relative;}
.a:hover{overflow: visible;}
.a:hover .c::after{content:attr(data-text); display: block;position: absolute; top: 0; left: 0; background: green;}
<table>
<tr>
<th class="a">
<span class="c" data-text="a very long text that overflows">a very long text that overflows</span>
</th>
<th class="b">some other text</th>
</tr>
</table>
Related
I am trying to render the html tags like br,p space tags etc in the td tag that has display:flex.
Note: this is our existing code
red highlighted text (p tags) are need to render with the each new line on the right side but it just renders horizontal in one line
When i try to change display:block the red highlighted displays correct but not render as table on the right column
I want to achieve this
I am not familiar with the display:flex. 'display:flex' is not friendly with the td element if it has html tags? how to achieve with flex and render with html tags.
Give this CSS to parent element of these three boxes:
{
display: flex;
flex-direction: column;
}
I didn't see your full code, but if you want three red box in column and in right side, use this.
I know that you've only asked about the right column, but you should also know that you're not using tables as they should be used here. Your pseudo-element labels are not only making things harder for yourself, they're also not accessible, and they should just be presented as the tabular data they are.
That said, you should really refactor your code.
Like others mentioned, you can use flex-direction: column on that specific cell, if that cell is set to display: flex. That'll then make all of the children inside that cell be organised in a top-to-bottom column, rather than the default left-to-right.
You didn't provide your original code, but he's a refactor including a solution to your issue.
.table {
background-color: #f5f5f5;
border: 1px solid #e3e3e3;
border-spacing: 0 .25em;
padding: 1em;
}
.table__row > * {
vertical-align: top;
text-align: left;
padding: .25em;
}
.table__row th {
background-color: #fefb54;
}
.table__row td {
background-color: #ea4025;
}
.table__row--heading {
background-color: #952516;
color: white;
}
.table__row--heading th,
.table__row--heading td {
background-color: transparent;
}
.table__row th + td {
display: flex;
vertical-align: top;
flex-direction: column;
}
.table__row p {
margin: 0;
}
.table__row p + * {
margin-block-start: 0.5em;
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
<table class="table">
<tr class="table__row table__row--heading">
<th><span class="sr-only">First Name</span></th>
<td>John</td>
</tr>
<tr class="table__row table__row--name">
<th>Last Name</th>
<td>Smith</td>
<tr>
<tr class="table__row table__row--gender">
<th>Gender</th>
<td>
<p>this is a first gender</p>
<p>(break point) </p>
<p>this is the final gender</p>
</td>
</tr>
</table>
You can follow this structure to achieve your requiremnt:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Code</title>
<style>
table {
border-collapse: collapse;
width: 100%;
}
td {
display: block;
}
td.first:before {
content: "First Name";
width: 200px;
display: inline-block;
}
td.last:before {
content: "Last Name";
width: 200px;
display: inline-block;
}
td.gender {
display: flex;
flex-direction: row;
}
td.gender:before {
content: "Gender";
width: 200px;
}
td.gender div p {
margin: 0;
}
</style>
</head>
<body>
<table>
<tbody>
<tr>
<td class="first" title="First Name">John</td>
<td class="last" title="Last Name">Dave</td>
<td class="gender" title="Gender">
<div>
<p>first gender</p>
<p>break point</p>
<p>last gender</p>
</div>
</td>
</tr>
</tbody>
</table>
</body>
</html>
Here is the demo link:
Demo
When the user hovers .tags I want the image at url https://i.stack.imgur.com/BTb0z.jpg (for example) to float to the right of the user's mouse pointer.
How can I do this purely in CSS?
I'd know how to do this in JavaScript, but don't even know if it's possible in CSS, let alone where to start.
I don't think appending an image to the cursor can be done with only CSS. But you can have the cursor itself be an image, check out https://css-tricks.com/almanac/properties/c/cursor/ for a explanation.
But for an image as cursor, you do this:
.class {
cursor: url(images/my-cursor.png), auto;
}
I have a little solution. I think that will work.
.tooltip {
position: relative;
display: inline-block;
border-bottom: 1px dotted black;
}
.tooltip .tooltiptext {
visibility: hidden;
width: 120px;
background-color: black;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px 0;
/* Position the tooltip */
position: absolute;
z-index: 1;
}
.tooltip:hover .tooltiptext {
visibility: visible;
}
<p>Move the mouse over the text below:</p>
<div class="tooltip">Hover over me
<span class="tooltiptext">
<img src="https://secure.gravatar.com/avatar/655f4cf189cbb2349e5bad3314c4f3bc?s=114&d=mm&r=g" alt="" />
</span>
</div>
In pure CSS it's tricky to track the mouse pointer.
As TazTheManiac points out you can set the cursor to an image, but browsers limit the size of the image (commonly 128x182px).
So re-working Harun's answer, which places the image next to the hovered element rather than next to the cursor, to be pure CSS gives:
.tags {
position: relative;
}
.tags:hover:after {
content: '';
position: absolute;
background-image: url(https://i.stack.imgur.com/BTb0z.jpg);
background-repeat: no-repeat;
left: 100%;
top: 0;
width: 1000px; /* These are just large enough to definitely */
height: 1000px; /* contain the image. Image could be any size. */
}
<table>
<tr>
<td>No action</td>
<td>No action</td>
<td>No action</td>
<td class="tags">Hover me!</td>
</tr>
<tr>
<td>No action</td>
<td>No action</td>
<td>No action</td>
<td class="tags">Hover me!</td>
</tr>
</table>
<!--table borders--><style>td{border:1px solid #999;padding:10px;}table{border-collapse:collapse;}</style>
Which worked for me.
I want to be able to change color of any table cell border.
I've decided to not use border-left, border-right, etc, because it's not possible to make it pixel-perfect. Different browsers render it in a different way. Especially in borders intersection area.
I came up with the approach, but it's not working in IE as I expected:
HTML:
<table>
<tr>
<td>
line 1
<div class="left-border"></div>
</td>
<td>
line 1<br>
line 2
</td>
<tr>
</table>
CSS:
table {
border-collapse: collapse;
}
table, th, td {
border: 1px solid #ccc;
}
tr {
vertical-align: top;
}
td {
position: relative;
padding: 5px;
}
.left-border {
position: absolute;
top: -1px;
bottom: -1px;
left: -1px;
width: 1px;
background-color: #000;
}
JSFIDDLE: http://jsfiddle.net/dv1oqopL/5/
well IE is a B***h as always, it just calculates the height of the td based on it's own content so I have no clean fix for you but a hack that might solve your issue is to add
border-left:1px solid #000;
on that td, this will fill the border underneath your div and look the part an all browsers.
I'm having some trouble with the positioning of tooltips on a column of data within a table, which itself is inside a vertical scrolling div. A little background for you...
Due to legacy issues which are beyond my control, the page I am developing has to be displayed through an iframe of fixed width and height. The data I need to display has about 12 columns, all of which are required to be displayed. One column will contain serial numbers, which sometimes end up overflowing the bounds of the cell. I've set the overflow of this column to show an ellipsis, and have added tooltips as described in the accepted answer to this question.
When the tooltips are added, it appears to take the distance from the top of the table to the hovered cell, and draw the tooltip that distance from the top of the parent div. This means that, when you scroll down through the div, the tooltips end up being drawn down below the bottom of the div.
I've created a jsFiddle which demonstrates this: http://jsfiddle.net/kuzxLwxe/4/
Here's my css:
.ResultsWrapper {
width:150px;
height:314px;
text-align:center;
overflow-x:hidden;
overflow-y:scroll;
border:1px solid black;
}
.ResultsTable {
width:86px;
border-collapse:collapse;
table-layout:fixed;
}
.ResultsTable th, .ResultsTable td {
border:1px solid black;
overflow:hidden;
text-overflow:ellipsis;
}
.ColumnSerialNo {
width:81px;
}
.hasTooltip span {
display: none;
color: #000;
text-decoration: none;
padding: 3px;
}
.hasTooltip:hover span {
display: block;
position: absolute;
background-color: #FFF;
border: 1px solid #CCC;
margin: 2px 10px;
}
And my html:
<div class="ResultsWrapper">
<table class="ResultsTable">
<thead>
<tr>
<th class="ColumnSerialNo">Serial Number</th>
</tr>
</thead>
<tbody>
<tr>
<td class="hasTooltip">3119985815206<span>3119985815206</span></td>
</tr>
<tr>
<td class="hasTooltip">5665811486586<span>5665811486586</span></td>
</tr>
...
</tbody>
</table>
</div>
I'm using jQuery for other things within the same page, but so far haven't been able to come up with a solution with it. If you think the best way to fix this is by using JS or jQuery I'd love to see the result!
Thanks in advance
Change your HTML markup to take more control on overflow:
<tr>
<td class="hasTooltip">
<div class="SerialNumberContainer">
<div class="SerialNumber">3119985815206</div>
<div class="SerialNumberTooltip">3119985815206</div>
</div>
</td>
</tr>
And in your CSS, remove overflow from td:
.ResultsTable th, .ResultsTable td {
border:1px solid black;
/* overflow: hidden; this line should delete */
text-overflow:ellipsis;
}
And new CSS:
.SerialNumberContainer {
position: relative;
z-index: 10;
}
.SerialNumber {
width: 80px;
overflow: hidden;
}
.SerialNumberTooltip {
position: absolute;
top: 10px;
left: 2px;
background-color: #FFF;
border: 1px solid #CCC;
display: none;
}
.SerialNumberContainer:hover {
z-index: 20;
}
.SerialNumberContainer:hover .SerialNumberTooltip {
display: block;
}
JSFiddle Demo.
Consider the following example: (live demo here)
$(function() {
console.log("width = " + $("td").width());
});
td {
border: 1px solid black;
width: 50px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tbody>
<tr>
<td>Hello Stack Overflow</td>
</tr>
</tbody>
</table>
The output is: width = 139, and the ellipsis doesn't appear.
What am I missing here?
Apparently, adding:
td {
display: block; /* or inline-block */
}
solves the problem as well.
Another possible solution is to set table-layout: fixed; for the table, and also set it's width. For example: http://jsfiddle.net/fd3Zx/5/
It's also important to put
table-layout:fixed;
Onto the containing table, so it operates well in IE9 (if your utilize max-width) as well.
As said before, you can use td { display: block; } but this defeats the purpose of using a table.
You can use table { table-layout: fixed; } but maybe you want it to behave differently for some colums.
So the best way to achieve what you want would be to wrap your text in a <div> and apply your CSS to the <div> (not to the <td>) like this :
td {
border: 1px solid black;
}
td > div {
width: 50px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
Try using max-width instead of width, the table will still calculate the width automatically.
Works even in ie11 (with ie8 compatibility mode).
td.max-width-50 {
border: 1px solid black;
max-width: 50px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
<table>
<tbody>
<tr>
<td class="max-width-50">Hello Stack Overflow</td>
</tr>
<tr>
<td>Hello Stack Overflow</td>
</tr>
<tr>
<td>Hello Stack Overflow</td>
</tr>
</tbody>
</table>
jsfiddle.
Demo page
For tables with dynamic width, I found the below way to produce satisfying results. Each <th> which is wished to have trimmed-text ability should have an inner wrapping element which wraps the contents of the <th> allow text-overflow to work.
The real trick is to set max-width (on the <th>) in vw units.
This will effectively cause the element's width to be "bound" to the viewport width (browser window) and will result in a responsive content clipping. Set the vw units to a satisfying value needed.
Minimal CSS:
th{ max-width:10vw; }
th > .wrap{
text-overflow:ellipsis;
overflow:hidden;
white-space:nowrap;
}
Demo (with editable texts):
document.designMode="on"
table {
font: 18px Arial;
width: 40%;
margin: 1em auto;
color: #333;
border: 1px solid rgba(153, 153, 153, 0.4);
}
table td, table th {
text-align: left;
padding: 1.2em 20px;
white-space: nowrap;
border-left: 1px solid rgba(153, 153, 153, 0.4);
}
table td:first-child, table th:first-child {
border-left: 0;
}
table th {
border-bottom: 1px solid rgba(153, 153, 153, 0.4);
font-weight: 400;
text-transform: uppercase;
max-width: 10vw;
}
table th > .wrap {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
<table>
<thead>
<tr>
<th>
<div class="wrap" title="Some long title">Some long title</div>
</th>
<th>
<div class="wrap">Short</div>
</th>
<th>
<div class="wrap">medium one</div>
</th>
<th>
<div class="wrap" title="endlessly super long title which no developer likes to see">endlessly super long title which no developer likes to see</div>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>-</td>
<td>-</td>
<td>-</td>
<td>very long text here</td>
</tr>
</tbody>
</table>
Just offering an alternative as I had this problem and none of the other answers here had the desired effect I wanted. So instead I used a list. Now semantically the information I was outputting could have been regarded as both tabular data but also listed data.
So in the end what I did was:
<ul>
<li class="group">
<span class="title">...</span>
<span class="description">...</span>
<span class="mp3-player">...</span>
<span class="download">...</span>
<span class="shortlist">...</span>
</li>
<!-- looped <li> -->
</ul>
So basically ul is table, li is tr, and span is td.
Then in CSS I set the span elements to be display:block; and float:left; (I prefer that combination to inline-block as it'll work in older versions of IE, to clear the float effect see: http://css-tricks.com/snippets/css/clear-fix/) and to also have the ellipses:
span {
display: block;
float: left;
width: 100%;
// truncate when long
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
Then all you do is set the max-widths of your spans and that'll give the list an appearance of a table.
Instead of using ellipsis to solve the problem of overflowing text, I found that a disabled and styled input looked better and still allows the user to view and select the entire string if they need to.
<input disabled='disabled' style="border: 0; padding: 0; margin: 0" />
It looks like a text field but is highlight-able so more user friendly
Check box-sizing css property of your td elements. I had problem with css template which sets it to border-box value. You need set box-sizing: content-box.
I've tried many of the above solutions but none of them felt flexible or satisfying.
This little hack with max-width: 1px can be applied directly to the td element
.truncated-cell {
max-width: 1px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
Leave your tables as they are. Just wrap the content inside the TD's with a span that has the truncation CSS applied.
/* CSS */
.truncate {
width: 50px; /*your fixed width */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: block; /* this fixes your issue */
}
<!-- HTML -->
<table>
<tbody>
<tr>
<td>
<span class="truncate">
Table data to be truncated if it's too long.
</span>
</td>
</tr>
</tbody>
</table>
.ellipsis {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
}
The above setting worked for me, without changing table widths. I added a div inside and added the class ellipsis to it.
If you don't want to set max-width to td (like in this answer), you can set max-width to div:
function so_hack(){}
function so_hack(){} http://jsfiddle.net/fd3Zx/754/ function so_hack(){}
function so_hack(){}
Note: 100% doesn't work, but 99% does the trick in FF. Other modern browsers doesn't need silly div hacks.
td {
border: 1px solid black;
padding-left:5px;
padding-right:5px;
}
td>div{
max-width: 99%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}