Reputation: 1028
I'm trying to achieve a sort of selection effect on a table that I'm currently working on. I want to do this by adding a class to the table row that the user clicks. The class that gets added to the row will add a small circle to the left of the row. However, as I'm adding the class to the row, the table (or the row) seems to expand a few pixels. I can't figure out why.
Some example code to illustrate my problem:
document.querySelector('tr').addEventListener('click', function() {
if (!this.classList.contains('clicked')) {
this.classList.add('clicked');
return;
}
this.classList.remove('clicked');
});
table {
position: relative;
background: #ccc;
margin: 5rem auto;
}
.clicked:before {
position: absolute;
content: '';
right: 100%;
top: 50%;
width: 10px;
height: 10px;
border-radius: 50%;
background: yellow;
}
<table>
<tr>
<td>1</td>
<td>Two</td>
<td>3</td>
<td>Four</td>
<td>1</td>
<td>Longer text..</td>
<td>3</td>
<td>Four</td>
</tr>
</table>
Any help would be much appreciated!
Upvotes: 0
Views: 216
Reputation: 1028
This post helped me solve the problem. Seems :before actually "creates" a new table cell. Had to add the :before to the first <td>
in my code instead of the <tr>
.
Is it possible to use pseudo-elements (:after, :before) inside a table row?
Upvotes: 0
Reputation: 23492
You could use the css visibility property and an extra class. This way any effect that is caused by ::before
will be in the rendering but just not visible.
Summary The visibility property can be used to hide an element while leaving the space where it would have been. It can also hide rows or columns of a table.
document.querySelector('tr').addEventListener('click', function () {
this.classList.toggle('visible');
});
table {
position: relative;
background: #ccc;
margin: 5rem auto;
}
.clicked::before {
position: absolute;
content:'';
right: 100%;
top: 50%;
width: 10px;
height: 10px;
border-radius: 50%;
background: yellow;
visibility: hidden;
}
.visible::before {
visibility: visible;
}
<table>
<tr class="clicked">
<td>1</td>
<td>Two</td>
<td>3</td>
<td>Four</td>
<td>1</td>
<td>Longer text..</td>
<td>3</td>
<td>Four</td>
</tr>
</table>
Upvotes: 0
Reputation: 701
I have a trick. I hope it works as what you want
document.querySelector('tr').addEventListener('click', function() {
if (!this.classList.contains('clicked')) {
this.classList.add('clicked');
return;
}
this.classList.remove('clicked');
});
table {
position: relative;
background: #ccc;
margin: 5rem auto;
}
.show-me {
width: 10px;
height: 10px;
border: 0;
background-color: transparent;
}
.show-me span {
display: none;
width: 10px;
height: 10px;
border-radius: 50%;
background: yellow;
}
.clicked .show-me span {
display: block;
}
<table>
<tr>
<td class="show-me">
<span></span>
</td>
<td>1</td>
<td>Two</td>
<td>3</td>
<td>Four</td>
<td>1</td>
<td>Longer text..</td>
<td>3</td>
<td>Four</td>
</tr>
</table>
Upvotes: 0
Reputation: 15303
You could add your clicked:before
element and set it's opacity
to 0
and then on the click event
add another class to actually show the element.
document.querySelector('tr').addEventListener('click', function() {
if (!this.classList.contains('show-clicked')) {
this.classList.add('show-clicked');
return;
}
this.classList.remove('show-clicked');
});
table {
position: relative;
background: #ccc;
margin: 5rem auto;
}
tr {
margin-left: 10px;
}
.clicked:before {
position: absolute;
content: '';
right: 100%;
top: 50%;
width: 10px;
height: 10px;
border-radius: 50%;
background: yellow;
opacity: 0;
}
.show-clicked:before {
opacity: 1;
}
<table>
<tr class="clicked">
<td>1</td>
<td>Two</td>
<td>3</td>
<td>Four</td>
<td>1</td>
<td>Longer text..</td>
<td>3</td>
<td>Four</td>
</tr>
</table>
Upvotes: 1