tables – CSS-Tricks https://css-tricks.com Tips, Tricks, and Techniques on using Cascading Style Sheets. Tue, 10 Jan 2023 15:11:24 +0000 en-US hourly 1 https://wordpress.org/?v=6.2.2 https://i0.wp.com/css-tricks.com/wp-content/uploads/2021/07/star.png?fit=32%2C32&ssl=1 tables – CSS-Tricks https://css-tricks.com 32 32 45537868 Faking Min Width on a Table Column https://css-tricks.com/faking-min-width-on-a-table-column/ https://css-tricks.com/faking-min-width-on-a-table-column/#comments Tue, 10 Jan 2023 15:11:20 +0000 https://css-tricks.com/?p=376307 The good ol’ <table> tag is the most semantic HTML for showing tabular data. But I find it very hard to control how the table is presented, particularly column widths in a dynamic environment where you might not know how …


Faking Min Width on a Table Column originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
The good ol’ <table> tag is the most semantic HTML for showing tabular data. But I find it very hard to control how the table is presented, particularly column widths in a dynamic environment where you might not know how much content is going into each table cell. In some cases, one column is super wide while others are scrunched up. Other times, we get equal widths, but at the expense of a column that contains more content and needs more space.

But I found a CSS tricks-y workaround that helps make things a little easier. That’s what I want to show you in this post.

The problem

First we need to understand how layout is handled by the browser. We have the table-layout property in CSS to define how a table should distribute the width for each table column. It takes one of two values:

  • auto (default)
  • fixed

Let us start with a table without defining any widths on its columns. In other words, we will let the browser decide how much width to give each column by applying table-layout: auto on it in CSS. As you will notice, the browser does its best with the algorithm it has to divide the full available width between each column.

If we swap out an auto table layout with table-layout: fixed, then the browser will merely divide the full available space by the total number of columns, then apply that value as the width for each column:

But what if we want to control the widths of our columns? We have the <colgroup> element to help! It consists of individual <col> elements we can use to specify the exact width we need for each column. Let’s see how that works in with table-layout: auto:

I have inlined the styles for the sake of illustration.

The browser is not respecting the inline widths since they exceed the amount of available table space when added up. As a result, the table steals space from the columns so that all of the columns are visible. This is perfectly fine default behavior.

How does <colgroup> work with table-layout: fixed. Let’s find out:

This doesn’t look good at all. We need the column with a bunch of content in it to flex a little while maintaining a fixed width for the rest of the columns. A fixed table-layout value respects the width — but so much so that it eats up the space of the column that needs the most space… which is a no-go for us.

This could easily be solved if only we could set a min-width on the column instead of a width. That way, the column would say, “I can give all of you some of my width until we reach this minimum value.“ Then the table would simply overflow its container and give the user a horizontal scroll to display the rest of the table. But unfortunately, min-width on table columns are not respected by the <col> element.

The solution

The solution is to fake a min-width and we need to be a bit creative to do it.

We can add an empty <col> as the second column for our <colgroup> in the HTML and apply a colspan attribute on the first column so that the first column takes up the space for both columns:


<table>
  <colgroup>
    <col class="col-200" />
    <col />
    <col class="col-input" />
    <col class="col-date" />
    <col class="col-edit" />
  </colgroup>
  
  <thead>
    <tr>
      <th colspan="2">Project name</th>
      <th>Amount</th>
      <th>Date</th>
      <th>Edit</th>
    </tr>
  </thead>
  
  <!-- etc. -->
</table>

Note that I have added classes in place of the inline styles from the previous example. The same idea still applies: we’re applying widths to each column.

The trick is that relationship between the first <col> and the empty second <col>. If we apply a width to the first <col> (it’s 200px in the snippet above), then the second column will be eaten up when the fixed table layout divides up the available space to distribute to the columns. But the width of the first column (200px) is respected and remains in place.

Voilà! We have a faux min-width set on a table cell. The first cell flexes as the available space changes and the table overflows for horizontal scrolling just as we hoped it would.

(I added a little sticky positioning to the first column there.)

Accessibility

Let’s not totally forget about accessibility here. I ran the table through NVDA on Windows and VoiceOver on macOS and found that all five columns are announced, even if we’re only using four of them. And when the first column is in focus, it announces, “Column one through two”. Not perfectly elegant but also not going to cause someone to get lost. I imagine we could throw an aria-hidden attribute on the unused column, but also know ARIA isn’t a substitute for poor HTML.


I’ll admit, this feels a little, um, hacky. But it does work! Let me know if you have a different approach in the comments… or know of any confusions this “hack” might bring to our users.


Faking Min Width on a Table Column originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/faking-min-width-on-a-table-column/feed/ 5 376307
TablesNG — Improvements to table rendering in Chromium https://css-tricks.com/tablesng-improvements-to-rendering-in-chromium/ https://css-tricks.com/tablesng-improvements-to-rendering-in-chromium/#comments Wed, 23 Jun 2021 21:37:14 +0000 https://css-tricks.com/?p=343076 When I blogged “Making Tables With Sticky Header and Footers Got a Bit Easier” recently, I mentioned that the “stickiness” improvement was just one of the features that got better for <table>s in Chrome as part of the TablesNG upgrade


TablesNG — Improvements to table rendering in Chromium originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
When I blogged “Making Tables With Sticky Header and Footers Got a Bit Easier” recently, I mentioned that the “stickiness” improvement was just one of the features that got better for <table>s in Chrome as part of the TablesNG upgrade. I ain’t the only one who’s stoked about it.

But Bramus took it the rest of the nine yards and looked at all of the table enhancements. Every one of these is great. The kind of thing that makes CSS ever-so-slightly less frustrating.

Just the writing-mode stuff is fantastic.

To Shared LinkPermalink on CSS-Tricks


TablesNG — Improvements to table rendering in Chromium originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/tablesng-improvements-to-rendering-in-chromium/feed/ 2 343076
A table with both a sticky header and a sticky first column https://css-tricks.com/a-table-with-both-a-sticky-header-and-a-sticky-first-column/ https://css-tricks.com/a-table-with-both-a-sticky-header-and-a-sticky-first-column/#comments Wed, 10 Feb 2021 01:06:47 +0000 https://css-tricks.com/?p=333880 We’ve covered that individual <table> cells, <th> and <td> can be position: sticky. It’s pretty easy to make the header of a table stick to the top of the screen while scrolling through a bunch or rows (like this


A table with both a sticky header and a sticky first column originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
We’ve covered that individual <table> cells, <th> and <td> can be position: sticky. It’s pretty easy to make the header of a table stick to the top of the screen while scrolling through a bunch or rows (like this demo).

But stickiness isn’t just for the top of the screen, you can stick things in any scroll direction (horizontal is just as fun). In fact, we can have multiple sticky elements stuck in different directions inside the same element, and even single elements that are stuck in multiple directions.

Here’s a video example of a table that sticks both the header and first column:

Why would you do that? Specifically for tabular data where cross-referencing is the point. In this table (which represents, of course, the scoring baseball game where somehow 20 teams are all playing each other at once because that’s how baseball works), it “makes sense” that you wouldn’t want the team name or the inning number to scroll away, as you’d lose context of what you’re looking at.

Not all tables need to be bi-directionally cross-referenceable. A lot of tables can smash rows into blocks on small screens for a better small-screen experience.

The “trick” at play here is partially the position: sticky; usage, but moreso to me, how you have to handle overlapping elements. A table cell that is sticky needs to have a background, because otherwise we’ll see overlapping content. It also needs proper z-index handling so that when it sticks in place, it’ll be on top of what it is supposed to be on top of. This feels like the trickiest part:

  • Make sure the tbody>th cells are above regular table cells, so they stay on top during a horizontal scroll.
  • Make sure the thead>th cells are above those, for vertical scrolling.
  • Make sure the thead>th:first-child cell is the very highest, as it needs to be above the body cells and it’s sibling headers again for horizontal scrolling.

A bit of a dance, but it’s doable.

High five to Cameron Clark who emailed me demoed this and showed me how cool it is. And indeed, Cameron, it is cool. When I shared that around, Estelle Weyl showed me a demo she made several years ago. That feels about right, Estelle is always a couple of years ahead of me.


A table with both a sticky header and a sticky first column originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/a-table-with-both-a-sticky-header-and-a-sticky-first-column/feed/ 23 333880
In Defense of Tables and Floats in Modern Day Development https://css-tricks.com/in-defense-of-tables-and-floats-in-modern-day-development/ https://css-tricks.com/in-defense-of-tables-and-floats-in-modern-day-development/#comments Fri, 30 Oct 2020 14:44:15 +0000 https://css-tricks.com/?p=324289 Twenty-plus years ago, tables were the main way web pages were created in HTML. It gave web builders consistent control of constructing pages with some “design.” No longer did sites only have to be top-to-bottom in a linear manner — …


In Defense of Tables and Floats in Modern Day Development originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Twenty-plus years ago, tables were the main way web pages were created in HTML. It gave web builders consistent control of constructing pages with some “design.” No longer did sites only have to be top-to-bottom in a linear manner — they could be set up with columns that align left-to-right and top-to-bottom. Back then, it was seen as a huge breakthrough.

Tables, however, were never designed to lay out pages and, in fact, have all sorts of problems when used that way today. It was a convenient hack, but at the time, a very welcome one, particularly for those trying to achieve a super-specific layout that previous ways couldn’t handle.

Fast-forward to modern days and it’s now obvious that were tons of issues with the table layout approach. Accessibility is a big one.<table>, <th>, <tr> and <td> elements aren’t exactly accessible, especially when they’re nested several levels deep. Screen readers — the devices that read web content and serve as a measure of accessibility compliance — struggle to parse them into cohesive blocks of content. That’s not to say tables are bad; they simply were never intended as a layout mechanism.

Check out this table layout. Feel free to run it through VoiceOver or whatever screen reading software you have access to.

Yes, that example looks very much like a typical website layout, but it’s crafted solely with a table. You can see how quickly it becomes bloated and inaccessible the very moment we start using it for anything other than tabular data.

So after more than 20 years of being put through the ringer, you might think we should avoid tables altogether. If you’ve never shipped a table-based layout, you’ve undoubtedly heard war stories from those of us who have, and those stories are never kind. It’s like we’ve sort of made tables the “Internet Explorer of HTML elements.”

But that’s not totally fair because tables do indeed fill a purpose on the web and they are indeed accessible when they are used correctly.

Tables are designed to handle data that is semantically related and is best presented in a linear-like format. So, yes, we can use tables today in the year 2020, and that will likely continue to be true many years from now.

Here’s a table being used to display exactly what it’s intended to: tabular data!

With the push toward web standards in the early 2000s, tables were pushed aside as a layout solution in favor of other approaches, most notably the CSS float property. Designers and developers alike rejoiced because, for the first time, we had a true separation of concerns that let markup do the markup-y things it needs to do, and CSS to do the visual stuff it needs to do. That made code both cleaner and way easier to maintain and, as a result, we could actually focus on true standards, like accessibility, and even other practices, like SEO.

See (or rather hear) the difference in this example?

Many of us have worked with floats in the past. They were originally designed to allow content to flow around images that are floated either to the left or right, and still be in the document flow. Now that we’ve gotten newer layout features — again, like grid and flexbox — floats, too, have sort of fallen by the wayside, perhaps either because there are better ways to accomplish what they do, or because they also got the same bad rap as tables after being (ab)used for a long time.

But floats are still useful and relevant! In fact, we have to use them for the shape-outside property to work.

A legitimate float use case could be for wrapping content around a styled <blockquote>.

CSS features like grid, flexbox, and multicolumn layouts are among the wonderful tools we have to work with these days. With even more layout possibilities, cleaner and more accessible code, they will remain our go-to layout approaches for many years to come.

No hacks or extra code in this flexbox example of the same layout we’ve looked at throughout this article:


So, next time you find yourself considering tables or floats, reach for them with confidence! Well, when you know the situation aligns with their intended use. It’s not like I’m expecting you to walk away from this with a reinvigorated enthusiasm for tables and floats; only that, when used correctly, they are perfectly valid techniques, and even continue to be indispensable parts of our overall toolset.


In Defense of Tables and Floats in Modern Day Development originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/in-defense-of-tables-and-floats-in-modern-day-development/feed/ 9 324289
Rotated Table Column Headers… Now With Fewer Magic Numbers! https://css-tricks.com/rotated-table-column-headers-now-with-fewer-magic-numbers/ https://css-tricks.com/rotated-table-column-headers-now-with-fewer-magic-numbers/#comments Mon, 01 Jun 2020 14:43:37 +0000 https://css-tricks.com/?p=311036 Rotated <table> column headers is something that’s been covered before right here on CSS-Tricks, so shout-out to that for getting me started and helping me achieve this effect. As the article points out, if you aren’t using trigonometry to calculate …


Rotated Table Column Headers… Now With Fewer Magic Numbers! originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Rotated <table> column headers is something that’s been covered before right here on CSS-Tricks, so shout-out to that for getting me started and helping me achieve this effect. As the article points out, if you aren’t using trigonometry to calculate your table styles, you’ll have to rely on magic numbers and your table will be brittle and any dreams of responsiveness crushed. 

Fortunately, in this case, we can take the trigonometry out and replace it with some careful geometry and our magic numbers all turn into 0 (a truly magical number).

For those in a hurry, here is the CSS (it’s very similar to the styles in the other article). Below is a thorough walk-through.

<th class="rotate"><div><span>Column Header 1</span></div></th>
table {
 border-collapse: collapse;
 --table-border-width: 1px;
}
th.rotate {
  white-space: nowrap;
  position: relative;

}
th.rotate > div {
  /* place div at bottom left of the th parent */
  position: absolute;
  bottom: 0;
  left: 0;
  /* Make sure short labels still meet the corner of the parent otherwise you'll get a gap */
  text-align: left;
  /* Move the top left corner of the span's bottom-border to line up with the top left corner of the td's border-right border so that the border corners are matched
   * Rotate 315 (-45) degrees about matched border corners */
  transform: 
    translate(calc(100% - var(--table-border-width) / 2), var(--table-border-width))
    rotate(315deg);
  transform-origin: 0% calc(100% - var(--table-border-width));
  width: 100%;

}
th.rotate > div > span {
  /* make sure the bottom of the span is matched up with the bottom of the parent div */
  position: absolute;
  bottom: 0;
  left: 0;
  border-bottom: var(--table-border-width) solid gray;
}
td {
  border-right: var(--table-border-width) solid gray;
  /* make sure this is at least as wide as sqrt(2) * height of the tallest letter in your font or the headers will overlap each other*/
  min-width: 30px;
  padding-top: 2px;
  padding-left: 5px;
  text-align: right;
}

Let’s unpack this table and see what’s going on. The magic starts with that funny chain of HTML tags. We’re putting a <span> inside of a <div> inside of our <th>. Is this all really necessary? Between how borders behave, the positioning flexibility we need, and what determines the width of a table column… yes, they each have a purpose and are necessary.

Let’s see what happens if we rotate the <th> directly:

<th class="rotate">Column header 1</th>
table {
  border-collapse: collapse;
}
th.rotate {
  border-bottom: 1px solid gray;
  transform: rotate(315deg);
  white-space: nowrap;
}
td {
  border-right: 1px solid gray;
  min-width: 30px;
  padding-top: 2px;
  padding-left: 5px;
  text-align: right;
}

Ignoring the fact that we haven’t corrected position, there are two big issues here: 

  1. The column width is still calculated from the header length which is what we were trying to avoid.
  2. Our border didn’t come with us in the rotation, because it is actually part of the table.

These problems aren’t so difficult to fix. We know that if the <th> has a child element with a border, the browser won’t treat that border as part of the table. Further, we know that absolutely-positioned elements are taken out of the document flow and won’t affect the parent’s width. Enter <div> tag, stage left…and right, I guess.

<th class="rotate"><div>Column header 1</div></th>
table {
  border-collapse: collapse;
}
th.rotate {
  white-space: nowrap;
  position: relative;
}
th.rotate > div {
  position: absolute;
  transform: rotate(315deg);
  border-bottom: 1px solid gray;
}
td {
  border-right: 1px solid gray;
  min-width: 30px;
  text-align: right;
  padding-top: 2px;
  padding-left: 5px;
}
Now our headers don’t influence the column width and the borders are rotated. We just need to line things up.

It’s easier to tell in the image with the rotated <th> elements, but that rotation is happening around the center of the element (that’s the default behavior of transform-origin). It is only another transform in x and y to get it to the right spot, but this is where we’d need trigonometry to figure out just how much x and y to line it up with the column borders. If we instead carefully choose the point to rotate the header about, and use transform-origin to select it, then we can end up with distances that are more straightforward than magic numbers.

The animation below helps illustrate what we’re going to do to avoid complicated math. The black dot in the top left of the blue border needs to match the red dot on the right border of the table column and rotate about it. Then there won’t be any gaps between the two borders.

It’s not helpful to start going somewhere if you don’t know where you are. The absolute positioning is going to help us out with this. By specifying bottom: 0; left: 0; on the <div>, it ends up at the bottom left of the parent <th>. This means the <div> border’s bottom-left corner is sitting on top of the left column border and halfway through it. From here, it’s apparent we need to move down one border width and over one cell width, but how are we going to get that responsively? It’s at this very moment you may recall that we haven’t added the <span> yet — we’re going to need it!

We’ll use the <div> to “figure out” how big the table cells are and the <span> to actually hold the text and position it absolutely as well to overflow the parent.

<th class="rotate"><div><span>Column header 1</span></div></th>
th.rotate{
  white-space: nowrap;
  position: relative;
}
th.rotate > div {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;  /* <- now the div parent is as wide as the columns */
}
th.rotate > div > span {
  position: absolute;
  bottom: 0;
  left: 0;
  border-bottom: 1px solid gray;
}

Great! When we set the width of the <div> to 100%, it holds the information for how big the column is regardless of what the content is in the table cells. With this in place, we can easily translate things over by the width of the <div> — but don’t forget that we need to shave off a half border width. Our translation becomes:

transform: translate( calc( 100% - var(--table-border-width)/2), var(--table-border-width));

The <div> is now in the right spot to rotate, but we have to make sure to pick the correct transform-origin. We want it to be on the top-left corner of the border, which will be on the left and up one border’s width from the bottom of our <div> element:

transform-origin: 0%, calc(100% - var(--table-border-width));

This brings us to our final style for the table header.

table {
  border-collapse: collapse;
  --table-border-width: 1px;
}
th.rotate{
  white-space: nowrap;
  position: relative;
}
th.rotate > div {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  transform:
    translate( calc( 100% - var(--table-border-width)/2), var(--table-border-width));
    rotate(315deg);
  transform-origin: 0%, calc(100% - var(--table-border-width));
}
th.rotate > div > span {
  position: absolute;
  bottom: 0;
  left: 0;
  border-bottom: var(--table-border-width) solid gray;
}

Note that transformations happen after everything is placed. That means the rotated headers will overflow onto everything as best they can. You will need to wrap the whole table in something to compensate for the unexpected height. I put the title and table together in a flexbox <div> and set the flex-basis of the title to a value large enough to compensate for the tall headers.

#div-with-table {
  display: flex;
  flex-direction: column;
  justify-content: space-around;
}
#title {
  flex-basis: 140px;
}

Rotated Table Column Headers… Now With Fewer Magic Numbers! originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/rotated-table-column-headers-now-with-fewer-magic-numbers/feed/ 9 311036
Making Tables Responsive With Minimal CSS https://css-tricks.com/making-tables-responsive-with-minimal-css/ https://css-tricks.com/making-tables-responsive-with-minimal-css/#comments Thu, 17 Oct 2019 14:23:48 +0000 https://css-tricks.com/?p=297246 Here’s a fabulous CSS trick from Bradley Taunt in which he shows how to make tables work on mobile with just a little bit of extra code. He styles each table row into a card that looks something like this:…


Making Tables Responsive With Minimal CSS originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Here’s a fabulous CSS trick from Bradley Taunt in which he shows how to make tables work on mobile with just a little bit of extra code. He styles each table row into a card that looks something like this:

See the Pen
Responsive Tables #2.5: Flexbox
by Bradley Taunt (@bradleytaunt)
on CodePen.

(Make sure to grab the Pen and make it a bit smaller to see how the design works responsively.)

Bradley’s example markup looks like this – clean, accessible, regular ol’ HTML:

<table>
  <thead>
    <tr>
      <th>Type of Food</th>
      <th>Calories</th>
      <th>Tasty Factor</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><span>Type of Food</span> Slice of Pizza</td>
      <td><span>Calories</span> 450</td>
      <td><span>Tasty Factor</span> 95%</td>
    </tr>
  </tbody>
</table>

How does he make that card effect? He uses flexbox on smaller screens and sets the span elements to reveal themselves.

However! I’m not a big fan of those spans. They’re hidden on larger screen sizes but the markup is still there, so it doesn’t feel particularly clean to me. I was working on a project a little while ago where we stumbled on the same problem. We decided to use data attributes on each td instead, like this:

<table>
  <thead>
    <tr>
      <th>Type of Food</th>
      <th>Calories</th>
      <th>Tasty Factor</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td data-title="Type of Food">Slice of Pizza</td>
      <td data-title="Calories">450</td>
      <td data-title="Tasty Factor">95%</td>
    </tr>
  </tbody>
</table>

Then we can grab that data attribute in our styles and render it on the page in a pseudo element:

td:before {
  content: attr(data-title);
}

From there we absolutely position the pseudo element to the side and only show it on smaller screens with a media query. I’m uncertain about the accessibility implications of this but it just feels a bit easier to read and understand in my opinion.

Either way, I think this post is a great reminder about all the tricky issues that pop up once you start using tables. There’s so many ways to handle things responsively and those decisions should entirely be made on the context of the design.

To Shared LinkPermalink on CSS-Tricks


Making Tables Responsive With Minimal CSS originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/making-tables-responsive-with-minimal-css/feed/ 2 297246
Table with Expando Rows https://css-tricks.com/table-with-expando-rows/ Fri, 20 Sep 2019 14:17:33 +0000 https://css-tricks.com/?p=296124 “Expando Rows” is a concept where multiple related rows in a <table> are collapsed until you open them. You’d call that “progressive disclosure” in interaction design parlance.

After all these years on CSS-Tricks, I have a little better eye for …


Table with Expando Rows originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
“Expando Rows” is a concept where multiple related rows in a <table> are collapsed until you open them. You’d call that “progressive disclosure” in interaction design parlance.

After all these years on CSS-Tricks, I have a little better eye for what the accessibility concerns of a design/interactivity feature are. I’m not entirely sure how I would have approached this problem myself, but there is a good chance that whatever I would have tried wouldn’t have hit the bullseye with accessibility.

That’s why I’m extra happy when someone like Adrian Roselli tackles problems like this, because the accessibility is handled right up front (see the videos in all the major screen readers).

I feel the same way when we get demos from Scott O’Hara, Lindsey Kopacz, and Hedyon Pickering.

See the Pen
Table with Expando Rows
by Adrian Roselli (@aardrian)
on CodePen.

To Shared LinkPermalink on CSS-Tricks


Table with Expando Rows originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
296124
Position Sticky and Table Headers https://css-tricks.com/position-sticky-and-table-headers/ https://css-tricks.com/position-sticky-and-table-headers/#comments Fri, 12 Jul 2019 22:31:21 +0000 http://css-tricks.com/?p=292192 You can’t position: sticky; a <thead>. Nor a <tr>. But you can sticky a <th>, which means you can make sticky headers inside a regular ol’ <table>. This is tricky stuff, because if you didn’t know …


Position Sticky and Table Headers originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
You can’t position: sticky; a <thead>. Nor a <tr>. But you can sticky a <th>, which means you can make sticky headers inside a regular ol’ <table>. This is tricky stuff, because if you didn’t know this weird quirk, it would be hard to blame you. It makes way more sense to sticky a parent element like the table header rather than each individual element in a row.

The issue boils down to the fact that stickiness requires position: relative to work and that doesn’t apply to <thead> and <tr> in the CSS 2.1 spec.

There are two very extreme reactions to this, should you need to implement sticky table headers and not be aware of the <th> workaround.

  • Don’t use table markup at all. Instead, use different elements (<div>s and whatnot) and other CSS layout methods to replicate the style of a table, but not locked out of using position: relative and creating position: sticky parent elements.
  • Use table elements, but totally remove all their styling defaults with new display values.

The first is dangerous because you aren’t using semantic and accessible elements for the content to be read and navigated. The second is almost the same. You can go that route, but need to be really careful to re-apply semantic roles.

Anyway, none of that matters if you just stick (get it?!) to using a sticky value on those <th> elements.

See the Pen
Sticky Table Headers with CSS
by Chris Coyier (@chriscoyier)
on CodePen.

It’s probably a bit weird to have table headers as a row in the middle of a table, but it’s just illustrating the idea. I was imagining colored header bars separating players on different sports teams or something.

Anytime I think about data tables, I also think about how tricky it can be to make them responsive. Fortunately, there are a variety of ways, all depending on the best way to group and explore the data in them.


Position Sticky and Table Headers originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/position-sticky-and-table-headers/feed/ 18 292192
Table design patterns on the web https://css-tricks.com/table-design-patterns-on-the-web/ https://css-tricks.com/table-design-patterns-on-the-web/#comments Mon, 28 Jan 2019 16:29:24 +0000 http://css-tricks.com/?p=281855 Chen Hui Jing has tackled a ton of design patterns for tables that might come in handy when creating tables that are easy to read and responsive for the web:

There are a myriad of table design patterns out there,


Table design patterns on the web originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Chen Hui Jing has tackled a ton of design patterns for tables that might come in handy when creating tables that are easy to read and responsive for the web:

There are a myriad of table design patterns out there, and which approach you pick depends heavily on the type of data you have and the target audience for that data. At the end of the day, tables are a method for the organisation and presentation of data. It is important to figure out which information matters most to your users and decide on an approach that best serves their needs.

This reminds me of way back when Chris wrote about responsive data tables and just how tricky they are to get right. Also there’s a great post by Richard Rutter in a similar vein where he writes about the legibility of tables and fine typography:

Many tables, such as financial statements or timetables, are made up mostly of numbers. Generally speaking, their purpose is to provide the reader with numeric data, presented in either columns or rows, and sometimes in a matrix of the two. Your reader may use the table by scanning down the columns, either searching for a data point or by making comparisons between numbers. Your reader may also make sense of the data by simply glancing at the column or row. It is far easier to compare numbers if the ones, tens and hundreds are all lined up vertically; that is, all the digits should occupy exactly the same width.

One of my favorite table patterns that I now use consistently is one with a sticky header. Like this demo here:

See the Pen
Table Sticky Header
by Robin Rendle (@robinrendle)
on CodePen.

As a user myself, I find that when I’m scrolling through large tables of data with complex information, I tend to forget what one column is all about and then I’ll have to scroll all the way back up to the top again to read the column header.

Anyway, all this makes me think that I would read a whole dang book on the subject of the <table> element and how to design data accurately and responsively.

To Shared LinkPermalink on CSS-Tricks


Table design patterns on the web originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/table-design-patterns-on-the-web/feed/ 2 281855
An Idea for a Simple Responsive Spreadsheet https://css-tricks.com/idea-simple-responsive-spreadsheet/ https://css-tricks.com/idea-simple-responsive-spreadsheet/#comments Tue, 28 Nov 2017 19:02:52 +0000 http://css-tricks.com/?p=262902 How do you make a spreadsheet-like interface responsive without the use of any JavaScript? This is the question I’ve been asking myself all week as I’ve been working on a new project and trying to figure out how to make …


An Idea for a Simple Responsive Spreadsheet originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
How do you make a spreadsheet-like interface responsive without the use of any JavaScript? This is the question I’ve been asking myself all week as I’ve been working on a new project and trying to figure out how to make the simplest spreadsheet possible. I wanted to avoid using a framework and instead, I decided to experiment with some new properties in order to use nothing but a light touch of CSS.

Spoilers! This is what I’ve come up with so far (oh and please note that this demo currently works in the latest version of Chrome). Try scrolling around a little bit:

See the Pen A Simple Responsive Spreadsheet – Final by Robin Rendle (@robinrendle) on CodePen.

Notice how the first column sticks to the left and the heading sticks to the top of the spreadsheet? This lets us scan lots of data without having to keep scrolling to figure out which column or row we’re in — in a lot of interfaces like this it’s pretty easy to get lost.

So how did I go about making this thing? Let’s jump in!

Adding the markup

First we need to add our markup for the table and, just to make sure that this example is as realistic as possible, we’re going to add a lot of rows and columns here:

See the Pen A Simple Responsive Spreadsheet – 1st by Robin Rendle (@robinrendle) on CodePen.

There’s nothing really complex going on. We just have a regular ol’ table with a <thead> and a <tbody>, but we do wrap the whole table in the table-wrapper div which I’ll explain in just a little bit.

Next, we’ll add basic styling to that wrapper element to move it into the center of the page and also give it a max-width. We also need to make sure that the .table-wrapper has overflow set to scroll, although at larger screen sizes we won’t need that just yet:

body {
  display: flex;
  font-family: -apple-system;
  font-size: 90%;
  color: #333;
  justify-content: center;
}

.table-wrapper {
  max-width: 700px;
  overflow: scroll;
}

See the Pen A Simple Responsive Spreadsheet – 2nd by Robin Rendle (@robinrendle) on CodePen.

Nifty! Now we can add styles for the first column of our table and the thead element as well as basic styling for each of the table cells:

table {
  border: 1px solid #ddd;
  border-collapse: collapse;
}

td, th {
  white-space: nowrap;
  border: 1px solid #ddd;
  padding: 20px;
}

See the Pen A Simple Responsive Spreadsheet – 3 by Robin Rendle (@robinrendle) on CodePen.

The problem here is that we’ve now made a pretty inaccessible table; although we can scroll around in the spreadsheet we can’t read which column or row is associated to which bit of data. This can lead to a table that is almost completely illegible and if we were to populate this with real data then it would be even worse:

position: sticky to the rescue!

position: sticky is a wonderfully handy CSS trick that I’ve started experimenting with a great deal lately. It lets you stick child elements to their parent containers so that as you scroll around the child element is always visible. And this is exactly what we need here for the first column and the heading of our table element.

We can use this relatively new feature with CSS like this:

// The heading of our table
th {
  background-color: #eee;
  position: sticky;
  top: -1px;
  z-index: 2;
  
  // The first cell that lives in the top left of our spreadsheet
  &:first-of-type {
    left: 0;
    z-index: 3;
  }
}

// The first column that we want to stick to the left
tbody tr td:first-of-type {
  background-color: #eee;
  position: sticky;
  left: -1px;
  z-index: 1;
}

This z-index values are important here because we want the header to overlap the first left hand column that will also be sticky. However! We also want that empty cell at the top left to overlap both our header and our left hand column, like this:

See the Pen A Simple Responsive Spreadsheet – Final by Robin Rendle (@robinrendle) on CodePen.

But there we have it! A simple responsive spreadsheet where you can view both the heading and the first column no matter where you are in the table. Although, it’s worth noting that your mileage may vary. position: sticky has relatively patchy support right now and so it’s worth thoroughly testing before you start using it. Or you could use something like Stickybits that would act as a lightweight polyfill.

Also, if you need to dig into tables in more depth then we’ve made a rather handy Complete Guide to the Table Element.


An Idea for a Simple Responsive Spreadsheet originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/idea-simple-responsive-spreadsheet/feed/ 6 262902
Designing Tables to be Read, Not Looked At https://css-tricks.com/designing-tables-read-not-looked/ Tue, 07 Nov 2017 14:52:22 +0000 http://css-tricks.com/?p=262294 Richard Rutter, in support of his new book Web Typography, shares loads of great advice on data table design. Here’s a good one:

You might consider making all the columns an even width. This too does nothing for the


Designing Tables to be Read, Not Looked At originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Richard Rutter, in support of his new book Web Typography, shares loads of great advice on data table design. Here’s a good one:

You might consider making all the columns an even width. This too does nothing for the readability of the contents. Some table cells will be too wide, leaving the data lost and detached from its neighbours. Other table cells will be too narrow, cramping the data uncomfortably. Table columns should be sized according to the data they contain.

I was excited to be reminded of the possibility for aligning numbers with decimals:

td { text-align: "." center; }

But the support for that is non-existent as best I can tell. Another tip, using font-variant-numeric: lining-nums tabular-nums; does have some support.

Tables can be beautiful but they are not works of art. Instead of painting and decorating them, design tables for your reader.

To Shared LinkPermalink on CSS-Tricks


Designing Tables to be Read, Not Looked At originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
262294
The Media Object, A Bunch of Ways https://css-tricks.com/media-object-bunch-ways/ https://css-tricks.com/media-object-bunch-ways/#comments Sat, 28 Jan 2017 19:10:49 +0000 http://css-tricks.com/?p=250642 The Media Object pattern is: image thingy on the left, heading and text on the right.

That’s what Nicole Sullivan called it and the name stuck. It’s a pretty simple pattern, but like all things web design, it can …


The Media Object, A Bunch of Ways originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
The Media Object pattern is: image thingy on the left, heading and text on the right.

That’s what Nicole Sullivan called it and the name stuck. It’s a pretty simple pattern, but like all things web design, it can be done many ways.

Bootstrap’s version, which uses table layout in v3 and flexbox in v4.

Let’s take a crack at a lot of those ways. In these demos, I’m not particularly focusing on naming conventions, semantics, or browser support. Just possibilities.

With Floats

Certainly, we could float the image to the left!

See the Pen Media Block #1 by Chris Coyier (@chriscoyier) on CodePen.

But just floating means you get wrapping. Wrapping might be perfectly fine, or you might not want it.

I’d say in the typical media object pattern, there is no wrapping.

To fix that, we could make sure all the text is wrapped in an element, then make sure that element has padding-left equal to the width of the image and any white space between them.

See the Pen Media Block #2 by Chris Coyier (@chriscoyier) on CodePen.

Or, you could float both sides:

See the Pen Media Block #3 by Chris Coyier (@chriscoyier) on CodePen.

With Flexbox

Flexbox makes quick work of it!

See the Pen Media Block #4 by Chris Coyier (@chriscoyier) on CodePen.

Note that we’re allowing the <img> to become a flex item. We used align-items: flex-start; to make sure it doesn’t stretch out to the same height as the text.

With Tables

The media object could be a two-cell row of a table:

See the Pen Media Block #5 by Chris Coyier (@chriscoyier) on CodePen.

If you wanted to keep non-<table> markup, it’s still possible to make it behave like a table via display: table;:

See the Pen Media Block #6 by Chris Coyier (@chriscoyier) on CodePen.

With Grid

Grid layout allows us to define a set of columns. It’s quite easy to set up the first column to the fixed width we want, and the second column to take up the rest of the space.

See the Pen Media Block #7 by Chris Coyier (@chriscoyier) on CodePen.

Like in flexbox, we can avoid the image stretching itself out by aligning it to the top with align-self: start;.


I’m sure y’all can find about a dozen more ways to do it!


The Media Object, A Bunch of Ways originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/media-object-bunch-ways/feed/ 11 250642
4 Ways to Make a Table With Borders Only On The Inside (Tic-Tac-Toe Style) https://css-tricks.com/table-with-borders-only-on-the-inside/ https://css-tricks.com/table-with-borders-only-on-the-inside/#comments Sat, 21 Jan 2017 16:56:36 +0000 http://css-tricks.com/?p=250283 Wondering how you can make a Table With Borders only on the inside with CSS? Here's four different ways, all with their upsides and downsides. It's very doable.


4 Ways to Make a Table With Borders Only On The Inside (Tic-Tac-Toe Style) originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
You know, like a tic-tac-toe board. I was just pondering how to make a table with borders only on the inside the other day, as one does. There are three ways I can think of. One involves a good handful of rules and is the way I intuitively think of, one involves a deprecated attribute, and one is very simple and feels kinda like a CSS trick.

Tic Tac Toe boards have are an example of a Table With Borders Only On The Inside.

Possibility #1) Removing the Borders You Don’t Need

This is the first way I think of. Add a border everywhere, then remove the border on the:

  1. The top of every cell in the first row
  2. The bottom of every cell in the last row
  3. The left of the first cell in every row
  4. The right of last cell in every row
table {
  border-collapse: collapse;
}
table td {
  border: 5px solid black; 
}
table tr:first-child td {
  border-top: 0;
}
table tr td:first-child {
  border-left: 0;
}
table tr:last-child td {
  border-bottom: 0;
}
table tr td:last-child {
  border-right: 0;
}

Possibility #2) The rules Attribute

This is not recommended as it’s a deprecated attribute. But, that’s what the rules attribute was specifically for.

You can control the color with border-color, but not border-width or border-style.

Possibility #3) Using border-style: hidden;

This is the one that feels like a CSS trick to me.

table {
  border-collapse: collapse;
  border-style: hidden;
}
table td {
  border: 5px solid black;
}

MDN has an explanation:

In case of table cell and border collapsing, the hidden value has the highest priority: it means that if any other conflicting border is set, it won’t be displayed.

By putting border-style: hidden; on the table itself, it means that “hidden” wins on that outside edge, but only the outside edge, not any of the other borders on the inside cells.

Possibility #4: Use the outline property

Carter Li wrote about this then challenged me:

Maybe something like this tic-tac-toe board Chris put together several years ago could benefit from outline, instead of resorting to individually-crafted cell borders. Challenge accepted, Mr. Coyier? 😉

Gotta step to that challenge! Looks like thanks to outline-offset it can be done!

table {
  outline: 2px solid white;
  outline-offset: -2px;
}
table td {
  outline: 2px solid black;
}

Possibility #5: Gradients

Bonus! Temani Afif cooked up a way to do it with a singular conic gradient. It blows my mind so I won’t attempt to explain it.


Can you think of other ways?


4 Ways to Make a Table With Borders Only On The Inside (Tic-Tac-Toe Style) originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/table-with-borders-only-on-the-inside/feed/ 8 250283
table-layout https://css-tricks.com/almanac/properties/t/table-layout/ Wed, 04 Jan 2017 13:12:01 +0000 http://css-tricks.com/?page_id=249476 The table-layout property defines what algorithm the browser should use to lay out table rows, cells, and columns.

table {
  table-layout: fixed;
}

As explained in the CSS2.1 specification, table layout in general is usually a matter of taste …


table-layout originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
The table-layout property defines what algorithm the browser should use to lay out table rows, cells, and columns.

table {
  table-layout: fixed;
}

As explained in the CSS2.1 specification, table layout in general is usually a matter of taste and will vary depending on design choices. Browsers will, however, automatically apply certain constraints that will define how tables are laid out. This happens when the table-layout property is set to auto (the default). But these constraints can be lifted when table-layout is set to fixed.

Values

  • auto: the default. The browser’s automatic algorithm is used to define how a table’s rows, cells, and columns are laid out. The resulting table layout is generally dependent on the content of the table.
  • fixed: With this value, the table’s layout ignores the content and instead uses the table’s width, any specified width of columns, and border and cell spacing values. The column values used are based on widths defined on columns or cells for the first row of the table.
  • inherit: indicates that the value is inherited from the table-layout value of its parent

In order for a value of fixed to have any effect, the table’s width has to be set to something other than auto (the default for the width property). In the demos below, all the table widths are set to 100%, which assumes we want the table to fill its parent container horizontally.

The best way to see the the effects of a fixed table layout algorithm is using a demo.

See the Pen Demo for CSS’s table-layout property by Louis Lazaris (@impressivewebs) on CodePen.

When you first view the above demo, you’ll notice the layout of the table columns is unbalanced and awkward. At that point, the table is using the browser’s default algorithm to define how to lay out the table, which means the content will dictate the layout. The demo exaggerates this fact by including a long string of text inside one table cell, while all the other table cells use just two words each. As you can see, the browser expands the first column to accommodate the larger bit of content.

If you click the “Toggle table-layout: fixed” button, you’ll see what the table layout looks like when the “fixed” algorithm is used. When table-layout: fixed is applied, the content no longer dictates the layout, but instead, the browser uses any defined widths from the table’s first row to define column widths. If no widths are present on the first row, the column widths are divided equally across the table, regardless of content inside the cells.

Further examples may help make this clearer. In the following demo, the table has a <colgroup> element whose first <col> element has a width of 400px. Notice in this case, toggling table-layout: fixed has no effect.

See the Pen Demo for CSS’s table-layout property by Louis Lazaris (@impressivewebs) on CodePen.

This happens because the default layout algorithm is essentially saying “make the first column 400px wide, and distribute the remaining columns based on their content”. Since the other three columns have the same content as each other, there will be no change. But now let’s add some extra text content to one of the other columns:

See the Pen Demo for CSS’s table-layout property with col width and variable content by Louis Lazaris (@impressivewebs) on CodePen.

Now if you click the toggle button, you’ll see the columns adjust to accommodate a fixed layout, irrespective of content. Once again, the same thing is happening; the first column is set at 400px then the remaining columns are divided equally. But this time, because one of the columns has extra content, the difference is noticeable.

How a fixed layout algorithm determines column widths

The following two demos should help in understanding that the first row of the table is what helps to define the column widths of a table set to table-layout: fixed.

See the Pen Demo for CSS’s table-layout with cell in row 1 given defined width by Louis Lazaris (@impressivewebs) on CodePen.

In the above demo, the first cell in the table’s first row has a width of 350px. Toggling table-layout: fixed adjusts the other columns, but the first one remains the same. Now try the following demo:

See the Pen Demo for CSS’s table-layout with cell in row 2 given defined width by Louis Lazaris (@impressivewebs) on CodePen.

In this case, it’s the second row that has a width attached to its first table cell. Now when the toggle button is clicked, all the column widths are adjusted. Again, this is because the fixed layout algorithm is using the first row to determine the column widths, and the end result is that it distributes the widths equally.

Benefits of a fixed layout algorithm

The aesthetic benefits of using table-layout: fixed should be clear from the demonstrations above. But the other major benefit is performance. The spec refers to the fixed algorithm as a “fast” algorithm, and for good reason. The browser does not need to analyze the entire table’s content before determining the size of the columns; it only needs to analyze the first row. So the result is a faster processing of the table’s layout.

Related Properties

More Information

Browser Support

Chrome Safari Firefox Opera IE Android iOS
1+ 1+ 1+ 7+ 5+ 2.1+ 3+

table-layout originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
249476
caption-side https://css-tricks.com/almanac/properties/c/caption-side/ Thu, 29 Dec 2016 13:14:29 +0000 http://css-tricks.com/?page_id=248452 The caption-side property in CSS allows you to define where to position HTML’s <caption> element, used on HTML table headers. This property can also apply to any element whose display property is set to caption-side.

table {
  caption-side: top;


caption-side originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
The caption-side property in CSS allows you to define where to position HTML’s <caption> element, used on HTML table headers. This property can also apply to any element whose display property is set to caption-side.

table {
  caption-side: top;
}

Syntax

caption-side: top | bottom | block-start | block-end | inline-start | inline-end
  • Initial value: top
  • Applies to: table-caption elements
  • Inherited: yes
  • Computed value: as specified
  • Animation type: discrete

Values

/* Directional values */
caption-side: top;
caption-side: bottom;

/* Logical values */
caption-side: block-start;
caption-side: block-end;
caption-side: inline-start;
caption-side: inline-end;

/* Global values */
caption-side: inherit;
caption-side: initial;
caption-side: revert;
caption-side: unset;
  • top: the default. Positions the caption at the top of the table.
  • bottom: Positions the caption at the bottom of the table.
  • block-start: Positions the caption at the table’s starting edge in the block direction.
  • block-end: Positions the caption at the table’s starting edge in the block direction.
  • inline-start: Positions the caption at the table’s starting edge in the inline direction.
  • inline-end: Positions the caption at the table’s starting edge in the inline direction.
  • inherit: Indicates that the value is inherited from the caption-side value of its parent

The caption-side property can be applied either to the <table> element or the <caption> element, with the same effect. While this property will affect the position of the caption box as a whole (a caption’s display value computes to table-caption), it will not affect the alignment of text inside the box. Text inside the box may be aligned using the text-align property.

Note that the above values for caption-side are relative to the table’s writing-mode. For example, if a table is set to a vertical writing mode, then the top and bottom values will be relative to the direction of the table.

Examples of caption-side

The demo below includes a “toggle” button that toggles the table’s caption-side property between top and bottom, so you can see the difference using a table with many rows of data:

In the next demo, the writing-mode for the table is set to vertical-rl. As demonstrated by toggling using the button, the top and bottom values are relative to the table’s writing-mode:

Non-standard Firefox-only values

Firefox has long supported, and still supports, four non-standard values for caption-side:

  • left: positions the caption to the left of the table.
  • right: positions the caption to the right of the table.
  • top-outside: positions the caption at the top of the table, with its dimensions independent of the table
  • bottom-outside: positions the caption at the bottom of the table, with its dimensions independent of the table

The demo below works only in Firefox, and allows you to use four buttons to set the different non-standard values:

Browser support

ChromeSafariFirefoxOperaIEAndroidiOS
1+1+1+9.2+8+2.1+3.2+

Support in the table above refers to basic support for the standard top and bottom values. Firefox also additionally supports the non-standard left, right, top-outside, and bottom-outside values. There is no browser support for the new block-start, block-end, inline-start, and inline-end values.

More Information


caption-side originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
248452