vue
vue copied to clipboard
Style binding: implicitly assign 'px' as the default unit for numeric values for certain css properties
What problem does this feature solve?
When assigning values to a CSS property via style binding like
<div class="d-inline-block" :style="{width : width}"></div>
or using the shorthand syntax...
<div class="d-inline-block" :style="{width}"></div>
this will actually not gonna work because we need to explicitly set the unit
:
<div class="d-inline-block" :style="{width : width + 'px'}"></div>
or via interpolation...
<div class="d-inline-block" :style="{width : `${width}px`}"></div>
Now our code becomes more verbose. Combining all the number of occurrences of such binding, it's becoming ridiculous.
I'm not sure if currently there is an elegant solution for this, but if there is. It would be also good if it is referenced in in the docs.
In React, this is the default behavior. It will add 'px' if the unit
is not specified.
What does the proposed API look like?
For common css properties like width
and height
, having vue implicitly assign 'px' to the value it would definitely make our code much more cleaner.
This code...
<div class="d-inline-block" :style="{width}"></div>
will be interpreted as:
<div class="d-inline-block" :style="{width : width + 'px'}"></div>
TBH I'm not a fan of this feature. A CSS property can accept multiple value types and even it's “unitless” today doesn't mean it will stay “unitless” forever, and vice versa. As the language evolves, maybe someday a “unitless” property can take length units, or those accept length units can take “unitless” values. If a property use to not accept “unitless” values and later changed to accept them, we would never know the true semantics behind a number if we had supported appending px
to it by default.
Hi @Justineo,
I see your point, but I think you're a little bit exaggerating such concern. We know CSS' implementation in relation to the units of values of css properties hasn't changed that much between versions. Take the width or height for example, ever since the birth of CSS, it hasn't changed much. It didn't go unitless.
And also, I am certain that some properties wouldn't go unitless, particularly those properties where length
are involved like the height
, width
and border
for example. As far as CSS' maturity is concerned, I'm pretty much sure that we won't be seeing something like height: 1
or opacity: 1em
in the future.
Anyway, this is implemented in ReactJS, so there shouldn’t be that much problem having it in Vue since it will definitely improve our productivity.
I'm not a fan of this either, it means we have to keep another list of unitless properties and keep it up to date, and it has to be added at runtime too because a property name could be dynamic
Hi @posva,
I think we we don’t necessarily need to list all unitless or non-unitless properties. We could just list the commonly used properties in real world scenarios. Like the height
and width
, there are cases where we assign these properties via javascript.
Unfortunately, that wouldn't be consistent and confusing to users
Hi @posva ,
Yes, you are right.
I think this would be doable with a sort of feature-detection solution. For example, if a value of type "number" were passed, then during normalization a one-time check is done to see whether the property in question supports unitless values.
At least in Chrome, if a value isn't allowed to be unitless, it won't get set:
tmpDiv = document.createElement("div")
tmpDiv.style.width = 20
console.log(tmpDiv.style.width) // output: ""
The output will always be a string so for the comparison check, the input value should be converted to a string. This should allow Vue to maintain high performance in this area due to the solution's opt-in nature. If a developer never passes a number type, then they'll never encounter that branch.
As you can see, feature is already included in Vue 3:
https://github.com/vuejs/vue-next/blob/eaf414f06366b413e36a688749a6524687b952d7/packages/shared/src/domAttrConfig.ts#L44-L55
Although I mentioned this is theoretically not a safe move, the reality is that this feature already exists in React and we would have to take this into account when trying to evolve CSS, to prevent conflicts with the most popular JavaScript frameworks.
Maybe we can back port this into 2.7 after 3.0 and the companion libs are fully ready. But we still have to maintain a list because feature detection doesn’t work on the server side.
Vue 3 only used this to remove "invalid" declarations for SSR and the feature was already removed.
Yes, that's what I'm saying ever since I started this discussion. React has been implementing it, so why shouldn't we?
Anyway, it's really cool seeing this getting pushed despite the tons of dislikes. 😅 I'm looking forward to Vue 3.0. ❤️
PS: @julian-ca is my older account.