-
Notifications
You must be signed in to change notification settings - Fork 23k
docs: Add reference for CSS value serialization, especially colors #41322
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 14 commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
84438aa
docs: Add reference for CSS value serialization, especially colors
Shrinivassab ad17c8f
Merge branch 'main' into css-value-serialization
Shrinivassab eb3a19d
Update files/en-us/web/api/css_object_model/serializing_css_values/in…
Shrinivassab 0461c6a
Addressed PR comments
Shrinivassab d1661fd
Merge branch 'css-value-serialization' of https://github.com/Shriniva…
Shrinivassab 391a84d
Rewrite
Josh-Cena fc7f1c6
Update files/en-us/web/api/css_object_model/css_value_serialization/i…
Shrinivassab cc3a9a8
Update files/en-us/web/api/css_object_model/css_value_serialization/i…
Shrinivassab 766657b
Update files/en-us/web/api/css_object_model/css_value_serialization/i…
Shrinivassab 3b829f8
Update files/en-us/web/api/css_object_model/css_value_serialization/i…
Shrinivassab 8c1dd71
Update files/en-us/web/api/css_object_model/css_value_serialization/i…
Shrinivassab d8040e9
Merge branch 'main' into css-value-serialization
Josh-Cena fb9973c
Rewrite
Josh-Cena 8f991c4
Merge branch 'main' into css-value-serialization
estelle a7a4a39
Apply suggestions from code review
Josh-Cena c1db814
Add guide links
Josh-Cena File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
183 changes: 183 additions & 0 deletions
183
files/en-us/web/api/css_object_model/css_value_serialization/index.md
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,183 @@ | ||
| --- | ||
| title: CSS value serialization | ||
| slug: Web/API/CSS_Object_Model/CSS_value_serialization | ||
| page-type: guide | ||
| spec-urls: | ||
| - https://drafts.csswg.org/cssom/#serialize-a-css-value | ||
| - https://drafts.csswg.org/css-color-4/#serialization | ||
| --- | ||
|
|
||
| {{APIRef("CSSOM")}} | ||
|
|
||
| Some CSSOM APIs _serialize_ property values into standardized string representations based on the value's [data type](/en-US/docs/Web/CSS/Reference/Values/Data_types). For example, you might set a color using the `hsl(240 100% 50%)` syntax, but when accessed through JavaScript, the value will be returned in the equivalent `"rgb(0, 0, 255)"` syntax. | ||
|
|
||
| CSS data types can often be expressed in multiple syntaxes. For example, the [`<color>`](/en-US/docs/Web/CSS/Reference/Values/color_value) data type can be represented using named colors (`red`), hexadecimal notation (`#ff0000`), functional notation (`rgb(255 0 0)`), and more. These different syntaxes are exactly equivalent at every stage of [CSS value processing](/en-US/docs/Web/CSS/Guides/Cascade/Property_value_processing), similar to how in JavaScript, the same string can be written with single quotes or double quotes, or the same number can be written in different formats (like `16`, `16.0`, or `0x10`). | ||
|
|
||
| Because CSS converts all these surface representations to the same underlying value during value processing, it is often impossible to recover the original syntax from the already-parsed CSSOM. Furthermore, a _canonical_ representation is often more useful for scripts, because it allows comparisons and calculations based on how the content is presented to the user, rather than how it was originally authored. | ||
|
|
||
| ## When and how values are serialized | ||
|
|
||
| Serialization happens whenever CSS property values are read as strings through JavaScript APIs, such as: | ||
|
|
||
| - {{domxref("CSSStyleDeclaration.getPropertyValue()")}} | ||
| - {{domxref("CSSStyleDeclaration.cssText")}} | ||
| - Accessing properties directly on {{domxref("CSSStyleDeclaration")}} objects (e.g., `element.style.backgroundColor`) | ||
|
|
||
| Different APIs return `CSSStyleDeclaration` objects at different stages of [value processing](/en-US/docs/Web/CSS/Guides/Cascade/Property_value_processing), which have slightly different serialization behaviors. For example, {{domxref("Window.getComputedStyle()")}} and {{domxref("HTMLElement.style")}} returns the [resolved value](/en-US/docs/Web/CSS/Guides/Cascade/Property_value_processing#resolved_value) of properties, while {{domxref("CSSStyleRule.style")}} returns _more or less_ the [declared value](/en-US/docs/Web/CSS/Guides/Cascade/Property_value_processing#declared_value). | ||
|
|
||
| > [!NOTE] | ||
| > The [CSS Typed OM API](/en-US/docs/Web/API/CSS_Typed_OM_API) is able to represent units and other CSS syntaxes; however, style retrieved from elements is still processed and doesn't preserve the original syntax. For example, `CSS.cm(1).toString()` returns `"1cm"` instead of serializing to pixels, but `element.computedStyleMap().get("margin-left").toString()` still returns the resolved pixel value. | ||
Josh-Cena marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| Each CSS value type has an associated serialization format defined by the CSS specifications. Some common rules include: | ||
|
|
||
| - Keywords (like `auto`, `block`, `none`) serialize to all lowercase. | ||
| - [`<angle>`](/en-US/docs/Web/CSS/Reference/Values/angle): serialized to some angle unit, depending on the context (unspecified). For `element.style` and `getComputedStyle()`, this is `deg`. | ||
| - [`<color>`](/en-US/docs/Web/CSS/Reference/Values/color_value): | ||
| - For sRGB colors (named, `transparent`, system colors, hex, `rgb`, `hsl`, `hwb`): serialized as `rgb(R, G, B)` or `rgba(R, G, B, A)`, where all arguments are numbers, and the `rgb` form is selected if the alpha is exactly `1`. | ||
Josh-Cena marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| - For `lab()`, `lch()`, `oklab()`, `oklch()`, and `color()` colors: the function form is preserved, with numeric arguments. | ||
estelle marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| - The keyword `currentColor` serializes as `currentcolor`. | ||
| - [`<percentage>`](/en-US/docs/Web/CSS/Reference/Values/percentage): preserved as a percentage. | ||
| - [`<ratio>`](/en-US/docs/Web/CSS/Reference/Values/ratio): serialized to two numbers separated by `" / "`. | ||
| - [`<url>`](/en-US/docs/Web/CSS/Reference/Values/url_value): serialized with `url("...")`, with the URL resolved to an absolute URL. | ||
Josh-Cena marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| Note that `<percentage>` values often get computed into absolute dimensions (like `<length>`) during value processing, so they may not appear as percentages when serialized from computed styles. For dimensions with units, such as [`<frequency>`](/en-US/docs/Web/CSS/Reference/Values/frequency), [`<length>`](/en-US/docs/Web/CSS/Reference/Values/length), [`<resolution>`](/en-US/docs/Web/CSS/Reference/Values/resolution), and [`<time>`](/en-US/docs/Web/CSS/Reference/Values/time), the serialized unit depends on the context and is not well-specified. `getComputedStyle()` and `element.style` serialize them into `Hz`, `px`, `dppx`, and `s` respectively. | ||
Josh-Cena marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| When serializing the value for shorthand properties, its constituent longhand properties are serialized and combined according to the rules for that shorthand. | ||
|
|
||
| > [!NOTE] | ||
| > There are a lot of gory details regarding how CSS properties are serialized, especially for complex properties like `font`. They may be unspecified in the specifications or even inconsistent across browsers. You need to test and verify the behavior for your specific use case. | ||
Josh-Cena marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ```html | ||
| <div>Example Element</div> | ||
| ``` | ||
|
|
||
| ```css | ||
| div { | ||
| position: absolute; /* keyword */ | ||
| rotate: 1rad; /* <angle> */ | ||
| color: hsl(240 100% 50%); /* <color> */ | ||
| background-color: hsl(120 50% 50% / 0.3); /* <color> with alpha */ | ||
| border-color: lab(10 -120 -120); /* <color> in non-sRGB space */ | ||
| margin: 2em; /* relative <length> */ | ||
| padding: 2cm; /* absolute <length> */ | ||
| font-size: calc(1em + 2px); /* complex expression */ | ||
| left: 50%; /* <percentage> */ | ||
| animation-duration: 500ms; /* <time> */ | ||
| } | ||
| ``` | ||
|
|
||
| ```js | ||
| const element = document.querySelector("div"); | ||
| const table = document.createElement("table"); | ||
| const elemStyle = getComputedStyle(element); | ||
| const ruleStyle = document.getElementById("css-output").sheet.cssRules[0].style; | ||
| const head = table.createTHead().insertRow(); | ||
| ["Property", "getComputedStyle()", "CSSStyleRule"].forEach((text) => { | ||
| const th = document.createElement("th"); | ||
| th.textContent = text; | ||
| head.appendChild(th); | ||
| }); | ||
| for (const property of [ | ||
| "position", | ||
| "rotate", | ||
| "color", | ||
| "background-color", | ||
| "border-color", | ||
| "margin", | ||
| "padding", | ||
| "font-size", | ||
| "left", | ||
| "animation-duration", | ||
| ]) { | ||
| const row = document.createElement("tr"); | ||
| const propCell = document.createElement("td"); | ||
| const valueCell = document.createElement("td"); | ||
| const ruleCell = document.createElement("td"); | ||
| propCell.textContent = property; | ||
| valueCell.textContent = elemStyle.getPropertyValue(property); | ||
| ruleCell.textContent = ruleStyle.getPropertyValue(property); | ||
| row.appendChild(propCell); | ||
| row.appendChild(valueCell); | ||
| row.appendChild(ruleCell); | ||
| table.appendChild(row); | ||
| } | ||
| document.body.appendChild(table); | ||
| ``` | ||
|
|
||
| {{EmbedLiveSample("", "", 400)}} | ||
|
|
||
| ## Examples | ||
|
|
||
| ### Color value serialization | ||
|
|
||
| Colors are among the most common types affected by serialization. Regardless of whether you define a color using `hsl()`, `hwb()`, a keyword, or a modern color space, JavaScript usually returns it in [legacy `rgb()` or `rgba()` format](/en-US/docs/Web/CSS/Reference/Values/color_value/rgb#syntax). | ||
|
|
||
| The following examples demonstrate how different color formats are serialized when accessed through JavaScript. | ||
|
|
||
| ```html | ||
| <div class="example hsl">HSL Color</div> | ||
| <div class="example lab">LAB Color</div> | ||
| <div class="example named">Named Color</div> | ||
| <div class="example alpha">Transparent Color</div> | ||
| <pre id="output"></pre> | ||
| ``` | ||
|
|
||
| ```css | ||
| .example { | ||
| padding: 10px; | ||
| margin: 5px; | ||
| color: white; | ||
| } | ||
|
|
||
| .hsl { | ||
| background-color: hsl(240 100% 50%); | ||
| } | ||
|
|
||
| .lab { | ||
| background-color: lab(100% 0 0); | ||
| } | ||
|
|
||
| .named { | ||
| background-color: blue; | ||
| } | ||
|
|
||
| .alpha { | ||
| background-color: hsl(120 50% 50% / 0.3); | ||
| } | ||
| ``` | ||
|
|
||
| ```js | ||
| const examples = document.querySelectorAll(".example"); | ||
| const output = document.getElementById("output"); | ||
|
|
||
| examples.forEach((element) => { | ||
| const style = getComputedStyle(element); | ||
| output.textContent += `${element.className}: ${style.getPropertyValue("background-color")}\n`; | ||
| }); | ||
| ``` | ||
|
|
||
| {{EmbedLiveSample("Color value serialization", , 400)}} | ||
|
|
||
| ### Length value serialization | ||
|
|
||
| Lengths are another common case. Relative units (like `em`, `%`) are often resolved to absolute pixels when serialized through JavaScript APIs. | ||
|
|
||
| ```js | ||
| element.style.marginLeft = "2em"; | ||
| console.log(getComputedStyle(element).marginLeft); | ||
| // "32px" (depending on font size) | ||
| ``` | ||
|
|
||
| This normalization allows scripts to compare or calculate lengths consistently. | ||
|
|
||
| ## Specifications | ||
|
|
||
| {{Specifications}} | ||
|
|
||
| ## See also | ||
|
|
||
| - [`CSSStyleDeclaration.getPropertyValue()`](/en-US/docs/Web/API/CSSStyleDeclaration/getPropertyValue) | ||
| - [`Window.getComputedStyle()`](/en-US/docs/Web/API/Window/getComputedStyle) | ||
| - [CSS colors](/en-US/docs/Web/CSS/Guides/Colors) | ||
| - [`<color>`](/en-US/docs/Web/CSS/Reference/Values/color_value) | ||
| - [CSS values and units](/en-US/docs/Web/CSS/Guides/Values_and_units) module | ||
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
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The subject is
CSSStyleRule.stylewhich is singular?