[runtime-dom]: when <img> width and height are of string type, they will be set to `0`
Vue version
3.2.47
Link to minimal reproduction
Steps to reproduce
Look the preview:
The height
of <img>
is 0
, but it should be 24px
What is expected?
The height
of <img>
should be 24px
What is actually happening?
When height
and width
of some embedded element such as <img>
、<video>
、<source>
and <canvas>
are string type, they will be rendered as 0
. And they are rendered normally when they are number type. This is because of the height
and width
of these elements must be set as attribute when they are string type, but in patchProp
they are directly modified by patchDOMProp
instead of patchAttr
.
System Info
No response
Any additional comments?
No response
Duplicate of https://github.com/vuejs/core/issues/2801 the height or width must be an integer without a unit. see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img?retiredLocale=de#attr-height
I'm with edison here. The developer should provide a number as that's what's expected by the HTML spec. We should not start adding code to special handle such cases.
Although the description of width
on MDN must be a integer, it can also be a string type when used in html.I think the description on mdn is not necessarily accurate, and we should be more consistent with the actual use of html.
Here is an example to prove my point:
The attribute of <input>
in mdn also has width
and height
and their description is consistent with that of <img>
. But in fact, the width
of input
can only be changed through style. Neither setAttribute
nor prop
can change its width
, even if its value is a integer. The following is the example about <input >
:
it can also be a string type when used in html
Certain browsers may support that, but it's not in the spec:
The attributes, if specified, must have values that are valid non-negative integers.
https://html.spec.whatwg.org/multipage/embedded-content-other.html#attr-dim-height
Vue also supports strings, by the way, as long as they are convertible to integers which the spec expects as values. So if you provide a string containing just a number, free of a unit ('100'
instead of '100px'), SSR and CSR work the same and work fine:
So this PR would "only" add code to be more compatible with nonstandard browser behavior. That is something we could want, but I'm still not exactly convinced it's worth being another special case to have in the codebase.
@Justineo in what way does this break in certain cases in CSR?
it can also be a string type when used in html
Certain browsers may support that, but it's not in the spec:
The attributes, if specified, must have values that are valid non-negative integers.
https://html.spec.whatwg.org/multipage/embedded-content-other.html#attr-dim-height
Vue also supports strings, by the way, as long as they are convertible to integers which the spec expects as values. So if you provide a string containing just a number, free of a unit (
'100'
instead of '100px'), SSR and CSR work the same and work fine:So this PR would "only" add code to be more compatible with nonstandard browser behavior. That is something we could want, but I'm still not exactly convinced it's worth being another special case to have in the codebase.
@Justineo in what way does this break in certain cases in CSR?
All right, thanks for your answer.
it can also be a string type when used in html
Certain browsers may support that, but it's not in the spec:
The attributes, if specified, must have values that are valid non-negative integers.
https://html.spec.whatwg.org/multipage/embedded-content-other.html#attr-dim-height
Vue also supports strings, by the way, as long as they are convertible to integers which the spec expects as values. So if you provide a string containing just a number, free of a unit (
'100'
instead of '100px'), SSR and CSR work the same and work fine:So this PR would "only" add code to be more compatible with nonstandard browser behavior. That is something we could want, but I'm still not exactly convinced it's worth being another special case to have in the codebase.
@Justineo in what way does this break in certain cases in CSR?
I have the same problem. The description of width
of <img>
in mdn is that must be an integer, but it is not necessarily related to using setAttribute
or prop
to update width
? The fact is that no matter what the type of this attribute is, all browsers will retain the value given by the user on the dom. However, in Vue, if the user gives width
a non-numeric string, width
will be set to 0
on the actual dom instead of keeping the value given by the user, which is completely illogical.
@LinusBorg
in what way does this break in certain cases in CSR?
There's currently a createStaticVNode
optimization which stringifies vnodes into HTML so it works similar to SSR. You can see the difference here.
But if we decided not to support non-standard syntax which seems to be supported by all major browsers, current behavior should be fine. (And I just found out that browsers actually support not only ${value}px
values, but also all string values starts with a number (eg. 24vue
) and extract the number value with logic similar to parseInt
.)