The Scaring Table

Being semantic matters.

cover

The Scaring Table

Imaging that you have a figma design like the poster of this article. How do you implement it? As a fundamentalism, I insist it does have to be the semantic <table> tag. So the problem is, how do we draw a table like this with table element?

I have always been afraid of the table element. The display: table; is a black box to me , but it turns out that in most circumstances,

It "works".

What is this Table Like

First of all, let's conclude our specifications:

That's all, looks easy-peasy.

border-collapse Comes to Rescue

This is what our first sketch looks like with styles

table {
    border: 1px solid #D7D7E4;
    border-radius: 8px;
    & th {
        border-bottom: 1px solid #B0B0CD;
    }
    & td {
        border-bottom: 1px solid #D7D7E4;
    }
}
Date timeUserEvent
22th May at 8AMWinter Whitehurstadded the Quizz component
30th April at 1PMMiguel Steelepublished “Name” (Subsection)
1st Febuary at 8AMWinter Whitehurstedited the Tick a new “country”
9th January at 3PMCaleb Jensendeleted “Username” to the course team
5th January at 10AMWinter Whitehurstdeleted “badge name” to “sub-section name”

It almost works, except an obvious problem: the border of the last row is overlapping with the border of the table.

The direct solution is to remove the border of the last row by changing the selector from & td to & tr:not(:last-child) td. But it's a workaround instead of a solution because it's too specific and ugly.

Something interesting is that you may notice that even in the Figma design, the careless designer forgot to remove the "redundant" border of the last row. It's quiet a common issue, when an issue comes common enough, the standard is supposed to have corresponding solutions.

And the answer is border-collapse. According to border-collapse - CSS: Cascading Style Sheets | MDN

The border-collapse CSS property sets whether cells inside a <table> have shared or separate borders.

And this looks like what we need:

table {
    border-collapse: collapse;
}
Date timeUserEvent
22th May at 8AMWinter Whitehurstadded the Quizz component
30th April at 1PMMiguel Steelepublished “Name” (Subsection)
1st Febuary at 8AMWinter Whitehurstedited the Tick a new “country”
9th January at 3PMCaleb Jensendeleted “Username” to the course team
5th January at 10AMWinter Whitehurstdeleted “badge name” to “sub-section name”

Ahh, it resolves the problem of the last row, but a new problem arises: the rounded corners are gone. Because the border-collapse property is incompatible with border-radius.

But we are not going back, border-collapse: collapse; looks reasonable. We will found another way to make the corners work.

outline as Border

Since the border is not working, another way to draw the border is to use outline. According to CSS Basic User Interface Module Level 4

The outline created with the outline properties is drawn "over" a box, i.e., the outline is always on top and doesn’t influence the position or size of the box, or of any other boxes. Therefore, displaying or suppressing outlines does not cause reflow.

...

User agents should use an algorithm for determining the outline that encloses a region appropriate for conveying the concept of focus to the user.

In short, outline is a border that doesn't affect the layout of the element. Since table have no specific interactive behavior, it's safe to use outline as a border.

At the same time, we will make our border hidden to make the collapsed border invisible. And finally we got the solution:

table {
    border: hidden;
    border-radius: 8px;
    border-collapse: collapse;
    outline: 1px solid #D7D7E4;

    & th {
        border-bottom: 1px solid #B0B0CD;
    }
    & td {
        border-bottom: 1px solid #D7D7E4;
    }
}
Date timeUserEvent
22th May at 8AMWinter Whitehurstadded the Quizz component
30th April at 1PMMiguel Steelepublished “Name” (Subsection)
1st Febuary at 8AMWinter Whitehurstedited the Tick a new “country”
9th January at 3PMCaleb Jensendeleted “Username” to the course team
5th January at 10AMWinter Whitehurstdeleted “badge name” to “sub-section name”

Caveats

It looks good to me now. But actually, there is a problem under the hood. What if we want the header to have a different background color?

tabel thead tr {
    background-color: #e0f5ff;
}
Date timeUserEvent
22th May at 8AMWinter Whitehurstadded the Quizz component
30th April at 1PMMiguel Steelepublished “Name” (Subsection)
1st Febuary at 8AMWinter Whitehurstedited the Tick a new “country”
9th January at 3PMCaleb Jensendeleted “Username” to the course team
5th January at 10AMWinter Whitehurstdeleted “badge name” to “sub-section name”

It won't take too much effort to notice the background overflowed to the border.

Date timeUserEvent
22th May at 8AMWinter Whitehurstadded the Quizz component
30th April at 1PMMiguel Steelepublished “Name” (Subsection)
1st Febuary at 8AMWinter Whitehurstedited the Tick a new “country”
9th January at 3PMCaleb Jensendeleted “Username” to the course team
5th January at 10AMWinter Whitehurstdeleted “badge name” to “sub-section name”

It originates from the incompatibility between border-collapse and border-radius. (Which somehow means outline is indeed a workaround instead of a solution.)

And this time, I come out with no other ways but a workaround:

tabel thead tr {
    & th:first-child {
        border-top-left-radius: 8px;
    }
    & th:last-child {
        border-top-right-radius: 8px;
    }
}
Date timeUserEvent
22th May at 8AMWinter Whitehurstadded the Quizz component
30th April at 1PMMiguel Steelepublished “Name” (Subsection)
1st Febuary at 8AMWinter Whitehurstedited the Tick a new “country”
9th January at 3PMCaleb Jensendeleted “Username” to the course team
5th January at 10AMWinter Whitehurstdeleted “badge name” to “sub-section name”

A "good" news is that even had we chosen the workaround to hide the border of the last row, we will still come into this problem and even the same workaround.

That's why I hate workarounds, it always brings more workarounds.

Published

Tags

CSSWorkbook