Skip to content

write_html: let table cells without a width share the rest, like brow… - #2035

Merged
andersonhc merged 3 commits into
py-pdf:masterfrom
RavSinghChandan:html-partial-cell-widths
Oct 22, 2026
Merged

andersonhc merged 3 commits into
py-pdf:masterfrom
RavSinghChandan:html-partial-cell-widths

Conversation

@RavSinghChandan

Copy link
Copy Markdown

A table whose first row gives a width to only some of its cells, such as <td width="50%">a</td><td>b</td>, made write_html() raise ValueError: Invalid .col_widths specified: missing width for table() column 2. Browsers lay the cells with a width out first and let the others share the remaining space.

write_html() now remembers the width of every cell of the first row, and when some have none, the others share what is left of the table width (the average width if nothing is left). Rows where every cell has a width are unchanged. Added tests comparing against the equivalent fully specified widths, for percentages and an absolute width.

@andersonhc

Copy link
Copy Markdown
Collaborator

After a quick look, I have two questions worth investigating:

  • Does width inference handle colspan? [This code](

    fpdf2/fpdf/html.py

    Lines 1303 to 1308 in f03079a

    if len(self.table.rows) == 1:
    self.first_row_widths.append(cell_width)
    if cell_width is not None:
    # pylint: disable=protected-access
    self.table._col_widths = [
    w[0] for w in self.first_row_widths if w is not None
    ) records one width per cell, while _col_widths expects one per column. Could spanning cells still cause missing-width errors?
  • Should inference account for cellspacing? [This calculation](

    fpdf2/fpdf/html.py

    Lines 1444 to 1446 in f03079a

    table_width = float(self.table._width or self.pdf.epw)
    self.table._col_widths = _fill_missing_widths(
    self.first_row_widths, table_width * self.pdf.k
    ) uses the full table width, but rendering later subtracts gutters. Could this shrink explicitly sized cells? For example, a table with cellspacing="30" and <td width="200">a</td><td>b</td> appears to produce a first column of about 168.42 pt rather than 200 pt.

@RavSinghChandan

Copy link
Copy Markdown
Author

Both were real. Colspan was recorded per cell instead of per column. Cellspacing wasn't subtracted before sharing the width.
Both are fixed and pushed.
Each has a test, including a check that the column keeps exactly 200 pt.

@andersonhc
andersonhc merged commit 6357cb5 into py-pdf:master Oct 22, 2026
39 of 42 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants