Repository navigation
Let a table inherit from the block around it - #656
Merged
Merged
Conversation
27 of 28 tasks
jakejackson1
force-pushed
the
fix/543-table-inherits-from-block
branch
from
September 30, 2026 10:38
309b808 to
a381afc
Compare
jakejackson1
force-pushed
the
fix/542-row-properties-to-cells
branch
from
September 30, 2026 10:38
d044058 to
dcca660
Compare
jakejackson1
force-pushed
the
fix/543-table-inherits-from-block
branch
from
September 30, 2026 11:47
a381afc to
b8c3609
Compare
jakejackson1
force-pushed
the
fix/542-row-properties-to-cells
branch
from
September 30, 2026 11:47
dcca660 to
090dfc9
Compare
jakejackson1
force-pushed
the
fix/542-row-properties-to-cells
branch
2 times, most recently
from
October 4, 2026 21:28
d7bcd60 to
b31d661
Compare
Under the standard cssMode, a table takes every inherited property from the block, list item, header or positioned block it is in, and a nested table takes its cell's line-height and text-align too. A table's relative font size is taken of the block's, and rem in a table stays the document's size. The built-in hyphens and font-kerning on tables are dropped, and the built-in line-height of 1.2 stays only where the table would inherit normal. Legacy output is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#642 reads rem against html's font size, which a table does not replace, so this branch's own rem change and its changelog entry go. The snapshot case shows 1rem as html's size, 11pt, and a new case sets html's size. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jakejackson1
force-pushed
the
fix/543-table-inherits-from-block
branch
from
October 4, 2026 21:52
b8c3609 to
61eb72f
Compare
Under the standard cssMode, a table opened inside open inline elements, as in <span class="note">…<table>…</table>…</span>, sets their state aside on the enclosing block as #653 does for a block, so it inherits their colour, font, size and weight, and a relative font size on it is taken of theirs. The text after the table is drawn in their style again until their end tags. A table nested in a cell keeps the cell's open inline elements, so an end tag after it restores what was before. Legacy is unchanged. The set-aside and put-back helpers move from BlockTag to Tag, and the put-back restores the block's own state when nothing was set aside, reading it through InheritedProperties::blockTextState(). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… are Under the standard cssMode a table no longer keeps the built-in line-height: 1.2 where it would inherit normal, so a table in a block that sets no line-height is drawn at normalLineheight, as a browser draws it. The 92 standard-mode snapshot documents with such tables are regenerated; no legacy document changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The snapshot documents with a table that would now inherit normal set line-height: 1.2 on it, the value the table was drawn at before, so the 92 fixtures go back to what they were. Two documents that show a table inheriting a block's line-height set it only on their other tables. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jakejackson1
pushed a commit
that referenced
this pull request
Oct 5, 2026
…the fees table as its clause Since #656 a table inherits the block it is in, so the decoration documents' tables took line-height: normal and the amendment's fees table the inserted clause's green. The documents set line-height: 1.2 on their tables, as the others do, and the standard amendment fixture is refreshed for the green. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jakejackson1
added a commit
that referenced
this pull request
Oct 5, 2026
…etting them inherit or undo them (#654) * Draw an ancestor's text decorations over its descendants instead of letting them inherit or undo them Under the standard cssMode an underline, overline or line-through propagates to the element's descendants in the flow, as a set of its own kept by Mpdf\Css\TextDecorations: - each is drawn in the colour and at the size of the element that set it; - text-decoration: none on a descendant removes only its own decoration, so a link set to none inside an underlined paragraph is still underlined; - a descendant's own decoration is added to its ancestors'; - floats, positioned blocks and inline blocks start without their ancestors' decorations, and tables still do; - an element whose color is transparent adds no decoration of its own. A child block no longer takes its parent's vertical-align. Under the legacy cssMode text-decoration and vertical-align are inherited as in mPDF v7. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Carry decorations into a block opened inside an inline element, and leave a decoration unseen in inherited transparent A block inside an underlined span now starts from the span's text state, which #653 sets aside, so it and the text after it are underlined. TextDecorations::seen() reads #651's transparent flag, so a descendant that inherits color: transparent adds no decoration of its own either. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Keep the decoration snapshots' tables at line-height 1.2, and colour the fees table as its clause Since #656 a table inherits the block it is in, so the decoration documents' tables took line-height: normal and the amendment's fees table the inserted clause's green. The documents set line-height: 1.2 on their tables, as the others do, and the standard amendment fixture is refreshed for the green. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: gravitypdf-bot <support@gravitypdf.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #543. Part of #520 (step 22).
Was stacked on #655 and #648. Both have merged, and this branch is now rebased onto
gravitypdf.Problem
Measured on #655's head,
d0440581. A table starts from the document's defaults, so a block betweenbodyand the table hands it nothing.<div style="color:#0f0; font-family:monospace; font-size:20pt">around a table<body style="color:#0f0">around a table<div style="font-size:20pt"><table style="font-size:80%"><table style="font-size:20pt"><tr><td style="font-size:1rem"><td style="text-align:right">holding a table with aththcentredThe built-in default style also gives every table
line-height: 1.2,hyphens: manualandfont-kerning: auto, so a table reset those whatever it sat in (#648).Change
The user's decision: under standard, a table inherits every inherited property, as in a browser's no-quirks mode. Under legacy it starts from the document's defaults as before.
Under
CssMode::STANDARD:CssMerger::mergeInheritedBlockProperties()also runs for a table that is not in a cell. It reads the block the table is opened in and keepsInheritedProperties::names(). It leaves out the margin collapse, column background, text decoration andvertical-alignthat a child block takes. The table's merged CSS then carries the block's colour, font, size, alignment, line-height and the rest into its fields andbase_table_properties. Sobase_table_properties['COLOR']holds the inherited colour, which Draw currentColor, and a border or shadow with no colour, in the element's colour #651 reads forcurrentColor.Table::open()resolves a table's ownfont-sizeagainst the block's size.rem.SizeConverterreadsremagainstoriginal_default_font_size, which a table does not overwrite. Before, it readdefault_font_size, whichTable::open()sets to the table's size (from Many CSS values are ignored or read wrongly, and four common inputs break the document #552).Tdkeeps thetext-aligna cell inherits or sets on its table, andTable::open()merges a nested table's CSS over its cell'sline-heightandtext-align. So athin a table nested in a right-aligned cell is aligned right. Carry every inherited text property through every channel that hands inherited values on #648 already carries the cell's text properties.line-height,hyphensandfont-kerningon a table. SoCssMerger::mergeDefaultCss()drops the built-inline-height: 1.2,hyphens: manualandfont-kerning: auto(TABLE_INHERITED_DEFAULTS). A value changed through thedefaultCSSoption still applies. A table in a block with noline-heightof its own therefore inheritsnormal; see below.Compatibility
Every change is gated. Under legacy, tables merge and size as before, and
remreadsdefault_font_size.To prove legacy is unchanged, I rendered all 144 snapshot documents under legacy, with the mode forced on every document, from #648's head and from this branch. They are byte-identical. Rendered under standard, the same 144 documents are byte-identical to #655's. No existing fixture changed.
StringWidthDecodingTestwrapped its tables in adivthat setfont-family: dejavusans; font-size: 8pt, which the tables never took. Its expected lines are for the cells' default font, so the wrapper is gone. The lines are the same.line-height: normalin tablesThe question this section used to ask is decided: a table matches paragraphs. Under standard, a table that would inherit
normalnow takes it, as a browser's does, instead of keeping the built-in 1.2. Its cells drawnormalas a paragraph does, atnormalLineheight(1.33) plus the font's line gap, so every standard-mode table that sets noline-heighthas taller rows. Legacy keeps the 1.2.line-height: 1.2on their tables, mostly as atablerule at the top of their stylesheet, so no fixture changes. Two documents show a table inheriting a block'sline-height:table-inherits-from-blockandtable-in-blocks-article. In those two, only the other tables getline-height: 1.2, inline. The invoice and Factur-X documents get the rule ahead of the writer's HTML, so the invoice writer itself is unchanged.normalas the number 1.33, because Carry every inherited text property through every channel that hands inherited values on #648 writes the internalNinto the stand-in<div>'s style asn. Its table now inherits that number, as its paragraphs do, so it has no line gap. Carry every inherited text property through every channel that hands inherited values on #648's channel is left alone, since writingnormalthere would change how positioned blocks draw their own lines.table { line-height: 1.2; }to the stylesheet. The changelog entry says so.A table inside an inline element
#653 (step 20) made a block inherit from the inline elements it is opened in. A table had the same gap:
Table::open()emptiedInlineProperties, andclose()restored the enclosing block's state. So<span style="color: #0f0; font-weight: bold">xx<table>…qq…</table>yy</span>drewqqandyyblack and regular.Under standard, the last commit fixes that:
blockTextState(), which the table's merge already reads, and afont-sizepercentage on it is taken of theirs.close()puts them back, soyyis drawn in the span's style until</span>.PARENTCELLand puts them back when it closes. Before, in both modes, a span's style ran on past</span>after a nested table, because nothing was left for the end tag to restore. Legacy keeps that.setOpenInlineElementsAside()moves fromBlockTagtoTag. The put-back becomesrestoreBlockTextState(), which restores the block's own state when nothing was set aside, soBlockTag::close()andTable::close()share it.BlockInsideInlineTest::documents(): a table in a span, in a span in a block, in a span in a cell, in a span in a kept block laid out again on the next page, and a table that breaks the page before it. Each runs in both modes.TableInheritsFromBlockTest::fontSizes()adds 'a percentage of a span'.Tests
InheritedPropertiesTest: 7 new contexts in Carry every inherited text property through every channel that hands inherited values on #648's matrix, each checking everyTEXTproperty in both modes:<body style>, a header, a positioned block, and apage-break-inside: avoidblock laid out again on the next page;<body style>. Thefont-kerningandhyphensexception Carry every inherited text property through every channel that hands inherited values on #648 made for nested tables is gone under standard.TableInheritsFromBlockTest:text-align,line-heightanddirectionfrom a block, a list item, a positioned block, a kept block and a cell, compared by where the cell's lines are drawn. Legacy carries a block's direction, and a cell's alignment and direction, as before.line-height: normalon the block, or none, draws the cells asline-height: normalon the cell under standard, as1.33in a positioned block that sets none, and as1.2under legacy.CascadeOrderTest's uncontested documents andUniversalSelectorTest's reset compare standard with legacy. Their tables now setline-height: 1.2, the value legacy gives them.%andemof a block, a list item and a cell;remin a sized table, in a sized block, on a table and in a nested table;thalignment:text-alignwinning.TableInheritsFromBlockTestfail, all standard or both-moderemand alignment cases.Snapshots
table-inherits-from-block(standard), one case per caption:1remin a 20pt table;line-heightandtext-align, with ath;text-alignandline-heightreaching a nested table.table-in-blocks-article-standardandtable-in-blocks-article-legacy: an article with a table in a dark callout, a table in a list item, a sized table in a right-aligned quotation, and a panel cell holding a nested table. The captions say what each mode draws.I rendered each fixture and looked at it.
Rebased after #647 to #655
The branch's two commits were rebased onto
gravitypdfwithgit rebase --onto, dropping the old copies of #648 and #655.CHANGELOG-GRAVITYPDF.md: kept Draw currentColor, and a border or shadow with no colour, in the element's colour #651's and Resolve inherit, initial, unset and revert in the standard CSS mode #652's entries and this PR's, and both link lists.CssMerger: kept Draw currentColor, and a border or shadow with no colour, in the element's colour #651'scurrentColorconstants besideTABLE_INHERITED_DEFAULTS.Table::open(): Compute font-weight numbers, bolder and lighter, and font-size larger and smaller from the parent's values #647 resolves a table'sfont-sizethroughSizeConverter::convertFontSizeToMm(), solarger,smallerand the keywords work. The branch's choice of parent size (the cell's table, the block's size under standard, or the document's) now feeds that call.mergeInCascadeOrder()merges the defaults on their own, withcssPropertiesemptied, sorevertcan read them.standardTableDefaults()read the inheritedline-heightfromcssProperties, so it always saw none and kept the 1.2. A table then never took a block'sline-height.mergeDefaultCss()now takes the inherited layer, andstandardTableDefaults()reads it. Without that fix, the five standardLINE-HEIGHTcases oftestTheCellLaysItsLinesOutByTheInheritedValuefail.universal-stylesheet(from Match the universal selector * in the standard CSS mode (mpdf/mpdf#312) #644) setsbody { line-height: 1.4 }, which its table now inherits. Each of the table's three rows is 1.8pt taller (9pt × 0.2), and the content below moves down 5.4pt. Nothing else in the document changed, and the fixture is regenerated.Checks
composer test: OK. 11858 tests, 31 skipped for missing optional packages or ungenerated data. The snapshot suite ran with Imagick and Ghostscript, with no skips.composer cs: clean.Rebased after #633 to #646
#648, #655 and this PR were rebased onto
gravitypdf.rem: Match :root, html, :link and :any-link, and read rem against html's font size #642 readsremagainst html's font size (root_font_size), which a table does not replace. That covers this PR'sremfix, so itsoriginal_default_font_sizeline inSizeConvertergives way to Match :root, html, :link and :any-link, and read rem against html's font size #642's. Its bugfix entry "font-size: 1remin a table cell gave the table's font size" is dropped too, as Match :root, html, :link and :any-link, and read rem against html's font size #642's entry already says it.table-inherits-from-blockhas nohtmlrule, so the rem case shows 1rem as html's default size: the cell reads "11pt", and the caption says so. The fixture is regenerated, and only that case changed.TableInheritsFromBlockTest::fontSizes()has a new case, 'rem in a cell follows html'. Underhtml { font-size: 16pt }, a1remcell in an 8pt table is 16pt under standard, and 8pt under legacy.CssMerger:standardTableDefaults()sits beside Read each HTML presentational attribute only on the elements HTML defines it for, under any stylesheet rule #641'smergeTableSpecificCss().Gates:
composer test9454 tests, 31 skipped;composer csclean; PHPStan no errors.🤖 Generated with Claude Code