diff --git a/.vscode/dictionaries/code-entities.txt b/.vscode/dictionaries/code-entities.txt index 372a2c8ce370fd7..aeaed2ab3fd0c50 100644 --- a/.vscode/dictionaries/code-entities.txt +++ b/.vscode/dictionaries/code-entities.txt @@ -384,6 +384,7 @@ longtask lowdelay lowp lquote +LRGB ltrh makemigrations mathbb diff --git a/.vscode/dictionaries/ignore-list.txt b/.vscode/dictionaries/ignore-list.txt index c917ff7a69435db..b9874c637d256a7 100644 --- a/.vscode/dictionaries/ignore-list.txt +++ b/.vscode/dictionaries/ignore-list.txt @@ -161,9 +161,11 @@ Graece gubergren harborside hellonode +HEXA HEXDIG howtoplay HUD5767ghtyfyr4536dh45dg45dg3 +HWBA idbkeyrange IHdhcyBncmVhdCE innerht.ml @@ -323,6 +325,7 @@ Whereami Whereshire wisi Wookie +XYZD xyzzy YOUREXT YsAIAAAA-QG4G6kCMAMBAAAAAAAoK diff --git a/files/en-us/_redirects.txt b/files/en-us/_redirects.txt index 14a78b95871fea8..42721fa05e47c2e 100644 --- a/files/en-us/_redirects.txt +++ b/files/en-us/_redirects.txt @@ -12252,6 +12252,7 @@ /en-US/docs/Web/CSS/CSS_cascade/specified_value /en-US/docs/Web/CSS/CSS_cascade/Value_processing#specified_value /en-US/docs/Web/CSS/CSS_cascade/used_value /en-US/docs/Web/CSS/CSS_cascade/Value_processing#used_value /en-US/docs/Web/CSS/CSS_charsets /en-US/docs/Web/CSS/CSS_syntax +/en-US/docs/Web/CSS/CSS_colors/Color_picker_tool /en-US/docs/Web/CSS/CSS_colors/Color_picker /en-US/docs/Web/CSS/CSS_container_queries /en-US/docs/Web/CSS/CSS_containment/Container_queries /en-US/docs/Web/CSS/CSS_descriptor_definition /en-US/docs/Web/CSS /en-US/docs/Web/CSS/CSS_display/flow_layout/Block_and_inline_layout_in_normal_flow /en-US/docs/Web/CSS/CSS_display/Block_and_inline_layout_in_normal_flow @@ -12330,7 +12331,7 @@ /en-US/docs/Web/CSS/Tools/Border-image_generator /en-US/docs/Web/CSS/CSS_backgrounds_and_borders/Border-image_generator /en-US/docs/Web/CSS/Tools/Border-radius_generator /en-US/docs/Web/CSS/CSS_backgrounds_and_borders/Border-radius_generator /en-US/docs/Web/CSS/Tools/Box-shadow_generator /en-US/docs/Web/CSS/CSS_backgrounds_and_borders/Box-shadow_generator -/en-US/docs/Web/CSS/Tools/ColorPicker_Tool /en-US/docs/Web/CSS/CSS_colors/Color_picker_tool +/en-US/docs/Web/CSS/Tools/ColorPicker_Tool /en-US/docs/Web/CSS/CSS_colors/Color_picker /en-US/docs/Web/CSS/Understanding_CSS_z-index /en-US/docs/Web/CSS/CSS_positioned_layout/Understanding_z-index /en-US/docs/Web/CSS/Understanding_CSS_z-index/Adding_z-index /en-US/docs/Web/CSS/CSS_positioned_layout/Using_z-index /en-US/docs/Web/CSS/Understanding_CSS_z-index/Stacking_and_float /en-US/docs/Web/CSS/CSS_positioned_layout/Stacking_floating_elements diff --git a/files/en-us/_wikihistory.json b/files/en-us/_wikihistory.json index c53bd988bebd4b9..d703ccbee67c884 100644 --- a/files/en-us/_wikihistory.json +++ b/files/en-us/_wikihistory.json @@ -75899,7 +75899,7 @@ "chrisdavidmills" ] }, - "Web/CSS/CSS_colors/Color_picker_tool": { + "Web/CSS/CSS_colors/Color_picker": { "modified": "2020-10-30T22:49:32.596Z", "contributors": [ "td2014", diff --git a/files/en-us/learn_web_development/getting_started/your_first_website/what_will_your_website_look_like/index.md b/files/en-us/learn_web_development/getting_started/your_first_website/what_will_your_website_look_like/index.md index d2b7cd0a3bc5fcb..9a85935e63fe8bc 100644 --- a/files/en-us/learn_web_development/getting_started/your_first_website/what_will_your_website_look_like/index.md +++ b/files/en-us/learn_web_development/getting_started/your_first_website/what_will_your_website_look_like/index.md @@ -61,7 +61,7 @@ At this point, it's good to start putting together the content that will eventua Let's choose a background color for your page. -1. Go to [the Color Picker](/en-US/docs/Web/CSS/CSS_colors/Color_picker_tool) and find a color you like. +1. Go to [the Color Picker](/en-US/docs/Web/CSS/CSS_colors/Color_picker) and find a color you like. 2. When you click on a color, you'll see a strange six-character code like `#660066`. That's called a _hex code_ (short for hexadecimal), and represents your color. Copy the code down somewhere safe for now. ![Color-Picker-Tool on MDN Docs website with RGB, HSL, and HEX colors ](color-picker.png) diff --git a/files/en-us/web/css/color_value/color/index.md b/files/en-us/web/css/color_value/color/index.md index 7de55a5436329b4..2e090a9173edc56 100644 --- a/files/en-us/web/css/color_value/color/index.md +++ b/files/en-us/web/css/color_value/color/index.md @@ -383,7 +383,7 @@ The output is as follows: - {{CSSXref("color")}} property - [The `` data type](/en-US/docs/Web/CSS/color_value) for a list of all color notations - [Using relative colors](/en-US/docs/Web/CSS/CSS_colors/Relative_colors) -- [sRGB color picker and conversion tool](/en-US/docs/Web/CSS/CSS_colors/Color_picker_tool) +- [sRGB color picker and conversion tool](/en-US/docs/Web/CSS/CSS_colors/Color_picker) - [CSS colors](/en-US/docs/Web/CSS/CSS_colors) module - [`color-gamut`](/en-US/docs/Web/CSS/@media/color-gamut) media feature - [Wide Gamut Color in CSS with Display-p3](https://webkit.org/blog/10042/wide-gamut-color-in-css-with-display-p3/) diff --git a/files/en-us/web/css/color_value/hsl/index.md b/files/en-us/web/css/color_value/hsl/index.md index 313ed900c7e2e37..938fde36ff51c56 100644 --- a/files/en-us/web/css/color_value/hsl/index.md +++ b/files/en-us/web/css/color_value/hsl/index.md @@ -401,7 +401,7 @@ div.legacyHSLA { - [`lch()`](/en-US/docs/Web/CSS/color_value/lch) and [`hwb()`](/en-US/docs/Web/CSS/color_value/hwb) color functions - [Hue interpolation in `color-mix()`](/en-US/docs/Web/CSS/color_value/color-mix#using_hue_interpolation_in_color-mix) - [List of all color notations](/en-US/docs/Web/CSS/color_value) -- [sRGB color picker and conversion tool](/en-US/docs/Web/CSS/CSS_colors/Color_picker_tool) +- [sRGB color picker and conversion tool](/en-US/docs/Web/CSS/CSS_colors/Color_picker) - [Using relative colors](/en-US/docs/Web/CSS/CSS_colors/Relative_colors) - [CSS colors](/en-US/docs/Web/CSS/CSS_colors) module - [Color picker tool](https://apps.colorjs.io/picker/) by Lea Verou diff --git a/files/en-us/web/css/color_value/hwb/index.md b/files/en-us/web/css/color_value/hwb/index.md index 8e899c0d807880d..68b25090d6b9a70 100644 --- a/files/en-us/web/css/color_value/hwb/index.md +++ b/files/en-us/web/css/color_value/hwb/index.md @@ -275,7 +275,7 @@ The output is as follows: ## See also - {{CSSXref("<color>")}}: For a list of all color notations -- [Color picker and conversion tool](/en-US/docs/Web/CSS/CSS_colors/Color_picker_tool) +- [Color picker and conversion tool](/en-US/docs/Web/CSS/CSS_colors/Color_picker) - [Using relative colors](/en-US/docs/Web/CSS/CSS_colors/Relative_colors) - [CSS colors](/en-US/docs/Web/CSS/CSS_colors) module - {{CSSXref("<hue>")}}: the data type representing a hue angle of a color diff --git a/files/en-us/web/css/color_value/rgb/index.md b/files/en-us/web/css/color_value/rgb/index.md index 20281ddd9d92b34..642685e7a4e550f 100644 --- a/files/en-us/web/css/color_value/rgb/index.md +++ b/files/en-us/web/css/color_value/rgb/index.md @@ -343,6 +343,6 @@ div.comma-separated { ## See also - The {{CSSXref("<color>")}} data type for a list of all color notations -- [sRGB color picker and conversion tool](/en-US/docs/Web/CSS/CSS_colors/Color_picker_tool) +- [sRGB color picker and conversion tool](/en-US/docs/Web/CSS/CSS_colors/Color_picker) - [Using relative colors](/en-US/docs/Web/CSS/CSS_colors/Relative_colors) - [CSS colors](/en-US/docs/Web/CSS/CSS_colors) module diff --git a/files/en-us/web/css/css_colors/color_mixer/index.md b/files/en-us/web/css/css_colors/color_mixer/index.md new file mode 100644 index 000000000000000..95de8ee864c8154 --- /dev/null +++ b/files/en-us/web/css/css_colors/color_mixer/index.md @@ -0,0 +1,836 @@ +--- +title: Color mixer +slug: Web/CSS/CSS_colors/Color_mixer +page-type: guide +sidebar: cssref +--- + +This tool lets you mix two colors in any color space using the {{cssxref("color_value/color-mix")}} function and copy the resulting color in any CSS color format. The two input colors, `color-one` and `color-two`, are shown on the outside, and the mixed color returned by the function is shown in the middle. Click on the outer swatches to select new colors to mix. Use the sliders to change the percentages of each input color included in the mix. Use the drop-down menu to change the color space of the function's output. CSS color values for the resulting color are selectable below the color widget. + +```html hidden live-sample___color-mixer +
+

Color mixer

+

Click on 'color-one' and 'color-two' to change the input colors.

+ +
color-one
+
mixed-color
+
color-two
+ +
+ +
+ +
+
+ + +
+
+ + +
+ + + + + + +
+ +
Pick a color
+ + + + + + + + + + + + + +
+ +
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ The output color in various CSS color syntaxes: +
Hexadecimal
RGB
color(srgb)
HSL
HWB
Lab
Oklab
LCH
OkLCh
XYZ D50
XYZ D65
+``` + +```css hidden live-sample___color-mixer +#picker-dialog[open] { + position: fixed; + top: 30%; + z-index: 100; + padding: 1rem; + width: 70vw; + background: #ddd; + display: flex; + flex-flow: column; + align-items: center; +} + +#picker-dialog #color-opacity { + width: 200px; +} + +#picker-dialog > div:first-child { + font-weight: bold; + margin-bottom: 1rem; +} + +#picker-dialog > div { + width: max-content; + margin: 0.4rem auto; + white-space: nowrap; +} + +#picker-dialog #color-text { + width: 200px; +} + +#picker-dialog label { + margin: 1rem 0; +} + +#picker-dialog button { + width: 100px; + margin-top: 1rem; +} + +dialog#picker-dialog table { + width: fit-content; +} + +#color-mixer { + margin: 0.5rem; + font-family: sans-serif; + display: grid; + grid-template-columns: 150px 1fr 1fr 150px; + grid-template-areas: + "header header header header" + "text text text text" + "color-one-label mix-label mix-label color-two-label" + "color-background color-background color-background color-background" + "percent-one percent-one percent-two percent-two" + "color-space-label color-space interpolation-label interpolation" + "mix-output-text mix-output-text mix-output-text mix-output-text"; +} + +#color-mixer > * { + padding: 0; + margin: 0 auto; +} + +#color-mixer > :nth-child(1) { + grid-area: header; +} + +#color-mixer > :nth-child(2) { + grid-area: text; + margin-bottom: 2rem; +} + +#color-mixer > :nth-child(3) { + grid-area: color-one-label; +} + +#color-mixer > :nth-child(4) { + grid-area: mix-label; +} + +#color-mixer > :nth-child(5) { + grid-area: color-two-label; +} + +#color-mixer > :nth-child(6) { + grid-area: color-background; + background: + linear-gradient( + 0deg, + transparent 0 38%, + 47%, + rgb(0 0 0 / 0.7) 50%, + white 50% 100% + ), + conic-gradient( + black 0 90deg, + transparent 90deg 180deg, + black 180deg 270deg, + transparent 270deg 360deg + ); + background-size: + 100% 100%, + 20px 20px; + display: flex; + align-items: center; + margin: 0; + padding: 0; + border-radius: 10% 10% 10% 10%; +} + +#color-one { + height: 100px; + flex: 1 1 100%; + border-radius: 20% 0 0 20%; + cursor: pointer; + border: none; + z-index: 1; + box-shadow: -5px 5px 5px grey; + background-color: #ff7f50; +} + +#mixed-color { + flex: 2 0.7 100%; + height: 100px; +} + +#color-two { + height: 100px; + flex: 1 1 100%; + border-radius: 0 20% 20% 0; + cursor: pointer; + border: none; + z-index: 1; + box-shadow: 5px 5px 5px grey; + background-color: #00ffff; +} + +#color-mixer > :nth-child(7) { + grid-area: percent-one; + width: 100%; + display: flex; +} + +#percentage-one-label, +#percentage-two-label { + width: 2rem; + text-align: end; +} + +#color-mixer > :nth-child(8) { + grid-area: percent-two; + width: 100%; + display: flex; +} + +#color-mixer > :nth-child(9) { + grid-area: color-space-label; + margin: 0.5rem 0 0 auto; +} + +#color-mixer > :nth-child(10) { + grid-area: color-space; + margin: 0.5rem auto 0 1rem; +} + +#color-mixer > :nth-child(11) { + grid-area: interpolation-label; + margin: 0.5rem 0 0 auto; +} + +#color-mixer > :nth-child(12) { + grid-area: interpolation; + margin: 0.5rem auto 0 1rem; +} + +#color-mixer > :nth-child(13) { + grid-area: mix-output-text; + margin: 1rem 0; + padding: 1rem 0; + text-align: center; + background-color: #dfdfde; + font-family: monospace; +} + +input[type="range"] { + width: 80%; +} + +label { + margin: 1rem; +} + +*:focus { + outline: 2px dashed purple; + outline-offset: 1px; +} + +table { + width: 100%; +} +caption { + font-family: sans-serif; +} +th { + padding: 5px 15px; + background-color: #ededed; +} +td { + background-color: #dedede; + font-family: monospace; + padding: 5px; +} + +#output-colors th { + padding-right: 0; + width: 20%; +} + +#output-colors td button { + margin-right: 0.4rem; +} +``` + +```js hidden live-sample___color-mixer +const root = document.querySelector(":root"); + +const colorSpace = document.getElementById("color-space"); +const interpolationMethod = document.getElementById("interpolation-method"); +const interpolationMethodLabel = document.getElementById( + "interpolation-method-label", +); + +const colorOneButton = document.getElementById("color-one"); +const colorTwoButton = document.getElementById("color-two"); +const mixedColorDiv = document.getElementById("mixed-color"); +const mixedOutputText = document.getElementById("mix-output-text"); + +const percentageOneLabel = document.getElementById("percentage-one-label"); +const percentageTwoLabel = document.getElementById("percentage-two-label"); +const percentageOneSlider = document.getElementById("percentage-one"); +const percentageTwoSlider = document.getElementById("percentage-two"); + +// pop up dialog elements +const pickerDialog = document.getElementById("picker-dialog"); +const colorTextInput = document.getElementById("color-text"); +const colorInput = document.getElementById("color-input"); +const colorOpacitySlider = document.getElementById("color-opacity"); +const pickerOkButton = document.getElementById("picker-ok-button"); + +// color output spans +const hexOutput = document.querySelector("#hex td > span"); +const colorFunctionOutput = document.querySelector("#color-function td > span"); +const rgbFunctionOutput = document.querySelector("#rgb-function td > span"); +const hslFunctionOutput = document.querySelector("#hsl-function td > span"); +const hwbFunctionOutput = document.querySelector("#hwb-function td > span"); +const labFunctionOutput = document.querySelector("#lab-function td > span"); +const oklabFunctionOutput = document.querySelector("#oklab-function td > span"); +const lchFunctionOutput = document.querySelector("#lch-function td > span"); +const oklchFunctionOutput = document.querySelector("#oklch-function td > span"); +const xyzD50FunctionOutput = document.querySelector( + "#xyz-d50-function td > span", +); +const xyzD65FunctionOutput = document.querySelector( + "#xyz-d65-function td > span", +); + +const LRGB_LMS_MATRIX = [ + [0.4122214708, 0.5363325363, 0.0514459929], + [0.2119034982, 0.6806995451, 0.1073969566], + [0.0883024619, 0.2817188376, 0.6299787005], +]; + +const LMS_LAB_MATRIX = [ + [+0.2104542553, +0.793617785, -0.0040720468], + [+1.9779984951, -2.428592205, +0.4505937099], + [+0.0259040371, +0.7827717662, -0.808675766], +]; + +// srgb-linear to xyz-d50 +// matrix taken from http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html +const LRGB_XYZ_D50_MATRIX = [ + [0.4360747, 0.3850649, 0.1430804], + [0.2225045, 0.7168786, 0.0606169], + [0.0139322, 0.0971045, 0.7141733], +]; + +// srgb-linear to xyz-d65 +// matrix taken from http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html +const LRGB_XYZ_D65_MATRIX = [ + [0.4124564, 0.3575761, 0.1804375], + [0.2126729, 0.7151522, 0.072175], + [0.0193339, 0.119192, 0.9503041], +]; + +const polarColorSpaces = ["hsl", "hwb", "lch", "oklch"]; +const colorOne = { r: 255, g: 127, b: 80, alpha: 1.0 }; +const colorTwo = { r: 0, g: 255, b: 255, alpha: 1.0 }; +let currentColor = null; + +function rgbToLinear(c) { + return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4); +} + +function intToHex(i) { + return Math.floor(i).toString(16).padStart(2, "0").toUpperCase(); +} + +function rgbToHEXText(c) { + return `#${intToHex(c.r)}${intToHex(c.g)}${intToHex(c.b)}`; +} + +function colorToRGBA(c) { + const ctx = new OffscreenCanvas(1, 1).getContext("2d"); + ctx.fillStyle = c; + ctx.fillRect(0, 0, 1, 1); + const data = ctx.getImageData(0, 0, 1, 1).data; + return { + r: data[0], + g: data[1], + b: data[2], + alpha: data[3] / 255, + }; +} + +function multiplyByMatrix(matrix, tuple) { + let i = [0, 0, 0]; + let j = matrix.length; + let k = matrix[0].length; + for (let l = 0; l < j; l++) + for (let m = 0; m < k; m++) i[l] += matrix[l][m] * tuple[m]; + return i; +} + +function rgbaToHEXAText(color) { + const hexText = rgbToHEXText(color); + if (color.alpha === 1.0) { + return hexText; + } + const alpha = intToHex(color.alpha * 255); + return `${hexText}${alpha}`; +} + +function rgbaToHSLA(color) { + let { r, g, b, a: alpha } = color; + // Let's have r, g, b in the range [0, 1] + r = r / 255; + g = g / 255; + b = b / 255; + const min = Math.min(r, g, b); + const max = Math.max(r, g, b); + const delta = max - min; + let h, s, l; + + if (delta === 0) { + h = 0; + } else if (max === r) { + h = ((g - b) / delta) % 6; + } else if (max === g) { + h = (b - r) / delta + 2; + } else h = (r - g) / delta + 4; + h = Math.round(h * 60); + + // We want an angle between 0 and 360° + if (h < 0) { + h += 360; + } + + l = (max + min) / 2; + s = delta === 0 ? 0 : delta / (1 - Math.abs(2 * l - 1)); + s = Number((s * 100).toFixed(1)); + l = Number((l * 100).toFixed(1)); + + return { h, s, l, alpha }; +} + +function toHSLAText(color) { + const { h, s, l, alpha } = rgbaToHSLA(color); + return `hsl(${h.toFixed(0)} ${s.toFixed(0)}% ${l.toFixed(0)}%${ + alpha < 1.0 ? ` / ${alpha.toFixed(3)}` : "" + })`; +} + +function rgbaToHWBAText(color) { + let { h, s, l, alpha } = rgbaToHSLA(color); + const chroma = s * (1 - Math.abs(l / 50 - 1)); + let W = (l - chroma / 2).toFixed(0); + let B = (100 - l - chroma / 2).toFixed(0); + return `hwb(${h} ${W}% ${B}%${alpha < 1.0 ? ` / ${alpha.toFixed(3)}` : ""})`; +} + +function rgbaToXYZD50(color) { + let { r, g, b, alpha } = color; + r = rgbToLinear(r / 255) * 255; + g = rgbToLinear(g / 255) * 255; + b = rgbToLinear(b / 255) * 255; + + const xyz = multiplyByMatrix(LRGB_XYZ_D50_MATRIX, [r, g, b]); + return { x: xyz[0] / 255, y: xyz[1] / 255, z: xyz[2] / 255, a: alpha }; +} + +function rgbaToXYZD50Text(color) { + let { alpha } = color; + const xyz = rgbaToXYZD50(color); + return `color(xyz-d50 ${xyz.x.toFixed(5)} ${xyz.y.toFixed(5)} ${xyz.z.toFixed( + 5, + )}${alpha < 1.0 ? ` / ${alpha.toFixed(3)}` : ""})`; +} + +function rgbaToXYZD65(color) { + let { r, g, b, alpha } = color; + r = rgbToLinear(r / 255) * 255; + g = rgbToLinear(g / 255) * 255; + b = rgbToLinear(b / 255) * 255; + + const xyz = multiplyByMatrix(LRGB_XYZ_D65_MATRIX, [r, g, b]); + return { x: xyz[0] / 255, y: xyz[1] / 255, z: xyz[2] / 255, a: alpha }; +} + +function rgbaToXYZD65Text(color) { + let { alpha } = color; + const xyz = rgbaToXYZD65(color); + return `color(xyz-d65 ${xyz.x.toFixed(5)} ${xyz.y.toFixed(5)} ${xyz.z.toFixed( + 5, + )}${alpha < 1.0 ? ` / ${alpha.toFixed(3)}` : ""})`; +} + +const D65 = [0.3457 / 0.3585, 1, 0.2958 / 0.3585]; +function xyzToLab(color) { + let { x, y, z, alpha } = color; + [x, y, z] = [x, y, z].map((v, i) => { + v = v / D65[i]; + return v > 0.0088564516 ? Math.cbrt(v) : v * 903.2962962962963 + 16 / 116; + }); + return { l: 116 * y - 16, a: 500 * (x - y), b: 200 * (y - z), alpha }; +} + +function rgbaToLabText(color) { + let { alpha } = color; + const xyz = rgbaToXYZD50(color); + const lab = xyzToLab(xyz); + return `lab(${lab.l.toFixed(3)} ${lab.a.toFixed(3)} ${lab.b.toFixed(3)}${ + alpha < 1.0 ? ` / ${alpha.toFixed(3)}` : "" + })`; +} + +function rgbToOklab(color) { + let { r, g, b, alpha } = color; + r = rgbToLinear(r / 255); + g = rgbToLinear(g / 255); + b = rgbToLinear(b / 255); + const lms = multiplyByMatrix(LRGB_LMS_MATRIX, [r, g, b]).map((v) => + Math.cbrt(v), + ); + + const oklab = multiplyByMatrix(LMS_LAB_MATRIX, lms); + return { l: oklab[0], a: oklab[1], b: oklab[2], a: alpha }; +} + +function toOkLabText(color) { + let { alpha } = color; + const oklab = rgbToOklab(color); + return `oklab(${oklab.l.toFixed(5)} ${oklab.a.toFixed(5)} ${oklab.b.toFixed( + 5, + )}${alpha < 1.0 ? ` / ${alpha.toFixed(3)}` : ""})`; +} + +function labToLCH(color) { + const { l, a, b, alpha } = color; + const c = Math.sqrt(a * a + b * b); + let h = Math.atan2(b, a) * (180 / Math.PI); + if (h < 0) { + h += 360; + } + return { l, c, h, alpha }; +} + +function toLCHText(color) { + let { alpha } = color; + const xyz = rgbaToXYZD50(color); + const lab = xyzToLab(xyz); + const lch = labToLCH(lab); + return `lch(${lch.l.toFixed(3)} ${lch.c.toFixed(3)} ${lch.h.toFixed(3)}${ + alpha < 1.0 ? ` / ${alpha.toFixed(3)}` : "" + })`; +} + +function rgbaToOkLCh(color) { + const lab = rgbToOklab(color); + const oklch = labToLCH(lab); + return { l: oklch.l, c: oklch.c, h: oklch.h, alpha: color.alpha }; +} + +function toOkLChText(color) { + let { alpha } = color; + const oklch = rgbaToOkLCh(color); + return `oklch(${oklch.l.toFixed(5)} ${oklch.c.toFixed(5)} ${oklch.h.toFixed( + 5, + )}${alpha < 1.0 ? ` / ${alpha.toFixed(3)}` : ""})`; +} + +function updateColorMix() { + let colorMixFunction = "color-mix(in "; + + root.style.setProperty("--color-space", colorSpace.value); + colorMixFunction += colorSpace.value; + + if (polarColorSpaces.includes(colorSpace.value)) { + root.style.setProperty("--interpolation-method", interpolationMethod.value); + colorMixFunction += ` ${interpolationMethod.value}, `; + } else { + root.style.setProperty("--interpolation-method", ""); + colorMixFunction += `, `; + } + root.style.setProperty( + "--color-one", + colorOneButton.style.getPropertyValue("background-color"), + ); + root.style.setProperty("--percentage-one", percentageOneSlider.value + "%"); + colorMixFunction += `${rgbaToHEXAText(colorOne)} ${ + percentageOneSlider.value + }%, `; + + root.style.setProperty( + "--color-two", + colorTwoButton.style.getPropertyValue("background-color"), + ); + root.style.setProperty("--percentage-two", percentageTwoSlider.value + "%"); + colorMixFunction += `${rgbaToHEXAText(colorTwo)} ${ + percentageTwoSlider.value + }%)`; + + mixedColorDiv.style.setProperty("background-color", colorMixFunction); + + mixedOutputText.innerText = colorMixFunction; + displayOutputColors(window.getComputedStyle(mixedColorDiv).backgroundColor); +} + +function displayOutputColors(color) { + let rgbaColor = colorToRGBA(color); + + hexOutput.innerText = rgbaToHEXAText(rgbaColor); + + rgbFunctionOutput.innerText = `rgb(${Math.round(rgbaColor.r)} ${Math.round( + rgbaColor.g, + )} ${Math.round(rgbaColor.b)}`; + if (rgbaColor.alpha && rgbaColor.alpha < 1.0) { + rgbFunctionOutput.innerText += ` / ${rgbaColor.alpha.toFixed(3)}`; + } + rgbFunctionOutput.innerText += `)`; + + colorFunctionOutput.innerText = `color(srgb ${(rgbaColor.r / 255).toFixed( + 3, + )} ${(rgbaColor.g / 255).toFixed(3)} ${(rgbaColor.b / 255).toFixed(3)}`; + if (rgbaColor.alpha && rgbaColor.alpha < 1.0) { + colorFunctionOutput.innerText += ` / ${rgbaColor.alpha.toFixed(3)}`; + } + colorFunctionOutput.innerText += `)`; + + hslFunctionOutput.innerText = toHSLAText(rgbaColor); + + hwbFunctionOutput.innerText = rgbaToHWBAText(rgbaColor); + labFunctionOutput.innerText = rgbaToLabText(rgbaColor); + xyzD50FunctionOutput.innerText = rgbaToXYZD50Text(rgbaColor); + xyzD65FunctionOutput.innerText = rgbaToXYZD65Text(rgbaColor); + lchFunctionOutput.innerText = toLCHText(rgbaColor); + oklabFunctionOutput.innerText = toOkLabText(rgbaColor); + oklchFunctionOutput.innerText = toOkLChText(rgbaColor); +} + +function setColorToDialog() { + colorTextInput.value = rgbaToHEXAText(currentColor); + colorInput.value = rgbToHEXText(currentColor); + colorOpacitySlider.value = currentColor.alpha; +} + +function init() { + percentageOneSlider.addEventListener("input", (e) => { + percentageOneLabel.innerText = e.target.value + "%"; + updateColorMix(); + }); + + percentageTwoSlider.addEventListener("input", (e) => { + percentageTwoLabel.innerText = e.target.value + "%"; + updateColorMix(); + }); + + colorSpace.addEventListener("change", (e) => { + if (polarColorSpaces.includes(e.target.value)) { + interpolationMethod.style.visibility = "visible"; + interpolationMethodLabel.style.visibility = "visible"; + } else { + interpolationMethod.style.visibility = "hidden"; + interpolationMethodLabel.style.visibility = "hidden"; + } + updateColorMix(); + }); + + interpolationMethod.addEventListener("change", () => { + updateColorMix(); + }); + + interpolationMethod.style.visibility = "hidden"; + interpolationMethodLabel.style.visibility = "hidden"; + + colorOneButton.addEventListener("click", () => { + currentColor = colorOne; + setColorToDialog(); + pickerDialog.showModal(); + }); + + colorTwoButton.addEventListener("click", () => { + currentColor = colorTwo; + setColorToDialog(); + pickerDialog.showModal(); + }); + + colorTextInput.addEventListener("input", (e) => { + const color = colorToRGBA(e.target.value); + Object.assign(currentColor, color); + colorInput.value = rgbToHEXText(currentColor); + colorOpacitySlider.value = currentColor.alpha; + }); + + colorInput.addEventListener("input", (e) => { + const text = e.target.value; + currentColor.r = parseInt(text.slice(1, 3), 16); + currentColor.g = parseInt(text.slice(3, 5), 16); + currentColor.b = parseInt(text.slice(5, 7), 16); + colorTextInput.value = rgbaToHEXAText(currentColor); + colorOpacitySlider.value = 1.0; + }); + + colorOpacitySlider.addEventListener("input", (e) => { + const value = parseFloat(e.target.value); + if (value >= 0 && value <= 1) { + currentColor.alpha = value; + colorTextInput.value = rgbaToHEXAText(currentColor); + } + }); + + pickerOkButton.addEventListener("click", () => { + colorOneButton.style.setProperty( + "background-color", + rgbaToHEXAText(colorOne), + ); + colorTwoButton.style.setProperty( + "background-color", + rgbaToHEXAText(colorTwo), + ); + pickerDialog.close(); + updateColorMix(); + }); + + document.querySelectorAll("#output-colors button").forEach((button) => { + button.addEventListener("click", (e) => { + // get parent element + const text = e.target.nextElementSibling.innerText; + navigator.clipboard.writeText(text); + e.target.innerText = "Copied!"; + setTimeout(() => { + e.target.innerText = "Copy"; + }, 1000); + }); + }); + + updateColorMix(); +} + +init(); +``` + +{{EmbedLiveSample("color-mixer", "", 850, "", "", "", "clipboard-write")}} + +## See also + +- {{CSSXref("<color>")}} +- {{CSSXref("<color-interpolation-method>")}} +- {{cssxref("<hue>")}} +- [CSS relative colors](/en-US/docs/Web/CSS/CSS_colors/Relative_colors) diff --git a/files/en-us/web/css/css_colors/color_picker_tool/index.md b/files/en-us/web/css/css_colors/color_picker/index.md similarity index 96% rename from files/en-us/web/css/css_colors/color_picker_tool/index.md rename to files/en-us/web/css/css_colors/color_picker/index.md index c084b4ff45b2ce6..8ae597b1a74574e 100644 --- a/files/en-us/web/css/css_colors/color_picker_tool/index.md +++ b/files/en-us/web/css/css_colors/color_picker/index.md @@ -1,6 +1,6 @@ --- -title: Color picker tool -slug: Web/CSS/CSS_colors/Color_picker_tool +title: Color picker +slug: Web/CSS/CSS_colors/Color_picker page-type: guide sidebar: cssref --- diff --git a/files/en-us/web/css/css_colors/color_values/index.md b/files/en-us/web/css/css_colors/color_values/index.md index fefb91f2a3dae28..ab3a5ef6081f5c0 100644 --- a/files/en-us/web/css/css_colors/color_values/index.md +++ b/files/en-us/web/css/css_colors/color_values/index.md @@ -526,7 +526,7 @@ For example, if you wanted to show the `display-p3 0 0 1` color, which is outsid Understanding `color()` is important when it comes to relative colors, discussed next. The older sRGB color notations discussed above — `hsl()`, `hwb()`, and `rgb()`— do not express the full spectrum of visible colors, while the `color()` function supports a much wider color gamut. As a result, when using the older functions types to define relative colors, the output color returned by querying {{domxref("HTMLElement.style")}} property or the {{domxref("CSSStyleDeclaration.getPropertyValue()")}} method will be a `color(srgb ...)` value. -To see an example of converting the `hsl()`, `hwb()`, and `rgb()` color functions to `color()` in the `srgb` color space, check out our [color picker tool](/en-US/docs/Web/CSS/CSS_colors/Color_picker_tool). +To see an example of converting the `hsl()`, `hwb()`, and `rgb()` color functions to `color()` in the `srgb` color space, check out our [color picker tool](/en-US/docs/Web/CSS/CSS_colors/Color_picker). ### Relative colors diff --git a/files/en-us/web/css/css_colors/index.md b/files/en-us/web/css/css_colors/index.md index 573f8885d127f36..1f6e208f347296e 100644 --- a/files/en-us/web/css/css_colors/index.md +++ b/files/en-us/web/css/css_colors/index.md @@ -83,7 +83,7 @@ The CSS color module also introduces the `CSSColorProfileRule` interface. Curren - : Color theory and resources, including finding the right colors to create an accessible color palette, contrast, and printing in color. - [Using relative colors](/en-US/docs/Web/CSS/CSS_colors/Relative_colors) - : This article explains relative CSS color syntax, shows what the different options are, and looks at some illustrative examples. -- [Color picker tool](/en-US/docs/Web/CSS/CSS_colors/Color_picker_tool) +- [Color picker](/en-US/docs/Web/CSS/CSS_colors/Color_picker) - : A tool that lets you pick a color in the sRGB color space and converts it between various CSS color formats, helping you understand the syntax of the different color notations. - [Understanding color and luminance](/en-US/docs/Web/Accessibility/Guides/Colors_and_Luminance) - : Color perception and using colors with color insensitive (color blind) users, reduced vision users and users with vestibular disorders or other neurological disorders in mind. diff --git a/files/en-us/web/http/reference/headers/referrer-policy/index.md b/files/en-us/web/http/reference/headers/referrer-policy/index.md index 8a806b632d8af2f..7cb37656c2f527c 100644 --- a/files/en-us/web/http/reference/headers/referrer-policy/index.md +++ b/files/en-us/web/http/reference/headers/referrer-policy/index.md @@ -49,7 +49,7 @@ Referrer-Policy: unsafe-url - : Send only the {{glossary("origin")}} in the {{HTTPHeader("Referer")}} header. For example, a document at `https://example.com/page.html` will send the referrer `https://example.com/`. - `origin-when-cross-origin` - - : When performing a {{glossary("Same-origin_policy", "same-origin")}} request to the same protocol level (HTTP→HTTP, HTTPS→HTTPS), send the {{glossary("origin")}}, path, and query string. Send only the origin for cross origin requests and requests to less secure destinations (HTTPS→HTTP). + - : When performing a {{glossary("Same-origin_policy", "same-origin")}} request, send the {{glossary("origin")}}, path, and query string. Send only the origin for cross origin requests and requests to less secure destinations (HTTPS→HTTP). - `same-origin` - : Send the {{glossary("origin")}}, path, and query string for {{glossary("Same-origin_policy", "same-origin")}} requests. Don't send the {{HTTPHeader("Referer")}} header for cross-origin requests. - `strict-origin` diff --git a/files/sidebars/cssref.yaml b/files/sidebars/cssref.yaml index bd5e749259383f0..7c78cad99204dcb 100644 --- a/files/sidebars/cssref.yaml +++ b/files/sidebars/cssref.yaml @@ -29,6 +29,9 @@ sidebar: - /Learn_web_development/Core/Styling_basics/Images_media_forms - /Learn_web_development/Core/Styling_basics/Tables - /Learn_web_development/Core/Styling_basics/Debugging_CSS + - /Learn_web_development/Core/Styling_basics/Fundamental_CSS_comprehension + - /Learn_web_development/Core/Styling_basics/Fancy_letterheaded_paper + - /Learn_web_development/Core/Styling_basics - link: /Learn_web_development/Core/Text_styling title: CSS_text_styling details: closed @@ -346,10 +349,11 @@ sidebar: - type: section title: Tools - children: - - /Web/CSS/CSS_colors/Color_picker_tool - - /Web/CSS/CSS_backgrounds_and_borders/Box-shadow_generator - /Web/CSS/CSS_backgrounds_and_borders/Border-image_generator - /Web/CSS/CSS_backgrounds_and_borders/Border-radius_generator + - /Web/CSS/CSS_backgrounds_and_borders/Box-shadow_generator + - /Web/CSS/CSS_colors/Color_mixer + - /Web/CSS/CSS_colors/Color_picker - /Web/CSS/CSS_shapes/Shape_generator l10n: de: