@@ -174,7 +174,7 @@ Gradients {#gradients}
174
174
175
175
A gradient is an image that smoothly fades from one color to another.
176
176
These are commonly used for subtle shading in background images, buttons, and many other things.
177
- The gradient notations described in this section allow an author to specify such an image in a terse syntax,
177
+ The <dfn export lt=" gradient function">gradient functions</dfn> described in this section allow an author to specify such an image in a terse syntax,
178
178
so that the UA can generate the image automatically when rendering the page.
179
179
The syntax of a <<gradient>> is:
180
180
@@ -766,93 +766,236 @@ Repeating Gradients: the ''repeating-linear-gradient()'' and ''repeating-radial-
766
766
-->
767
767
768
768
769
- Gradient Color-Stops {#color-stop-syntax }
770
- -----------------------------------------
769
+ Defining Gradient Color {#gradient-colors }
770
+ -------------------------
771
771
772
- <pre class=prod>
773
- <dfn><color-stop-list></dfn> = <<color-stop>> #{2,}
774
- <dfn><color-stop></dfn> = <<color>> <<length-percentage>> ?
775
- </pre>
772
+ The colors in gradients are specified using <dfn export lt="color stop">color stops</dfn>
773
+ (a <<color>> and a corresponding position on the [=gradient line=] )
774
+ and <dfn export lt="color transition hint" local-lt="transition hint">color transition hints</dfn>
775
+ (a position between two [=color stops=]
776
+ representing the halfway point in the color transition)
777
+ which are placed on the <a>gradient line</a> ,
778
+ defining the color at every point of the line.
779
+ (Each [=gradient function=] defines the shape and length of the <a>gradient line</a> ,
780
+ along with its <a>starting point</a> and <a>ending point</a> ;
781
+ see above.)
782
+
783
+ <h4 id=color-stop-syntax>
784
+ Color Stop Lists</h4>
776
785
777
- The colors in gradients are specified using <a>color stops</a> .
778
- A <dfn export>color stop</dfn> is a combination of a color and a position.
779
- <!-- UNCOMMENT FOR L4
780
- Depending on the type of gradient, that position can be a length, angle, or percentage.
781
- -->
782
- While every color stop conceptually has a position,
783
- the position can be omitted in the syntax,
784
- in which case it gets automatically filled in by the user agent;
785
- see below for details.
786
-
787
- The color stops for a gradient are specified
786
+
787
+ <a>Color stops</a> and [=transition hints=] are specified
788
788
in a <dfn export>color stop list</dfn> ,
789
- which is a list of two or more <a> color stops</a> ,
790
- specified in geometric order.
789
+ which is a list of two or more [= color stops=]
790
+ interleaved with optional [=transition hints=] :
791
791
792
- <a>Color stops</a> are placed on a <a>gradient line</a> ,
793
- which defines the colors at every point of a gradient.
794
- The gradient function defines the shape and length of the <a>gradient line</a> ,
795
- along with its <a>starting point</a> and <a>ending point</a> .
792
+ <pre class=prod>
793
+ <dfn><color-stop-list></dfn> =
794
+ <<linear-color-stop>> , [ <<linear-color-hint>> ? , <<linear-color-stop>> ]#
795
+ <dfn><linear-color-stop></dfn> = <<color>> && <<length-percentage>> ?
796
+ <dfn><linear-color-hint></dfn> = <<length-percentage>>
797
+ </pre>
796
798
797
- Percentages refer to the length of the <a>gradient line</a>
799
+ Percentages are resolved against the length of the <a>gradient line</a>
798
800
between the <a>starting point</a> and <a>ending point</a> ,
799
801
with 0% being at the starting point
800
802
and 100% being at the ending point.
801
803
Lengths are measured along the <a>gradient line</a>
802
804
from the <a>starting point</a>
803
805
in the direction of the <a>ending point</a> .
804
- <!-- UNCOMMENT FOR L4
805
- Angles are measured with 0deg pointing up,
806
- and positive angles corresponding to clockwise rotations from there.
807
- -->
808
806
809
- <a>Color stops</a> are usually placed between
807
+ [=Color stop=] and [=transition hint=] positions
808
+ are usually placed between
810
809
the <a>starting point</a> and <a>ending point</a> ,
811
810
but that's not required:
812
811
the gradient line extends infinitely in both directions,
813
- and a <a>color stop</a> can be placed at any position on the <a>gradient line</a> .
814
-
815
- When the position of a <a>color stop</a> is omitted,
816
- it is positioned automatically
817
- halfway between the two surrounding stops.
812
+ and positions can be specified anywhere
813
+ on the <a>gradient line</a> .
814
+
815
+ When the position of a [=color stop=] is omitted,
816
+ it is automatically assigned a position.
817
+ The first or last [=color stop=] in the [=color stop list=]
818
+ is assigned
819
+ the [=gradient line’s=] [=starting point=] or [=ending point=]
820
+ (respectively).
821
+ Otherwise,
822
+ it's assigned the position halfway between the two surrounding stops.
818
823
If multiple stops in a row lack a position,
819
- they space themselves out equally.
820
-
821
- The following steps must be applied <em> in order</em> to process the list of <a>color stops</a> .
822
- After applying these rules,
823
- all <a>color stops</a> will have a definite position and color
824
- and they will be in ascending order:
825
-
826
- 1. If the first <a>color stop</a> does not have a position,
827
- set its position to 0%.
828
- If the last <a>color stop</a> does not have a position,
829
- set its position to 100%.
824
+ they space themselves out equally
825
+ between the surrounding positioned stops.
826
+ See [[#color-stop-fixup]] for details.
830
827
831
- 2. If a <a>color stop</a> has a position that is less than
832
- the specified position of any <a>color stop</a> before it in the list,
833
- set its position to be equal to the largest specified position of any <a>color stop</a> before it.
834
828
835
- 3. If any <a>color stop</a> still does not have a position,
836
- then, for each run of adjacent <a>color stops</a> without positions,
837
- set their positions so that they are evenly spaced between the preceding and following <a>color stops</a> with positions.
829
+ <h4 id=coloring-gradient-line>
830
+ Coloring the Gradient Line</h4>
838
831
839
832
At each <a>color stop</a> position,
840
- the line is the color of the <a>color stop</a> .
841
- Between two <a>color stops</a> ,
842
- the line's color is linearly interpolated between the colors of the two <a>color stops</a> ,
843
- with the interpolation taking place in premultiplied RGBA space.
833
+ the [=gradient line=] is the color of the <a>color stop</a> .
844
834
Before the first <a>color stop</a> ,
845
- the line is the color of the first <a>color stop</a> .
846
- After the last <a>color stop</a> , the line is the color of the last <a>color stop</a> .
835
+ the [=gradient line=] is the color of the first <a>color stop</a> ,
836
+ and after the last <a>color stop</a> ,
837
+ the [=gradient line=] is the color of the last <a>color stop</a> .
838
+ Between two <a>color stops</a> ,
839
+ the [=gradient line’s=] color is interpolated between the colors of the two <a>color stops</a> ,
840
+ with the interpolation taking place in <a href="#premultiplied">premultiplied RGBA space</a> .
841
+
842
+ By default,
843
+ this interpolation is linear--
844
+ at 25%, 50%, or 75% of the distance between two <a>color stops</a> ,
845
+ the color is a 25%, 50%, or 75% blend of the colors of the two stops.
846
+
847
+ However, if a [=transition hint=] was provided between two <a>color stops</a> ,
848
+ the interpolation is non-linear,
849
+ and controlled by the hint:
850
+
851
+ <div algorithm="interpolate with a color hint">
852
+ <ol>
853
+ <li>
854
+ Determine the location of the [=transition hint=] as a percentage of the distance between the two <a>color stops</a> ,
855
+ denoted as a number between 0 and 1,
856
+ where 0 indicates the hint is placed right on the first <a>color stop</a> ,
857
+ and 1 indicates the hint is placed right on the second <a>color stop</a> .
858
+ Let this percentage be <var> H</var> .
859
+
860
+ <li>
861
+ For any given point between the two color stops,
862
+ determine the point's location as a percentage of the distance between the two <a>color stops</a> ,
863
+ in the same way as the previous step.
864
+ Let this percentage be <var> P</var> .
865
+
866
+ <li>
867
+ Let <var> C</var> , the color weighting at that point,
868
+ be equal to <code><var> P</var><sup> log<sub><var> H</var></sub> (.5)</sup></code> .
869
+
870
+ <li>
871
+ The color at that point is then a linear blend between the colors of the two <a>color stops</a> ,
872
+ blending <code> (1 - <var> C</var> )</code> of the first stop and <var> C</var> of the second stop.
873
+ </ol>
874
+ </div>
875
+
876
+ Note: The [=transition hint=] specifies where the “halfway color”--
877
+ the 50% blend between the colors of the two surrounding color stops--
878
+ should be placed.
879
+ When the hint is exactly halfway between the two surrounding color stops,
880
+ the above interpolation algorithm
881
+ happens to produce the ordinary linear interpolation.
882
+ If the hint is placed anywhere else,
883
+ it produces a smooth exponential curve
884
+ between the surrounding color stops,
885
+ with the “halfway color” occuring exactly where the hint specifies.
886
+
887
+ Issue: Add a visual example of a color hint being used.
847
888
848
889
If multiple <a>color stops</a> have the same position,
849
- they produce an infinitesimal transition from the one specified first in the rule
890
+ they produce an infinitesimal transition from the one specified first in the list
850
891
to the one specified last.
851
892
In effect, the color suddenly changes at that position rather than smoothly transitioning.
852
893
894
+ <details class=note id=premultiplied>
895
+ <summary> What does “pre-multiplied” mean?</summary>
896
+
897
+ A “pre-multiplied” color
898
+ is written in a form
899
+ where the alpha channel
900
+ is multiplied into the color channels,
901
+ rather than being processed independently.
902
+ For example, a partially-transparent blue may be given as <code class=lang-css><nobr> rgba(0, 0, 255, .5)</nobr></code> ,
903
+ which would then be expressed as <code><nobr> [0, 0, 127.5, .5] </nobr></code> in its premultiplied representation.
904
+
905
+ Interpolating colors using the premultiplied representations
906
+ rather than the plain rgba representations
907
+ tends to produce more attractive transitions,
908
+ particularly when transitioning from a fully opaque color to fully transparent.
909
+
910
+ Note that transitions where either the transparency or the color are held constant
911
+ (for example, transitioning between <code class=lang-css><nobr> rgba(255, 0, 0, 100%)</nobr></code> (opaque red)
912
+ and <code class=lang-css><nobr> rgba(0,0,255,100%)</nobr></code> (opaque blue),
913
+ or <code class=lang-css><nobr> rgba(255,0,0,100%)</nobr></code> (opaque red)
914
+ and <code class=lang-css><nobr> rgba(255,0,0,0%)</nobr></code> (transparent red))
915
+ have identical results whether the color interpolation is done in premultiplied or non-premultiplied color-space.
916
+ Differences only arise when <em> both</em> the color and transparency differ between the two endpoints.
917
+
918
+ <div class=example>
919
+ The following example illustrates the difference between
920
+ a gradient transitioning in pre-multiplied sRGBA
921
+ and one transitioning (incorrectly) in non-premultiplied.
922
+ In both of these example,
923
+ the gradient is drawn over a white background.
924
+ Both gradients could be written with the following value:
925
+
926
+ <pre> linear-gradient(90deg, red, transparent, blue)</pre>
927
+
928
+ With premultiplied colors,
929
+ transitions to or from "transparent" always look nice:
930
+
931
+ <object data="images/gradient2.svg" width="200"height="100"> (Image requires SVG)</object>
932
+
933
+ On the other hand,
934
+ if a gradient were to incorrectly transition in non-premultiplied space,
935
+ the center of the gradient would be a noticeably grayish color,
936
+ because "transparent" is actually a shorthand for ''rgba(0,0,0,0)'' , or transparent black,
937
+ meaning that the red transitions to a black
938
+ as it loses opacity,
939
+ and similarly with the blue's transition:
940
+
941
+ <object data="images/gradient3.svg" width="200"height="100"> (Image requires SVG)</object>
942
+ </div>
943
+
944
+ </details>
945
+
946
+
947
+
948
+ <h4 id=color-stop-fixup>
949
+ Color Stop “Fixup”</h4>
950
+
951
+ When resolving the [=used value|used=] positions of each [=color stop=] ,
952
+ the following steps must be applied <em> in order</em> :
953
+
954
+ <ol>
955
+ <li>
956
+ If the first <a>color stop</a> does not have a position,
957
+ set its position to 0%.
958
+ If the last <a>color stop</a> does not have a position,
959
+ set its position to 100%.
960
+
961
+ <li>
962
+ If a <a>color stop</a> or [=transition hint=] has a position
963
+ that is less than the specified position
964
+ of any <a>color stop</a> or [=transition hint=] before it in the list,
965
+ set its position to be equal to the largest specified position
966
+ of any <a>color stop</a> or [=transition hint=] before it.
967
+
968
+ <li>
969
+ If any <a>color stop</a> still does not have a position,
970
+ then, for each run of adjacent <a>color stops</a> without positions,
971
+ set their positions so that they are evenly spaced
972
+ between the preceding and following <a>color stops</a> with positions.
973
+ </ol>
974
+
975
+ After applying these rules,
976
+ all [=color stops=] and [=transition hints=] will have a definite position and color
977
+ and they will be in ascending order.
978
+
979
+ Note: It is recommended that authors exercise caution
980
+ when mixing different types of units,
981
+ such as px, em, or %,
982
+ as this can cause a <a>color stop</a> to unintentionally try to move before an earlier one.
983
+ For example,
984
+ the rule ''background-image: linear-gradient(yellow 100px, blue 50%)''
985
+ wouldn't trigger any fix-up while the background area is at least ''200px'' tall.
986
+ If it was ''150px'' tall, however,
987
+ the blue <a>color stop's</a> position would be equivalent to ''75px'' ,
988
+ which precedes the yellow <a>color stop</a> ,
989
+ and would be corrected to a position of ''100px'' .
990
+ Additionally, since the relative ordering of such color stops
991
+ cannot be determined without performing layout,
992
+ they will not interpolate smoothly in
993
+ <a href="http://www.w3.org/TR/css-animations/">animations</a>
994
+ or <a href="http://www.w3.org/TR/css-transitions/">transitions</a> .
995
+
853
996
<div class=example>
854
997
Below are several pairs of gradients.
855
- The latter of each pair is a manually " fixed-up" version of the former,
998
+ The latter of each pair is a manually “ fixed-up” version of the former,
856
999
obtained by applying the above rules.
857
1000
For each pair, both gradients will render identically.
858
1001
<span class='note'> The numbers in each arrow specify which fixup steps are invoked in the transformation.</span>
@@ -863,86 +1006,31 @@ Gradient Color-Stops {#color-stop-syntax}
863
1006
linear-gradient(red 0%, white 20%, blue 100%)
864
1007
865
1008
2. linear-gradient(red 40%, white, black, blue)
866
- =13 =>
1009
+ =1,3 =>
867
1010
linear-gradient(red 40%, white 60%, black 80%, blue 100%)
868
1011
869
1012
3. linear-gradient(red -50%, white, blue)
870
- =13 =>
1013
+ =1,3 =>
871
1014
linear-gradient(red -50%, white 25%, blue 100%)
872
1015
873
1016
4. linear-gradient(red -50px, white, blue)
874
- =13 =>
1017
+ =1,3 =>
875
1018
linear-gradient(red -50px, white calc(-25px + 50%), blue 100%)
876
1019
877
1020
5. linear-gradient(red 20px, white 0px, blue 40px)
878
1021
=2=>
879
1022
linear-gradient(red 20px, white 20px, blue 40px)
880
1023
881
1024
6. linear-gradient(red, white -50%, black 150%, blue)
882
- =12 =>
1025
+ =1,2 =>
883
1026
linear-gradient(red 0%, white 0%, black 150%, blue 150%)
884
1027
885
1028
7. linear-gradient(red 80px, white 0px, black, blue 100px)
886
- =23 =>
1029
+ =2,3 =>
887
1030
linear-gradient(red 80px, white 80px, black 90px, blue 100px)
888
1031
</pre>
889
1032
</div>
890
1033
891
- <div class=example>
892
- The following example illustrates the difference between
893
- a gradient transitioning in pre-multiplied sRGBA
894
- and one transitioning (incorrectly) in non-premultiplied.
895
- In both of these example,
896
- the gradient is drawn over a white background.
897
- Both gradients could be written with the following value:
898
-
899
- <pre> linear-gradient(90deg, red, transparent, blue)</pre>
900
-
901
- In premultiplied space,
902
- transitions to or from "transparent" always look nice:
903
-
904
- <object data="images/gradient2.svg" width="200"height="100"> (Image requires SVG)</object>
905
-
906
- On the other hand,
907
- if a gradient were to incorrectly transition in non-premultiplied space,
908
- the colors near "transparent" would noticeably darken to a grayish color,
909
- because "transparent" is actually a shorthand for ''rgba(0,0,0,0)'' , or transparent black:
910
-
911
- <object data="images/gradient3.svg" width="200"height="100"> (Image requires SVG)</object>
912
- </div>
913
-
914
- Note: It is recommended that authors not mix different types of units,
915
- such as px, em, or %,
916
- in a single rule,
917
- as this can cause a <a>color stop</a> to unintentionally try to move before an earlier one.
918
- For example, the rule ''background-image: linear-gradient(yellow 100px, blue 50%)''
919
- wouldn't require any fix-up as long as the background area is at least 200px tall.
920
- If it was 150px tall, however,
921
- the blue <a>color stop's</a> position would be equivalent to "75px",
922
- which precedes the yellow <a>color stop</a> ,
923
- and would be corrected to a position of 100px.
924
- Additionally, since the relative ordering of such color stops
925
- cannot be determined without performing layout,
926
- they will not interpolate smoothly in
927
- <a href="http://www.w3.org/TR/css-animations/">animations</a>
928
- or <a href="http://www.w3.org/TR/css-transitions/">transitions</a> .
929
-
930
- Note: The definition and implications of "premultiplied" color spaces are given elsewhere in the technical literature,
931
- but a quick primer is given here to illuminate the process.
932
- Given a color expressed as an rgba() 4-tuple,
933
- one can convert this to a premultiplied representation
934
- by multiplying the red, green, and blue components by the alpha component.
935
- For example, a partially-transparent blue may be given as rgba(0,0,255,.5),
936
- which would then be expressed as [0, 0, 127.5, .5] in its premultiplied representation.
937
- Interpolating colors using the premultiplied representations
938
- rather than the plain rgba representations
939
- tends to produce more attractive transitions,
940
- particularly when transitioning from a fully opaque color to fully transparent.
941
- Note that transitions where either the transparency or the color are held constant
942
- (for example, transitioning between rgba(255,0,0,100%) and rgba(0,0,255,100%),
943
- or rgba(255,0,0,100%) and rgba(255,0,0,0%))
944
- have identical results whether the color interpolation is done in premultiplied or non-premultiplied color-space.
945
- Differences only arise when both the color and transparency differ between the two endpoints.
946
1034
947
1035
948
1036
<!--
0 commit comments