'What is the need for ::after when trying to highlight a table column in CSS?

So for highlighting rows in a table, we only need tr:hover and you have to set a background-color that has has an opacity of less than 1 to appear as if it's a highlight.

But for highlighting columns, why is there a need for ::after or ::before and the content part in this CSS? This code is currently working fine but I just want to understand what they're for.

table {
        border:  1px solid black;
        border-collapse: collapse;  /*no borders*/
        width: 75%;
        margin-left: auto;
        margin-right: auto;
        font-family: "Gill Sans", sans-serif;
        z-index: 1;             /*table is over the highlight*/
        overflow: hidden;       /*cuts off the column highlight as to not overflow*/
    }
    
tr:hover {                  /*highlights rows*/
        background-color: rgba(195, 164, 255, 0.25);
        z-index: -1;
    }
td:hover::after {           /*highlights columns*/
        background-color: rgba(195, 164, 255, 0.25);
        content: "";
        height: 10000px;    
        left: 0;
        position: absolute;  
        top: -5000px;
        width: 100%;
        z-index: -1;
    } 

Here's the HTML:

<body>
<h2>Timetable</h2>
<table>
    <tr>
        <th>Time</th>
        <th>Monday</th>
        <th>Tuesday</th>
        <th>Wednesday</th>
        <th>Thursday</th>
        <th>Friday</th>
        <th>Saturday</th>
        <th>Sunday</th>
    </tr>

    <tr>
        <th>0900-1000</th>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td>Jia</td>
        <td>Jesse</td>
    </tr>

    <tr>
        <th>1000-1100</th>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td></td>
        <td>Jia</td>
        <td>Kaidan</td>
    </tr>
</table>
</body>
css


Solution 1:[1]

::after and ::before are pseudo-elements. A pseudo-element is used to style specified parts of an element, and they're especified, as a rule, with double colons ::; this distinguishes pseudo-classes (with single colon :) from pseudo-elements (since CSS3).

Pseudo-classes let you apply a style to an element not only in relation to the content of the document tree, but also in relation to external factors like hover.

::before and ::after create a pseudo-element that is the first or the last child of the selected element, respectively. That means, that this pseudo-elements are contained by the element and thus don't apply to replaced elements.

The property content replaces an element with a generated value. For example, content could be an icon:

.test::after {
  content: "?";
 }
<div class='test'></div>

Or the quotes of a text:

.test::before {
  content: open-quote;
  color: lime;
}
.test::after {
  content: close-quote;
  color: blue;
}
 <div class='test'>This is a quoted text with pseudo-elements</div>

Or even a linear gradient:

.test::after {
  content: linear-gradient(#e66465, #9198e5);
}
<div class='test'></div>

When creating one of this after/before pseudo-elements, It's necessary to add the content property. So that's why you will sometimes see content: "". Look at this ::before with no content property:

.test::before {
  width: 40px;
  height: 40px;
  background-color: red;
  position: fixed;
}
<div class='test'></div>

Well, you probably didn't see anything. Now the same code, with content: "" property:

.test::before {
    content: "";
    width: 40px;
    height: 40px;
    background-color: red;
    position: fixed;
  }
<div class='test'></div>

Regarding to your question, there's no need to add ::after or ::before to highlight the columns. What you're doing in your ::after element is creating a very big "container" when user hovers over a td, so you're "highlighting" the entire page, not only the columns.

You could do:

Highlight al the td when on hover over tr:

table {
  border: 1px solid black;
  border-collapse: collapse;
  /*no borders*/
  width: 75%;
  margin-left: auto;
  margin-right: auto;
  font-family: "Gill Sans", sans-serif;
  z-index: 1;
  /*table is over the highlight*/
  overflow: hidden;
  /*cuts off the column highlight as to not overflow*/
}

tr:hover {
  /*highlights rows*/
  background-color: rgba(195, 164, 255, 0.25);
  z-index: -1;
}

tr:hover>td {
  /*highlights columns*/
  background-color: rgba(195, 164, 255, 0.9);
}
<table>
  <tr>
    <th>Time</th>
    <th>Monday</th>
    <th>Tuesday</th>
    <th>Wednesday</th>
    <th>Thursday</th>
    <th>Friday</th>
    <th>Saturday</th>
    <th>Sunday</th>
  </tr>

  <tr>
    <th>0900-1000</th>
    <td></td>
    <td></td>
    <td></td>
    <td></td>
    <td></td>
    <td>Jia</td>
    <td>Jesse</td>
  </tr>

  <tr>
    <th>1000-1100</th>
    <td></td>
    <td></td>
    <td></td>
    <td></td>
    <td></td>
    <td>Jia</td>
    <td>Kaidan</td>
  </tr>
</table>

Highlight only the td when on hover:

table {
  border: 1px solid black;
  border-collapse: collapse;
  /*no borders*/
  width: 75%;
  margin-left: auto;
  margin-right: auto;
  font-family: "Gill Sans", sans-serif;
  z-index: 1;
  /*table is over the highlight*/
  overflow: hidden;
  /*cuts off the column highlight as to not overflow*/
}

tr:hover {
  /*highlights rows*/
  background-color: rgba(195, 164, 255, 0.25);
  z-index: -1;
}

td:hover {
  /*highlights columns*/
  background-color: rgba(195, 164, 255, 0.9);
}
<table>
  <tr>
    <th>Time</th>
    <th>Monday</th>
    <th>Tuesday</th>
    <th>Wednesday</th>
    <th>Thursday</th>
    <th>Friday</th>
    <th>Saturday</th>
    <th>Sunday</th>
  </tr>

  <tr>
    <th>0900-1000</th>
    <td></td>
    <td></td>
    <td></td>
    <td></td>
    <td></td>
    <td>Jia</td>
    <td>Jesse</td>
  </tr>

  <tr>
    <th>1000-1100</th>
    <td></td>
    <td></td>
    <td></td>
    <td></td>
    <td></td>
    <td>Jia</td>
    <td>Kaidan</td>
  </tr>
</table>

If you want to do this whith pseudo-elements, this is what you should do:

Highlight al the td when on hover over tr with pseudo-elements:

table {
  border: 1px solid black;
  border-collapse: collapse;
  /*no borders*/
  width: 75%;
  margin-left: auto;
  margin-right: auto;
  font-family: "Gill Sans", sans-serif;
  z-index: 1;
  /*table is over the highlight*/
  overflow: hidden;
  /*cuts off the column highlight as to not overflow*/
}

tr:hover {
  /*highlights rows*/
  background-color: rgba(195, 164, 255, 0.25);
  z-index: -1;
}
tr:hover>td {
  position:relative;
}
tr:hover>td::before {
  /*highlights columns*/
  background-color: rgba(195, 164, 255, 0.9);
  content: "";
  position:absolute;
  top:0px;
  left:0px;
  width: 100%;
  height: 100%;
  z-index: -1;
}
<table>
  <tr>
    <th>Time</th>
    <th>Monday</th>
    <th>Tuesday</th>
    <th>Wednesday</th>
    <th>Thursday</th>
    <th>Friday</th>
    <th>Saturday</th>
    <th>Sunday</th>
  </tr>

  <tr>
    <th>0900-1000</th>
    <td></td>
    <td></td>
    <td></td>
    <td></td>
    <td></td>
    <td>Jia</td>
    <td>Jesse</td>
  </tr>

  <tr>
    <th>1000-1100</th>
    <td></td>
    <td></td>
    <td></td>
    <td></td>
    <td></td>
    <td>Jia</td>
    <td>Kaidan</td>
  </tr>
</table>

Highlight only the td when on hover with pseudo-elements:

table {
  border: 1px solid black;
  border-collapse: collapse;
  /*no borders*/
  width: 75%;
  margin-left: auto;
  margin-right: auto;
  font-family: "Gill Sans", sans-serif;
  z-index: 1;
  /*table is over the highlight*/
  overflow: hidden;
  /*cuts off the column highlight as to not overflow*/
}

tr:hover {
  /*highlights rows*/
  background-color: rgba(195, 164, 255, 0.25);
  z-index: -1;
}

tr:hover>td {
  position: relative;
}

td:hover::before {
  /*highlights columns*/
  background-color: rgba(195, 164, 255, 0.9);
  content: "";
  position: absolute;
  top: 0px;
  left: 0px;
  width: 100%;
  height: 100%;
  z-index: -1;
}
<table>
  <tr>
    <th>Time</th>
    <th>Monday</th>
    <th>Tuesday</th>
    <th>Wednesday</th>
    <th>Thursday</th>
    <th>Friday</th>
    <th>Saturday</th>
    <th>Sunday</th>
  </tr>

  <tr>
    <th>0900-1000</th>
    <td></td>
    <td></td>
    <td></td>
    <td></td>
    <td></td>
    <td>Jia</td>
    <td>Jesse</td>
  </tr>

  <tr>
    <th>1000-1100</th>
    <td></td>
    <td></td>
    <td></td>
    <td></td>
    <td></td>
    <td>Jia</td>
    <td>Kaidan</td>
  </tr>
</table>

In both examples with pseudo-elements, notice the index: -1, so it's placed underneath. Also you need to add a position: relative to the td. ::before or ::after are position: absolute, so when top,left,right, or bottom of the pseudo-element, it is placed relatively to the td container and doesn't get off the "flow" of the container. See this example without position: relative on the td, where the pseudo-element is positioned to the top of the page and is actually the full width and height (similar to your code):

table {
  border: 1px solid black;
  border-collapse: collapse;
  /*no borders*/
  width: 75%;
  margin-left: auto;
  margin-right: auto;
  font-family: "Gill Sans", sans-serif;
  z-index: 1;
  /*table is over the highlight*/
  overflow: hidden;
  /*cuts off the column highlight as to not overflow*/
}

tr:hover {
  /*highlights rows*/
  background-color: rgba(195, 164, 255, 0.25);
  z-index: -1;
}
tr:hover>td::before {
  /*highlights columns*/
  background-color: rgba(195, 164, 255, 0.9);
  content: "";
  position:absolute;
  top:0px;
  left:0px;
  width: 100%;
  height: 100%;
  z-index: -1;
}
<table>
  <tr>
    <th>Time</th>
    <th>Monday</th>
    <th>Tuesday</th>
    <th>Wednesday</th>
    <th>Thursday</th>
    <th>Friday</th>
    <th>Saturday</th>
    <th>Sunday</th>
  </tr>

  <tr>
    <th>0900-1000</th>
    <td></td>
    <td></td>
    <td></td>
    <td></td>
    <td></td>
    <td>Jia</td>
    <td>Jesse</td>
  </tr>

  <tr>
    <th>1000-1100</th>
    <td></td>
    <td></td>
    <td></td>
    <td></td>
    <td></td>
    <td>Jia</td>
    <td>Kaidan</td>
  </tr>
</table>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1