HTML and CSS project tutorial covering web development fundamentals. Learn to build interactive and responsive web pages.
Every table begins with the table element. Rows use tr, header cells use th, and data cells use td. Semantic grouping elements include thead for header rows, tbody for body content, and tfoot for footer rows. The caption element provides a title or description for screen readers and search engines. Always use scope="col" or scope="row" on th elements to improve accessibility — these attributes tell screen readers which cells each header applies to, making navigation of large tables much easier for visually impaired users.
The colspan attribute makes a cell span multiple columns, while rowspan makes it span multiple rows. These attributes are essential for complex table layouts with grouped headers or merged category labels. When merging cells, each row must have the same total effective column count — count each cell's colspan value plus any cells without colspan. A common use is creating a multi-level header: a row with th colspan="2" for "Personal Info" and th colspan="2" for "Contact", followed by a row with individual column headers. Test carefully because incorrect colspan counts cause layout shifting.
Start with border-collapse: collapse to merge adjacent cell borders into clean single lines. Use width: 100% for full-width tables and padding for cell spacing. Style header cells with background: #f0f4ff and border-bottom: 2px solid #4f46e5 for visual hierarchy. Data cells use border-bottom: 1px solid #e5e7eb for row separation. Zebra striping with tr:nth-child(even) td { background: #f9fafb; } improves readability on large data sets. Use text-align: right for numeric columns to align numbers properly, and white-space: nowrap for columns that should not wrap.
Tables inherently want to be as wide as their content, which causes overflow on small screens. The simplest solution is horizontal scrolling: wrap the table in a container with overflow-x: auto. Users can swipe or scroll horizontally to see all columns. For better mobile UX, convert tables to stacked cards on very small screens using a media query. Each row becomes a card with column labels displayed using data-label attributes and ::before pseudo-elements. This card approach works best for tables with 3-6 columns. For tables with many columns, horizontal scroll is usually the more practical choice.
Adding sort functionality to tables improves usability for data-heavy pages. The approach: attach click handlers to th elements, then sort the tbody rows using Array.sort(). Extract the text content of the clicked column's cells in each row, compare values, and reorder rows in the DOM. Add visual indicators like ▲ and ▼ arrows to show the current sort direction. Account for different data types: numbers need numeric comparison, dates need date parsing, and strings need locale-aware comparison. Debounce or throttle sort operations on large tables to prevent performance issues.
Pricing tables are one of the most common real-world table uses. Structure: columns for each plan tier with rows for features. Highlight the recommended plan with a distinct background color and a "Most Popular" badge. Use text-align: center on pricing columns. Include checkmarks (✓) and cross marks (✗) for feature availability. Add CTA buttons in each column. For mobile, convert pricing tables to a vertical stack where each plan becomes a card with all its features listed. Use CSS Grid instead of HTML tables for pricing layouts because pricing is presentational, not data — Grid gives more control over alignment and responsiveness.
Always include a caption element that describes the table's purpose: caption { caption-side: top; }. Use scope="col" on column headers and scope="row" on row headers. For complex tables with merged cells, use id and headers attributes to explicitly associate data cells with their header cells. Avoid using tables for layout — they are for tabular data only. Screen readers navigate tables cell by cell and announce headers, so proper associations are critical. Test with a screen reader like VoiceOver or NVDA to verify your table is navigable and understandable.