Skip to content

Fix html_attr dropping style declarations whose value is zero - #4916

Merged
fabpot merged 1 commit into
twigphp:3.xfrom
dylanpulver:fix/html-attr-zero-style-value
Sep 5, 2026
Merged

Fix html_attr dropping style declarations whose value is zero#4916
fabpot merged 1 commit into
twigphp:3.xfrom
dylanpulver:fix/html-attr-zero-style-value

Conversation

@dylanpulver

Copy link
Copy Markdown
Contributor

InlineStyle::getValue() skips a declaration when empty($value) is true. That also matches 0, 0.0 and '0', which are ordinary CSS values.

{{ html_attr({style: {opacity: 0}}) }}                    {# "" #}
{{ html_attr({style: {'flex-grow': 0, color: 'red'}}) }}  {# style="color: red;" #}
{{ html_attr({style: ['opacity: 0']}) }}                  {# style="opacity: 0;" #}
{{ html_attr({class: [0, 'a']}) }}                        {# class="0 a" #}

Same declaration, opposite result. The numeric-key branch never consults empty(), and the sibling SeparatedTokenList::getValue() already uses an explicit null !== $v && false !== $v test, so token lists keep a 0. When every declaration is dropped the attribute is omitted entirely, so {style: {opacity: 0}} renders nothing at all, and HtmlExtension::htmlAttrValue('style', ['opacity' => 0]) returns null.

Silently affects opacity, z-index, margin, padding, border, flex-grow and custom properties.

The guard now lists the values that carry no declaration. null, false, '' and true still skip, and [] is kept in that list so empty arrays behave exactly as before.

html_attr.rst documents the null/false/true omission rules and says nothing about zero, so no doc change is needed. HtmlAttrTest.php already has a case named "zero is not treated as falsy", but only for a plain attribute value.

3 tests added. Reverting the fix fails the first; a naive null/false-only guard fails the other two.

InlineStyle::getValue() skipped a declaration when empty($value) was true,
which also matches 0, 0.0 and '0'. Those are ordinary CSS values (opacity: 0,
z-index: 0, margin: 0, flex-grow: 0), so they were silently dropped, and a
style map containing only such declarations omitted the attribute entirely.

The sibling SeparatedTokenList::getValue() already uses an explicit
null/false test, so class token lists keep a 0 while style declarations did
not. The numeric-key branch of InlineStyle itself never consulted empty(),
so {style: ['opacity: 0']} printed while {style: {opacity: 0}} did not.
Comment thread extra/html-extra/HtmlAttr/InlineStyle.php
@fabpot

fabpot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Thank you @dylanpulver.

@fabpot
fabpot merged commit a320927 into twigphp:3.x Sep 5, 2026
25 of 53 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants