HTML Child / The Elements That Carry Meaning
Tables are for data, and using them for layout hurts
A table makes a promise about relationships between rows and columns. Keep the promise or use something else.
A table describes data that has two dimensions. Each row is a record, each column is a property, and each cell means something because of where it sits. That is a genuinely powerful description. When it is written properly, with the column headings and any row headings identified as headings, software can tell a reader who is listening exactly which column and which row a value belongs to as they move around. Without a mouse, without seeing the grid, a person can still ask what the third figure in the second row represents and be told.
That promise breaks the moment a table is used to arrange things on a page. If the reason for the grid is that you wanted a picture on the left and some text on the right, there are no rows and no columns in any meaningful sense, and the cells have no relationship to each other. To somebody listening, the page announces a table, offers to help navigate its rows and columns, and then delivers a jumble. It is a false promise made with good intentions, and the arrangement it produces is usually more brittle than a proper layout approach would have been anyway.
There are a few ordinary courtesies inside real tables that beginners often miss. A caption naming what the table shows is genuinely helpful, especially on a page with several of them. Headings must actually be identified as headings rather than merely appearing bold at the top. Complicated tables with cells spanning several columns are hard for everyone, so splitting them into two simple tables is usually the kinder choice. And a very wide table needs a plan for narrow screens, because a grid that cannot be seen in full is not much better than no grid at all.