0

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!

jollelj
  • 1,010
  • 1
  • 10
  • 18
  • the `:before` and `:after` elements are added into the selected element, before its content and after its content, respectively. – Banana Jun 05 '15 at 07:29

4 Answers4

1

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>
DavidDomain
  • 14,976
  • 4
  • 42
  • 50
0

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>
Thi Tran
  • 681
  • 5
  • 11
  • It's kind of what I want, but I actually want the "dot" to display outside the table. Seems the :before actually adds a new table cell. I solved this by adding the :before to the first instead of the – jollelj Jun 05 '15 at 07:39
  • I think DavidDomain's answer is the best solution ^^ – Thi Tran Jun 05 '15 at 07:42
0

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>
Xotic750
  • 22,914
  • 8
  • 57
  • 79
0

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?

David Thomas
  • 249,100
  • 51
  • 377
  • 410
jollelj
  • 1,010
  • 1
  • 10
  • 18