diff --git a/docs/tutorials/04-Questions.md b/docs/tutorials/04-Questions.md
index d104a628..262a7509 100644
--- a/docs/tutorials/04-Questions.md
+++ b/docs/tutorials/04-Questions.md
@@ -6,10 +6,10 @@ section: "AngleSharp.Css"
## How to change the color output?
-By default, AngleSharp.Css uses `rgba()` for the serialization of `Color`. To change this you can set
+By default, AngleSharp.Css uses `rgba()` for the serialization of `CssColorValue`. To change this you can set
```cs
-Color.UseHex = true;
+CssColorValue.UseHex = true;
```
which will automatically use hex for all non-transparent colors. All other colors would still be represented via the `rgba()` function.
@@ -17,13 +17,25 @@ which will automatically use hex for all non-transparent colors. All other color
So you'd get:
```cs
-Color.UseHex = true;
-var color1 = new Color(65, 12, 48);
+CssColorValue.UseHex = true;
+var color1 = new CssColorValue(65, 12, 48);
// color1.CssText = #410C30
-var color2 = new Color(65, 12, 48, 10);
+var color2 = new CssColorValue(65, 12, 48, 10);
// color2.CssText = rgba(65, 12, 48, 0.04)
```
+Alternatively, you can follow the serialization rules from the CSSOM specification, which omit the alpha channel of an opaque color:
+
+```cs
+CssColorValue.UseSpecSerialization = true;
+var color1 = new CssColorValue(65, 12, 48);
+// color1.CssText = rgb(65, 12, 48)
+var color2 = new CssColorValue(65, 12, 48, 10);
+// color2.CssText = rgba(65, 12, 48, 0.04)
+```
+
+Both switches are global and `UseHex` wins if both are active.
+
## Why is my linked stylesheet not loaded?
Most commonly, resource loading is not enabled. For external stylesheets, configure a requester and enable resource loading.
diff --git a/src/AngleSharp.Css.Tests/Library/StringRepresentation.cs b/src/AngleSharp.Css.Tests/Library/StringRepresentation.cs
index 31d97cfd..497a4122 100644
--- a/src/AngleSharp.Css.Tests/Library/StringRepresentation.cs
+++ b/src/AngleSharp.Css.Tests/Library/StringRepresentation.cs
@@ -16,6 +16,13 @@ namespace AngleSharp.Css.Tests.Library
[TestFixture]
public class StringRepresentationTests
{
+ [TearDown]
+ public void ResetColorSerialization()
+ {
+ CssColorValue.UseHex = false;
+ CssColorValue.UseSpecSerialization = false;
+ }
+
[Test]
public void PrettyStyleFormatterStringifyShouldWork_Issue41()
{
@@ -50,6 +57,62 @@ public void TransparentColorWorksWithHexOutput_Issue132()
Assert.AreEqual("#410C300A", text);
}
+ [Test]
+ public void OpaqueColorKeepsTheAlphaChannelByDefault_Issue227()
+ {
+ var color = new CssColorValue(65, 12, 48);
+ Assert.AreEqual("rgba(65, 12, 48, 1)", color.CssText);
+ }
+
+ [Test]
+ public void OpaqueColorDropsTheAlphaChannelWithSpecOutput_Issue227()
+ {
+ var color = new CssColorValue(65, 12, 48);
+ CssColorValue.UseSpecSerialization = true;
+ Assert.AreEqual("rgb(65, 12, 48)", color.CssText);
+ }
+
+ [Test]
+ public void TransparentColorKeepsTheAlphaChannelWithSpecOutput_Issue227()
+ {
+ var color = new CssColorValue(65, 12, 48, 128);
+ CssColorValue.UseSpecSerialization = true;
+ Assert.AreEqual("rgba(65, 12, 48, 0.5)", color.CssText);
+ }
+
+ [Test]
+ public void OpaqueColorPrefersHexOutputOverSpecOutput_Issue227()
+ {
+ var color = new CssColorValue(65, 12, 48);
+ CssColorValue.UseHex = true;
+ CssColorValue.UseSpecSerialization = true;
+ Assert.AreEqual("#410C30", color.CssText);
+ }
+
+ [Test]
+ public void TransparentColorPrefersHexOutputOverSpecOutput_Issue227()
+ {
+ var color = new CssColorValue(65, 12, 48, 10);
+ CssColorValue.UseHex = true;
+ CssColorValue.UseSpecSerialization = true;
+ Assert.AreEqual("#410C300A", color.CssText);
+ }
+
+ [Test]
+ public void CurrentColorIsNotAffectedBySpecOutput_Issue227()
+ {
+ CssColorValue.UseSpecSerialization = true;
+ Assert.AreEqual("currentColor", CssColorValue.CurrentColor.CssText);
+ }
+
+ [Test]
+ public void DeclarationUsesSpecOutputForOpaqueColors_Issue227()
+ {
+ CssColorValue.UseSpecSerialization = true;
+ var declaration = ParseDeclaration("color: rgba(255, 0, 0, 1)");
+ Assert.AreEqual("color: rgb(255, 0, 0)", declaration.CssText);
+ }
+
[Test]
public void ShorthandPaddingInheritPropertiesShouldBeIncluded_Issue100()
{
diff --git a/src/AngleSharp.Css/Values/Primitives/CssColorValue.cs b/src/AngleSharp.Css/Values/Primitives/CssColorValue.cs
index 5caa2fb2..46be0a84 100644
--- a/src/AngleSharp.Css/Values/Primitives/CssColorValue.cs
+++ b/src/AngleSharp.Css/Values/Primitives/CssColorValue.cs
@@ -469,6 +469,12 @@ public static CssColorValue FromHwba(Double h, Double w, Double b, Double alpha)
///
public static Boolean UseHex { get; set; }
+ ///
+ /// Gets or sets if the CSSOM serialization rules should be used, i.e.,
+ /// if the alpha channel of an opaque color should be omitted.
+ ///
+ public static Boolean UseSpecSerialization { get; set; }
+
///
/// Gets the CSS text representation.
///
@@ -495,6 +501,17 @@ public String CssText
return color;
}
+ else if (UseSpecSerialization && _alpha == 255)
+ {
+ var fn = FunctionNames.Rgb;
+ var args = String.Join(", ", new[]
+ {
+ R.ToString(CultureInfo.InvariantCulture),
+ G.ToString(CultureInfo.InvariantCulture),
+ B.ToString(CultureInfo.InvariantCulture),
+ });
+ return fn.CssFunction(args);
+ }
else
{
var fn = FunctionNames.Rgba;