@@ -886,7 +886,8 @@ Serializing Custom Properties</h3>
886886 so implementations typically serialize the name lowercased.
887887
888888 Specified values of [=custom properties=] must be serialized
889- <em> exactly as specified by the author</em> .
889+ <em> exactly as specified by the author</em>
890+ (with one exception, below).
890891 Simplifications that might occur in other properties,
891892 such as dropping comments,
892893 normalizing whitespace,
@@ -895,9 +896,15 @@ Serializing Custom Properties</h3>
895896 must not occur.
896897
897898 Computed values of [=custom properties=] must similarly be serialized
898- <em> exactly as specified by the author</em> ,
899+ <em> exactly as specified by the author</em>
900+ (with the same one exception, below),
899901 save for the replacement of any ''var()'' functions.
900902
903+ The one exception to serialization being precisely as specified in the source file
904+ is that an <em> empty</em> custom property
905+ (such as ''--foo:;'' )
906+ must serialize with a single space as its value.
907+
901908 <wpt>
902909 variable-reference-shorthands-cssom.html
903910 variable-reference-variable.html
@@ -921,7 +928,8 @@ Serializing Custom Properties</h3>
921928 </div>
922929
923930 <div class=note>
924- This requirement exists because authors sometimes store non-CSS information in custom properties,
931+ This "exactly as specified" requirement exists
932+ because authors sometimes store non-CSS information in custom properties,
925933 and "normalizing" this information can change it in ways that break author code.
926934
927935 For example, storing a UUID in a custom property,
@@ -936,6 +944,29 @@ Serializing Custom Properties</h3>
936944 would fatally break the author's use of the value.
937945 </div>
938946
947+ <div class=note>
948+ The requirement to serialize an empty custom property
949+ as a string with a single space in it instead
950+ is due to compatibility with the existing CSSOM API.
951+ {{setProperty()}} specifies that
952+ if the passed value is an empty string
953+ it instead acts as {{removeProperty()}} .
954+
955+ This is a frankly weird behavior,
956+ and not something we would do in new APIs.
957+ But we can't change the past,
958+ and letting empty properties accurately serialize as the empty string
959+ would mean that round-tripping a custom property value,
960+ or reading a property on one element
961+ and setting a property on another element to the same value,
962+ wouldn't work as intended.
963+ Using a single space preserves the author-intended behavior as much as possible,
964+ while having the smallest chance of accidentally breaking things,
965+ since authors working with custom property values in JS
966+ are probably calling {{String/trim()}} on the values anyway.
967+ </div>
968+
969+
939970
940971<!-- Big Text: etc
941972
0 commit comments