CINXE.COM
Wide Gamut 2D Graphics using HTML Canvas | WebKit
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> <meta name="robots" content="noodp"> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes, viewport-fit=cover"> <meta name="theme-color" content="hsl(203.6, 100%, 12%)"> <title> Wide Gamut 2D Graphics using HTML Canvas | WebKit</title> <meta name="application-name" content="WebKit"> <link rel="stylesheet" type="text/css" href="https://webkit.org/wp-content/themes/webkit/style.css?2022100501" media="all"> <link rel="stylesheet" href="https://www.apple.com/wss/fonts?families=SF+Pro,v1" type="text/css"> <link rel="stylesheet" href="https://www.apple.com/wss/fonts?families=SF+Mono,v2" type="text/css"> <meta name="supported-color-schemes" content="light dark"> <noscript> <img src="https://shynet.webkit.org/ingress/561b9e53-fb8c-4297-ae4d-bde05e8daa59/pixel.gif"> </noscript> <script defer src="https://shynet.webkit.org/ingress/561b9e53-fb8c-4297-ae4d-bde05e8daa59/script.js"></script> <link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="https://webkit.org/feed/"> <link rel="alternate" type="text/xml" title="RSS .92" href="https://webkit.org/feed/rss/"> <link rel="alternate" type="application/atom+xml" title="Atom 0.3" href="https://webkit.org/feed/atom/"> <link rel="pingback" href="https://webkit.org/wp/xmlrpc.php"> <link rel="shortcut icon" sizes="32x32" type="image/x-icon" href="/favicon.ico"> <meta name='robots' content='max-image-preview:large' /> <link rel='stylesheet' id='wp-block-library-css' href='https://webkit.org/wp/wp-includes/css/dist/block-library/style.min.css?ver=6.7' type='text/css' media='all' /> <style id='classic-theme-styles-inline-css' type='text/css'> /*! This file is auto-generated */ .wp-block-button__link{color:#fff;background-color:#32373c;border-radius:9999px;box-shadow:none;text-decoration:none;padding:calc(.667em + 2px) calc(1.333em + 2px);font-size:1.125em}.wp-block-file__button{background:#32373c;color:#fff;text-decoration:none} </style> <style id='global-styles-inline-css' type='text/css'> :root{--wp--preset--aspect-ratio--square: 1;--wp--preset--aspect-ratio--4-3: 4/3;--wp--preset--aspect-ratio--3-4: 3/4;--wp--preset--aspect-ratio--3-2: 3/2;--wp--preset--aspect-ratio--2-3: 2/3;--wp--preset--aspect-ratio--16-9: 16/9;--wp--preset--aspect-ratio--9-16: 9/16;--wp--preset--color--black: #000000;--wp--preset--color--cyan-bluish-gray: #abb8c3;--wp--preset--color--white: #ffffff;--wp--preset--color--pale-pink: #f78da7;--wp--preset--color--vivid-red: #cf2e2e;--wp--preset--color--luminous-vivid-orange: #ff6900;--wp--preset--color--luminous-vivid-amber: #fcb900;--wp--preset--color--light-green-cyan: #7bdcb5;--wp--preset--color--vivid-green-cyan: #00d084;--wp--preset--color--pale-cyan-blue: #8ed1fc;--wp--preset--color--vivid-cyan-blue: #0693e3;--wp--preset--color--vivid-purple: #9b51e0;--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple: linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%);--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan: linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%);--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange: linear-gradient(135deg,rgba(252,185,0,1) 0%,rgba(255,105,0,1) 100%);--wp--preset--gradient--luminous-vivid-orange-to-vivid-red: linear-gradient(135deg,rgba(255,105,0,1) 0%,rgb(207,46,46) 100%);--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray: linear-gradient(135deg,rgb(238,238,238) 0%,rgb(169,184,195) 100%);--wp--preset--gradient--cool-to-warm-spectrum: linear-gradient(135deg,rgb(74,234,220) 0%,rgb(151,120,209) 20%,rgb(207,42,186) 40%,rgb(238,44,130) 60%,rgb(251,105,98) 80%,rgb(254,248,76) 100%);--wp--preset--gradient--blush-light-purple: linear-gradient(135deg,rgb(255,206,236) 0%,rgb(152,150,240) 100%);--wp--preset--gradient--blush-bordeaux: linear-gradient(135deg,rgb(254,205,165) 0%,rgb(254,45,45) 50%,rgb(107,0,62) 100%);--wp--preset--gradient--luminous-dusk: linear-gradient(135deg,rgb(255,203,112) 0%,rgb(199,81,192) 50%,rgb(65,88,208) 100%);--wp--preset--gradient--pale-ocean: linear-gradient(135deg,rgb(255,245,203) 0%,rgb(182,227,212) 50%,rgb(51,167,181) 100%);--wp--preset--gradient--electric-grass: linear-gradient(135deg,rgb(202,248,128) 0%,rgb(113,206,126) 100%);--wp--preset--gradient--midnight: linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%);--wp--preset--font-size--small: 13px;--wp--preset--font-size--medium: 20px;--wp--preset--font-size--large: 36px;--wp--preset--font-size--x-large: 42px;--wp--preset--spacing--20: 0.44rem;--wp--preset--spacing--30: 0.67rem;--wp--preset--spacing--40: 1rem;--wp--preset--spacing--50: 1.5rem;--wp--preset--spacing--60: 2.25rem;--wp--preset--spacing--70: 3.38rem;--wp--preset--spacing--80: 5.06rem;--wp--preset--shadow--natural: 6px 6px 9px rgba(0, 0, 0, 0.2);--wp--preset--shadow--deep: 12px 12px 50px rgba(0, 0, 0, 0.4);--wp--preset--shadow--sharp: 6px 6px 0px rgba(0, 0, 0, 0.2);--wp--preset--shadow--outlined: 6px 6px 0px -3px rgba(255, 255, 255, 1), 6px 6px rgba(0, 0, 0, 1);--wp--preset--shadow--crisp: 6px 6px 0px rgba(0, 0, 0, 1);}:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}:where(.wp-block-columns.is-layout-flex){gap: 2em;}:where(.wp-block-columns.is-layout-grid){gap: 2em;}:where(.wp-block-post-template.is-layout-flex){gap: 1.25em;}:where(.wp-block-post-template.is-layout-grid){gap: 1.25em;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-color{color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-color{color: var(--wp--preset--color--white) !important;}.has-pale-pink-color{color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-color{color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-color{color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-color{color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-color{color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-color{color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-color{color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-color{color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-color{color: var(--wp--preset--color--vivid-purple) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-background-color{background-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-pale-pink-background-color{background-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-background-color{background-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-background-color{background-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-background-color{background-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-background-color{background-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-background-color{background-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-background-color{background-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-background-color{background-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-background-color{background-color: var(--wp--preset--color--vivid-purple) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-border-color{border-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-pale-pink-border-color{border-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-border-color{border-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-border-color{border-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-border-color{border-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-border-color{border-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-border-color{border-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-border-color{border-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-border-color{border-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-border-color{border-color: var(--wp--preset--color--vivid-purple) !important;}.has-vivid-cyan-blue-to-vivid-purple-gradient-background{background: var(--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple) !important;}.has-light-green-cyan-to-vivid-green-cyan-gradient-background{background: var(--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan) !important;}.has-luminous-vivid-amber-to-luminous-vivid-orange-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange) !important;}.has-luminous-vivid-orange-to-vivid-red-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-orange-to-vivid-red) !important;}.has-very-light-gray-to-cyan-bluish-gray-gradient-background{background: var(--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray) !important;}.has-cool-to-warm-spectrum-gradient-background{background: var(--wp--preset--gradient--cool-to-warm-spectrum) !important;}.has-blush-light-purple-gradient-background{background: var(--wp--preset--gradient--blush-light-purple) !important;}.has-blush-bordeaux-gradient-background{background: var(--wp--preset--gradient--blush-bordeaux) !important;}.has-luminous-dusk-gradient-background{background: var(--wp--preset--gradient--luminous-dusk) !important;}.has-pale-ocean-gradient-background{background: var(--wp--preset--gradient--pale-ocean) !important;}.has-electric-grass-gradient-background{background: var(--wp--preset--gradient--electric-grass) !important;}.has-midnight-gradient-background{background: var(--wp--preset--gradient--midnight) !important;}.has-small-font-size{font-size: var(--wp--preset--font-size--small) !important;}.has-medium-font-size{font-size: var(--wp--preset--font-size--medium) !important;}.has-large-font-size{font-size: var(--wp--preset--font-size--large) !important;}.has-x-large-font-size{font-size: var(--wp--preset--font-size--x-large) !important;} :where(.wp-block-post-template.is-layout-flex){gap: 1.25em;}:where(.wp-block-post-template.is-layout-grid){gap: 1.25em;} :where(.wp-block-columns.is-layout-flex){gap: 2em;}:where(.wp-block-columns.is-layout-grid){gap: 2em;} :root :where(.wp-block-pullquote){font-size: 1.5em;line-height: 1.6;} </style> <link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://webkit.org/wp/xmlrpc.php?rsd" /> <meta name="generator" content="WordPress 6.7" /> <link rel="canonical" href="https://webkit.org/blog/12058/wide-gamut-2d-graphics-using-html-canvas/" /> <link rel='shortlink' href='https://webkit.org/?p=12058' /> <link rel="alternate" title="oEmbed (JSON)" type="application/json+oembed" href="https://webkit.org/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fwebkit.org%2Fblog%2F12058%2Fwide-gamut-2d-graphics-using-html-canvas%2F" /> <link rel="alternate" title="oEmbed (XML)" type="text/xml+oembed" href="https://webkit.org/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fwebkit.org%2Fblog%2F12058%2Fwide-gamut-2d-graphics-using-html-canvas%2F&format=xml" /> <!-- Schema.org markup --> <meta itemprop="name" content="Wide Gamut 2D Graphics using HTML Canvas"> <meta itemprop="description" content="Support for creating 2D canvases with Display P3 backing stores has been added to WebKit."> <meta itemprop="image" content="https://webkit.org/wp-content/uploads/pinwheel-Display-P3.png"> <!-- Twitter Card data --> <meta name="twitter:card" content="summary_large_image"> <meta name="twitter:image:src" content="https://webkit.org/wp-content/uploads/pinwheel-Display-P3.png"> <meta name="twitter:site" content="@webkit"> <meta name="twitter:title" content="Wide Gamut 2D Graphics using HTML Canvas"> <meta name="twitter:description" content="Support for creating 2D canvases with Display P3 backing stores has been added to WebKit."> <meta name="twitter:creator" content="@heycam"> <!-- Open Graph data --> <meta property="og:title" content="Wide Gamut 2D Graphics using HTML Canvas"> <meta property="og:type" content="article"> <meta property="og:url" content="https://webkit.org/blog/12058/wide-gamut-2d-graphics-using-html-canvas/"> <meta property="og:image" content="https://webkit.org/wp-content/uploads/pinwheel-Display-P3.png"> <meta property="og:description" content="Support for creating 2D canvases with Display P3 backing stores has been added to WebKit."> <meta property="og:site_name" content="WebKit"> <meta property="article:published_time" content="2021-12-14T09:00:35-08:00"> <meta property="article:modified_time" content="2021-12-14T09:50:36-08:00"> <meta property="article:section" content="CSS"> <meta property="article:tag" content="JavaScript"> <meta property="fb:admins" content="1085088865"> </head> <body class="post-template-default single single-post postid-12058 single-format-standard"> <!-- Copyright © 2020 Apple Inc. All rights reserved. --> <svg xmlns="http://www.w3.org/2000/svg"> <style> svg { display: block; width: 0; height: 0; } </style> <filter id="invertLightness" x="0" y="0" style="color-interpolation-filters: sRGB"> <feColorMatrix type="matrix" in="SourceGraphic" result="red" values="1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1" /> <feColorMatrix type="matrix" in="SourceGraphic" result="green" values="0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1" /> <feColorMatrix type="matrix" in="SourceGraphic" result="blue" values="0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1" /> <feBlend in="red" in2="green" mode="lighten" result="maxyellow" /> <feBlend in="maxyellow" in2="blue" mode="lighten" result="max" /> <feBlend in="red" in2="green" mode="darken" result="minyellow" /> <feBlend in="minyellow" in2="blue" mode="darken" result="min" /> <feComponentTransfer result="adjustment" in="min"> <feFuncR type="linear" intercept="1" slope="-1" /> <feFuncG type="linear" intercept="1" slope="-1" /> <feFuncB type="linear" intercept="1" slope="-1" /> </feComponentTransfer> <feComposite operator="arithmetic" in="SourceGraphic" in2="adjustment" k1="0" k2="1" k3="1" k4="-1" result="channelAdjustment" /> <feComposite operator="arithmetic" in="channelAdjustment" in2="max" k1="0" k2="1" k3="-1" k4="1" result="finalColors" /> <feComposite operator="in" in="finalColors" in2="SourceAlpha" /> </filter> </svg> <header aria-label="WebKit.org Header" id="header"> <div class="page-width"> <a href="/"><div id="logo" class="site-logo">WebKit</div></a> <nav id="site-nav" aria-label="Site Menu"> <div class="menu-main-menu-container"><input type="checkbox" id="menu-main-menu-toggle" class="menu-toggle" /><label for="menu-main-menu-toggle" class="label-toggle main-menu" data-open="Main Menu" data-close="Close Menu"></label><ul id="menu-main-menu" class="menu" role="menubar"><li id="menu-item-6091" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-6091"><a href="https://webkit.org/downloads/" role="menuitem">Downloads</a></li> <li id="menu-item-4272" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-4272"><input type="checkbox" id="toggle-4272" class="menu-toggle" /><a href="#nav-sub-menu" role="menuitem" aria-haspopup="true" aria-owns="sub-menu-for-4272" aria-controls="sub-menu-for-4272" aria-expanded="true"><label for="toggle-4272" class="label-toggle">Feature Status</label></a> <ul class="sub-menu sub-menu-layer" role="menu" id="sub-menu-for-4272"> <li id="menu-item-13052" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-13052"><a href="https://webkit.org/css-status/" role="menuitem">CSS Features</a></li> <li id="menu-item-14388" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-14388"><a href="https://webkit.org/standards-positions/" role="menuitem">Standards Positions</a></li> </ul> </li> <li id="menu-item-9988" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children menu-item-9988"><input type="checkbox" id="toggle-9988" class="menu-toggle" /><a href="#nav-sub-menu" role="menuitem" aria-haspopup="true" aria-owns="sub-menu-for-9988" aria-controls="sub-menu-for-9988" aria-expanded="true"><label for="toggle-9988" class="label-toggle">Documentation</label></a> <ul class="sub-menu sub-menu-layer" role="menu" id="sub-menu-for-9988"> <li id="menu-item-9989" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-9989"><a href="/web-inspector" role="menuitem">Web Inspector</a></li> <li id="menu-item-10868" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-10868"><a href="https://webkit.org/tracking-prevention/" role="menuitem">Tracking Prevention</a></li> </ul> </li> <li id="menu-item-4282" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-4282"><input type="checkbox" id="toggle-4282" class="menu-toggle" /><a href="#nav-sub-menu" role="menuitem" aria-haspopup="true" aria-owns="sub-menu-for-4282" aria-controls="sub-menu-for-4282" aria-expanded="true"><label for="toggle-4282" class="label-toggle">Policies</label></a> <ul class="sub-menu sub-menu-layer" role="menu" id="sub-menu-for-4282"> <li id="menu-item-10037" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-10037"><a href="https://webkit.org/project/" role="menuitem">Project Goals</a></li> <li id="menu-item-13077" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-13077"><a href="https://webkit.org/bug-prioritization/" role="menuitem">Bug Prioritization</a></li> <li id="menu-item-13076" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-13076"><a href="https://webkit.org/bug-report-guidelines/" role="menuitem">Bug Report Guidelines</a></li> <li id="menu-item-13075" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-13075"><a href="https://webkit.org/code-style-guidelines/" role="menuitem">Code Style Guidelines</a></li> <li id="menu-item-13074" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-13074"><a href="https://webkit.org/commit-and-review-policy/" role="menuitem">Commit and Review Policy</a></li> <li id="menu-item-13073" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-13073"><a href="https://webkit.org/feature-policy/" role="menuitem">Feature Policy</a></li> <li id="menu-item-13072" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-13072"><a href="https://webkit.org/security-policy/" role="menuitem">Security Policy</a></li> <li id="menu-item-13071" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-13071"><a href="https://webkit.org/tracking-prevention-policy/" role="menuitem">Tracking Prevention Policy</a></li> </ul> </li> <li id="menu-item-4274" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children menu-item-4274"><input type="checkbox" id="toggle-4274" class="menu-toggle" /><a href="#nav-sub-menu" role="menuitem" aria-haspopup="true" aria-owns="sub-menu-for-4274" aria-controls="sub-menu-for-4274" aria-expanded="true"><label for="toggle-4274" class="label-toggle">Contribute</label></a> <ul class="sub-menu sub-menu-layer" role="menu" id="sub-menu-for-4274"> <li id="menu-item-4277" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-4277"><a href="https://webkit.org/getting-started/" role="menuitem">Getting Started</a></li> <li id="menu-item-4284" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-4284"><a href="https://webkit.org/contributing-code/" role="menuitem">Contributing Code</a></li> <li id="menu-item-4281" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-4281"><a href="https://webkit.org/testing-contributions/" role="menuitem">Testing Contributions</a></li> <li id="menu-item-4273" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-4273"><a href="https://webkit.org/reporting-bugs/" role="menuitem">How to Report Bugs</a></li> <li id="menu-item-4278" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-4278"><a href="https://github.com/WebKit/WebKit" role="menuitem">GitHub Repository</a></li> </ul> </li> <li id="menu-item-4270" class="menu-item menu-item-type-post_type menu-item-object-page current_page_parent menu-item-has-children menu-item-4270"><input type="checkbox" id="toggle-4270" class="menu-toggle" /><a href="#nav-sub-menu" role="menuitem" aria-haspopup="true" aria-owns="sub-menu-for-4270" aria-controls="sub-menu-for-4270" aria-expanded="true"><label for="toggle-4270" class="label-toggle">Blog</label></a> <ul class="sub-menu sub-menu-layer" role="menu" id="sub-menu-for-4270"> <li id="menu-item-13057" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-13057"><a href="https://webkit.org/blog/category/news/" role="menuitem">News Posts</a></li> <li id="menu-item-13058" class="menu-item menu-item-type-taxonomy menu-item-object-category current-post-ancestor current-menu-parent current-post-parent menu-item-13058"><a href="https://webkit.org/blog/category/css/" role="menuitem">CSS Posts</a></li> <li id="menu-item-13063" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-13063"><a href="https://webkit.org/blog/category/contributing/" role="menuitem">Contributing Posts</a></li> <li id="menu-item-13062" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-13062"><a href="https://webkit.org/blog/category/privacy/" role="menuitem">Privacy Posts</a></li> <li id="menu-item-13060" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-13060"><a href="https://webkit.org/blog/category/performance/" role="menuitem">Performance Posts</a></li> <li id="menu-item-13061" class="menu-item menu-item-type-taxonomy menu-item-object-category current-post-ancestor current-menu-parent current-post-parent menu-item-13061"><a href="https://webkit.org/blog/category/javascript/" role="menuitem">JavaScript Posts</a></li> <li id="menu-item-13056" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-13056"><a href="https://webkit.org/blog/category/standards/" role="menuitem">Standards Posts</a></li> <li id="menu-item-13059" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-13059"><a href="https://webkit.org/blog/category/web-inspector/" role="menuitem">Web Inspector Posts</a></li> <li id="menu-item-13055" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-13055"><a href="https://webkit.org/blog/category/safari-technology-preview/" role="menuitem">Safari Technology Preview Posts</a></li> </ul> </li> <li><form action="/" method="get"><input type="search" name="s" class="search-input" value=""></form></li></ul></div></nav> </div> </header> <main id="content"> <div class="page-width"> <article class="post-12058 post type-post status-publish format-standard hentry category-css category-javascript" id="post-12058"> <h1><a href="https://webkit.org/blog/12058/wide-gamut-2d-graphics-using-html-canvas/" rel="bookmark" title="Permanent Link: Wide Gamut 2D Graphics using HTML Canvas">Wide Gamut 2D Graphics using HTML Canvas</a></h1> <div class="byline"> <p class="date">Dec 14, 2021</p> <p class="author">by <span>Cameron McCormack</span></p> <p class="twitter"><a href="https://twitter.com/heycam" target="_blank">@heycam</a></p> </div> <div class="bodycopy"> <style> @media (prefers-color-scheme:dark) { figure .preserve-color, figure:hover .preserve-color { filter: none !important; } } figure.widescreen.inline-images img { display: inline; } article .byline { width: 210px; margin-left: -20px; } .nowrap-overflow-auto { white-space: nowrap; max-width: 100%; overflow: auto; } figure img { display: inline !important; } @media (max-width: 1180px) { article .byline { width: unset; margin-right: auto; } } #fillstyles img { background-color: #ddd; } @media (prefers-color-scheme: dark) { #fillstyles img { background-color: #444; } } #puzzle iframe { width: 350px; height: 250px; } @media (min-width: 500px) { #puzzle iframe { width: 500px; height: 310px; } } @media (min-width: 1000px) { #puzzle iframe { width: 1000px; height: 520px; } } @media (color-gamut: p3) { #gamut-warning { display: none; } } </style> <p>Most colors used on the Web today are sRGB colors. These are the colors that you specify with the familiar <code>#rrggbb</code> and <code>rgb(r, g, b)</code> CSS syntax, and whose individual color components are given as values in the range [0, 255]. For example, <code>rgb(255, 0, 0)</code> is the most saturated, pure red in the sRGB color space. But the range of colors in sRGB — its <em>color gamut</em> — does not encompass all colors that can be perceived by the human visual system, and there are displays that can produce a broader range of colors.</p> <p>sRGB is based on the color capabilities of computer monitors that existed at the time of its standardization, in the late 1990s. Since then, other, wider gamut color spaces have been defined for use in digital content, and which cover more of the colors that humans can perceive. One such color space is Display P3, which contains colors with significantly higher saturation than sRGB.</p> <div class="note" id="gamut-warning"> This browser reports that the display does not support Display P3 colors; figures in this post may not appear as intended. </div> <figure class="widescreen mattewhite aligncenter"> <div class="nowrap-overflow-auto"> <img fetchpriority="high" decoding="async" src="https://webkit.org/wp-content/uploads/pinwheel-sRGB.png" width="240" height="244" alt="A conic gradient showing a range of sRGB colors" class="preserve-color"> <img decoding="async" src="https://webkit.org/wp-content/uploads/pinwheel-Display-P3.png" width="240" height="244" alt="A conic gradient showing a range of Display P3 colors" class="preserve-color"> </div><figcaption>Conic gradients showing fully saturated sRGB (left) and Display P3 (right) colors. Viewed in a browser and on a display supporting Display P3, the colors in the circle on the right will show as more intense than those on the left. (<a href="https://webkit.org/blog-files/wide-gamut-canvas/pinwheels.html">View as standalone page.</a>)</figcaption></figure> <div class="note">For a more in depth introduction to color spaces, see Dean Jackson’s earlier post, <a href="https://webkit.org/blog/6682/improving-color-on-the-web/">Improving Color on the Web</a>.</div> <p>Today, there are many computer and mobile devices on the market with displays that can reproduce all the colors of the Display P3 gamut, and the Web platform has been evolving over the last few years to allow authors to make best use of these displays. WebKit has supported wide color images and video since 2016, and last year became <a href="https://webkit.org/blog/10042/wide-gamut-color-in-css-with-display-p3/">the first browser engine to implement the new color syntax</a> defined in <a href="https://drafts.csswg.org/css-color-4/">CSS Color Module Level 4</a> where colors can be specified in a given color space (like <code>color(display-p3 1 0 0)</code>, a fully saturated Display P3 red).</p> <p>One notable omission in wide gamut color support, until now, has been in the HTML <code>canvas</code> element. The 2D canvas API was introduced before wide gamut displays were common, and until now has only handled drawing and manipulating sRGB pixel values. Earlier this year, a proposal for creating canvas contexts using other color spaces was added to the HTML standard, and we’ve recently added support for this to WebKit.</p> <h2>Drawing on a wide gamut canvas rendering context</h2> <p>The <code>getContext</code> method on a <code>canvas</code> element, which is used to create a rendering context object with 2D drawing APIs, accepts a new option to set the canvas backing store’s color space.</p> <pre><code class="html"><span class="tag"><<span class="keyword">canvas</span> <span class="keyword attribute">id</span>=<span class="attribute value string">"canvas"</span> <span class="keyword attribute">width</span>=<span class="attribute value string">"400"</span> <span class="keyword attribute">height</span>=<span class="attribute value string">"300"</span>></span><span class="tag"></<span class="keyword">canvas</span>></span> <span class="tag"><<span class="keyword">script</span>></span> let canvas = document.getElementById("canvas"); let context = canvas.getContext("2d", { colorSpace: "display-p3" }); // ... draw on context ... <span class="tag"></<span class="keyword">script</span>></span> </code></pre> <p>The default color space remains sRGB, rather than having the browser automatically use the wider color space, to avoid the performance overhead of color space conversions with existing content. The two explicit color spaces that can be requested are <code>"srgb"</code> and <code>"display-p3"</code>.</p> <p>Fill and stroke styles can be specified using any supported CSS color syntax.</p> <pre><code class="javascript"><span class="keyword type">let</span> <span class="identifier">position</span> <span class="operator">=</span> <span class="number">0</span>; <span class="keyword control">for</span> (<span class="keyword type">let</span> <span class="identifier">green</span> <span class="keyword operator">of</span> [<span class="number">1</span>, <span class="number">0</span>]) { <span class="keyword control">for</span> (<span class="keyword type">let</span> <span class="identifier">blue</span> <span class="keyword operator">of</span> [<span class="number">1</span>, <span class="number">0</span>]) { <span class="keyword control">for</span> (<span class="keyword type">let</span> <span class="identifier">red</span> <span class="keyword operator">of</span> [<span class="number">1</span>, <span class="number">0</span>]) { <span class="identifier">context</span>.<span class="identifier">fillStyle</span> <span class="operator">=</span> `<span class="identifier">color</span>(<span class="identifier">display</span><span class="operator">-</span><span class="identifier">p3</span> ${<span class="identifier">red</span>} ${<span class="identifier">green</span>} ${<span class="identifier">blue</span>})`; <span class="identifier">context</span>.<span class="identifier">fillRect</span>(<span class="identifier">position</span>, <span class="identifier">position</span>, <span class="number">40</span>, <span class="number">40</span>); <span class="identifier">position</span> <span class="operator">+</span><span class="operator">=</span> <span class="number">20</span>; } } } </code></pre> <figure id="fillstyles" class="widescreen mattewhite aligncenter"> <div class="nowrap-overflow-auto"> <img decoding="async" src="https://webkit.org/wp-content/uploads/squares-sRGB.png" width="220" height="220" class="preserve-color" alt="Colored squares that have been clamped to sRGB"> <img loading="lazy" decoding="async" src="https://webkit.org/wp-content/uploads/squares-Display-P3.png" width="220" height="220" class="preserve-color" alt="Colored squares using Display P3 colors that are outside the sRGB gamut"> </div><figcaption>Display P3 colors used as fill styles on an sRGB (left) and Display P3 (right) canvas. Colors on the left are clamped to remain within the sRGB gamut. (<a href="https://webkit.org/blog-files/wide-gamut-canvas/squares.html">View as standalone page.</a>)</figcaption></figure> <p>Any drawing that uses a color outside the color space of the canvas will be clamped so that it is in gamut. For example, filling a rectangle with <code>color(display-p3 1 0 0)</code> on an sRGB canvas will end up using a fully saturated sRGB red. Similarly, drawing on a Display P3 canvas with <code>color(rec2020 0.9 0 0.9)</code>, an almost full magenta in the <a href="https://drafts.csswg.org/css-color-4/#predefined-rec2020">Rec.2020 color space</a>, will result in pixels of approximately <code>color(display-p3 1.0 0 0.923)</code> being used, since that is the closest in the Display P3 color gamut.</p> <pre><code class="javascript"><span class="keyword type">const</span> <span class="identifier">COLORS</span> <span class="operator">=</span> [<span class="string">"#0f0"</span>, <span class="string">"color(display-p3 0 1 0)"</span>]; <span class="keyword control">for</span> (<span class="keyword type">let</span> <span class="identifier">y</span> <span class="operator">=</span> <span class="number">20</span>; <span class="identifier">y</span> <span class="operator"><</span> <span class="number">180</span>; <span class="identifier">y</span> <span class="operator">+</span><span class="operator">=</span> <span class="number">20</span>) { <span class="identifier">context</span>.<span class="identifier">fillStyle</span> <span class="operator">=</span> <span class="identifier">COLORS</span>[(<span class="identifier">y</span> <span class="operator">/</span> <span class="number">20</span>) <span class="operator">%</span> <span class="number">2</span>]; <span class="identifier">context</span>.<span class="identifier">fillRect</span>(<span class="number">20</span>, <span class="identifier">y</span>, <span class="number">160</span>, <span class="number">20</span>); } </code></pre> <figure class="widescreen mattewhite aligncenter"> <div class="nowrap-overflow-auto"> <img loading="lazy" decoding="async" src="https://webkit.org/wp-content/uploads/stripes-sRGB.png" width="200" height="200" class="preserve-color" alt="A filled square of full sRGB green"> <img loading="lazy" decoding="async" src="https://webkit.org/wp-content/uploads/stripes-Display-P3.png" width="200" height="200" class="preserve-color" alt="Stripes of full sRGB green and full Display P3 green"> </div><figcaption>Stripes of interleaved Display P3 and sRGB colors on an sRGB (left) and Display P3 (right) canvas. Because colors are clamped to remain within the gamut of the canvas, the two shades of green are indistinguishable on the sRGB canvas. (<a href="https://webkit.org/blog-files/wide-gamut-canvas/stripes.html">View as standalone page.</a>)</figcaption></figure> <div class="note"> On macOS, you can use the <a href="https://support.apple.com/guide/colorsync-utility/welcome/mac">ColorSync Utility</a> to convert color values between sRGB, Display P3, Rec.2020, and some other predefined color spaces. </div> <p>Wide gamut colors are usable in all canvas drawing primitives:</p> <ul> <li>as the fill and stroke of rectangles, paths, and text</li> <li>in gradient stops</li> <li>as a shadow color</li> </ul> <h2>Pixel manipulation in sRGB and Display P3</h2> <p><code>getImageData</code> and <code>putImageData</code> can be used to get and set pixel values on a wide gamut canvas. By default, <code>getImageData</code> will return an <code>ImageData</code> object with pixel values in the color space of the canvas, but it is possible to specify an explicit color space that does not match the canvas, and a conversion will be performed.</p> <pre><code class="javascript"><span class="keyword type">let</span> <span class="identifier">context</span> <span class="operator">=</span> <span class="identifier">canvas</span>.<span class="identifier">getContext</span>(<span class="string">"2d"</span>, { <span class="identifier">colorSpace</span><span class="operator">:</span> <span class="string">"display-p3"</span> }); <span class="identifier">context</span>.<span class="identifier">fillStyle</span> <span class="operator">=</span> <span class="string">"color(display-p3 0.5 0 0)"</span>; <span class="identifier">context</span>.<span class="identifier">fillRect</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">100</span>, <span class="number">100</span>); <span class="keyword type">let</span> <span class="identifier">imageData</span>; <span class="comment">// Get ImageData in the canvas color space (Display P3). </span><span class="identifier">imageData</span> <span class="operator">=</span> <span class="identifier">context</span>.<span class="identifier">getImageData</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">1</span>, <span class="number">1</span>); <span class="identifier">console</span>.<span class="identifier">log</span>(<span class="identifier">imageData</span>.<span class="identifier">colorSpace</span>); <span class="comment">// "display-p3" </span><span class="identifier">console</span>.<span class="identifier">log</span>([...<span class="identifier">imageData</span>.<span class="identifier">data</span>]); <span class="comment">// [128, 0, 0, 255] </span> <span class="comment">// Get ImageData in Display P3 explicitly. </span><span class="identifier">imageData</span> <span class="operator">=</span> <span class="identifier">context</span>.<span class="identifier">getImageData</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">1</span>, <span class="number">1</span>, { <span class="identifier">colorSpace</span><span class="operator">:</span> <span class="string">"display-p3"</span> }); <span class="identifier">console</span>.<span class="identifier">log</span>(<span class="identifier">imageData</span>.<span class="identifier">colorSpace</span>); <span class="comment">// "display-p3" </span><span class="identifier">console</span>.<span class="identifier">log</span>([...<span class="identifier">imageData</span>.<span class="identifier">data</span>]); <span class="comment">// [128, 0, 0, 255] </span> <span class="comment">// Get ImageData converted to sRGB. </span><span class="identifier">imageData</span> <span class="operator">=</span> <span class="identifier">context</span>.<span class="identifier">getImageData</span>(<span class="number">0</span>, <span class="number">0</span>, <span class="number">1</span>, <span class="number">1</span>, { <span class="identifier">colorSpace</span><span class="operator">:</span> <span class="string">"srgb"</span> }); <span class="identifier">console</span>.<span class="identifier">log</span>(<span class="identifier">imageData</span>.<span class="identifier">colorSpace</span>); <span class="comment">// "srgb" </span><span class="identifier">console</span>.<span class="identifier">log</span>([...<span class="identifier">imageData</span>.<span class="identifier">data</span>]); <span class="comment">// [141, 0, 0, 255] </span></code></pre> <p>The <code>ImageData</code> constructor similarly takes an optional options object with a <code>colorSpace</code> key.</p> <pre><code class="javascript"><span class="keyword type">let</span> <span class="identifier">context</span> <span class="operator">=</span> <span class="identifier">canvas</span>.<span class="identifier">getContext</span>(<span class="string">"2d"</span>, { <span class="identifier">colorSpace</span><span class="operator">:</span> <span class="string">"display-p3"</span> }); <span class="comment">// Create and fill an ImageData with full Display P3 yellow. </span><span class="keyword type">let</span> <span class="identifier">imageData</span> <span class="operator">=</span> <span class="keyword operator">new</span> <span class="identifier">ImageData</span>(<span class="number">10</span>, <span class="number">10</span>, { <span class="identifier">colorSpace</span><span class="operator">:</span> <span class="string">"display-p3"</span> }); <span class="keyword control">for</span> (<span class="keyword type">let</span> <span class="identifier">i</span> <span class="operator">=</span> <span class="number">0</span>; <span class="identifier">i</span> <span class="operator"><</span> <span class="number">10</span> <span class="operator">*</span> <span class="number">10</span> <span class="operator">*</span> <span class="number">4</span>; <span class="operator">+</span><span class="operator">+</span><span class="identifier">i</span>) <span class="identifier">imageData</span>.<span class="identifier">data</span>[<span class="identifier">i</span>] <span class="operator">=</span> [<span class="number">255</span>, <span class="number">255</span>, <span class="number">0</span>, <span class="number">255</span>][<span class="identifier">i</span> <span class="operator">%</span> <span class="number">4</span>]; <span class="identifier">context</span>.<span class="identifier">putImageData</span>(<span class="identifier">imageData</span>, <span class="number">0</span>, <span class="number">0</span>); </code></pre> <p>As when drawing shapes using colors of a different color space, any mismatch between the <code>ImageData</code> and the target canvas color space will cause <code>putImageData</code> to perform a conversion and potentially clamp the resulting pixels.</p> <h2>Serializing canvas content</h2> <p>The <code>toDataURL</code> and <code>toBlob</code> methods on a <code>canvas</code> DOM element produce a raster image with the canvas contents. In WebKit, these methods now embed an appropriate color profile in the generated PNG or JPEG when called on a Display P3 canvas, ensuring that the full range of color is preserved.</p> <h2>Drawing wide gamut images</h2> <p>Like <code>putImageData</code>, the <code>drawImage</code> method will perform any color space conversion needed when drawing an image whose color space differs from that of the canvas. Any color profile used by a raster image referenced by an <code>img</code>, and any color space information in a video referenced by a <code>video</code> (be it a video file or a WebRTC stream), will be honored when drawn to a canvas. This ensures that when drawing into a canvas whose color space matches the display’s (be that Display P3 or sRGB), the source image/video and the canvas pixels will look the same.</p> <p>Here is an interactive demonstration of using canvas to make a sliding tile puzzle. The tiles are drawn by applying a clip path and calling <code>drawImage</code> pointing to the <code>img</code> element on the left, which references a wide gamut JPEG. Toggling the checkbox shows how the colors are muted when an sRGB canvas is used.</p> <figure id="puzzle" class="widescreen mattewhite aligncenter"> <p><iframe loading="lazy" src="https://webkit.org/blog-files/wide-gamut-canvas/puzzle.html" width="350" height="250"></iframe><figcaption>Sliding tile puzzle. Toggling the checkbox will change whether an sRGB or a Display P3 canvas is used. (<a href="https://webkit.org/blog-files/wide-gamut-canvas/puzzle.html">View as standalone page.</a>)</figcaption></figure> <h2>Web Inspector support</h2> <p>Web Inspector also now shows color space information for canvases to help ensure your canvases’ backing stores are in the expected color space.</p> <figure class="image"><picture title=""><source media="(prefers-color-scheme: dark)" srcset="/wp-content/uploads/Overview-Dark-1024x654.png 2x" class="wp-image-12126"><img srcset ="/wp-content/uploads/Overview-Light-1024x654.png 2x" alt="" class="wp-image-12125" /></picture></figure> <p>In the Graphics tab, the Canvases Overview will display the color space for each canvas next to the context type (e.g. 2D) on each canvas overview tile.</p> <figure class="image"><picture title=""><source media="(prefers-color-scheme: dark)" srcset="/wp-content/uploads/Details-Dark-1024x654.png 2x" class="wp-image-12128"><img srcset ="/wp-content/uploads/Details-Light-1024x654.png 2x" alt="" class="wp-image-12127" /></picture></figure> <p>After clicking on a Canvas overview tile to inspect it, the color space is shown in the Details Sidebar in the Attributes section.</p> <h2>Browser support</h2> <p>Wide gamut canvas is supported in the macOS and iOS ports of WebKit as of <a href="https://trac.webkit.org/changeset/283541/webkit">r283541</a>, and is available in Safari on:</p> <ul> <li>macOS Monterey 12.1 and above</li> <li>iOS 15.1 and above</li> </ul> <p>Safari is the first browser to support drawing shapes, text, gradients, and shadows with wide gamut CSS colors on Display P3 canvases. All other features, including <code>getImageData</code>, <code>putImageData</code>, and <code>drawImage</code> on Display P3 canvases, are supported in Safari and in Chrome 94 and above.</p> <h2>Feature detection</h2> <p>There are a few techniques you can use to detect whether wide gamut display and canvas support is available.</p> <p><strong>Display support:</strong> To check whether the display supports Display P3 colors, use the <code>color-gamut</code> media query.</p> <pre><code class="javascript"><span class="keyword type">function</span> <span class="identifier">displaySupportsP3Color</span>() { <span class="keyword control">return</span> <span class="identifier">matchMedia</span>(<span class="string">"(color-gamut: p3)"</span>).<span class="identifier">matches</span>; } </code></pre> <p><strong>Canvas color space support:</strong> To check whether the browser supports wide gamut canvases, try creating one and checking the resulting color space.</p> <pre><code class="javascript"><span class="keyword type">function</span> <span class="identifier">canvasSupportsDisplayP3</span>() { <span class="keyword type">let</span> <span class="identifier">canvas</span> <span class="operator">=</span> <span class="identifier">document</span>.<span class="identifier">createElement</span>(<span class="string">"canvas"</span>); <span class="keyword control">try</span> { <span class="comment">// Safari throws a TypeError if the colorSpace option is supported, but </span> <span class="comment">// the system requirements (minimum macOS or iOS version) for Display P3 </span> <span class="comment">// support are not met. </span> <span class="keyword type">let</span> <span class="identifier">context</span> <span class="operator">=</span> <span class="identifier">canvas</span>.<span class="identifier">getContext</span>(<span class="string">"2d"</span>, { <span class="identifier">colorSpace</span><span class="operator">:</span> <span class="string">"display-p3"</span> }); <span class="keyword control">return</span> <span class="identifier">context</span>.<span class="identifier">getContextAttributes</span>().<span class="identifier">colorSpace</span> <span class="operator">=</span><span class="operator">=</span> <span class="string">"display-p3"</span>; } <span class="keyword control">catch</span> { } <span class="keyword control">return</span> <span class="keyword literal">false</span>; } </code></pre> <p><strong>CSS Color Module Level 4 syntax support:</strong> To check whether the browser supports specifying wide gamut colors on canvas, try setting one and checking it wasn’t ignored.</p> <pre><code class="javascript"><span class="keyword type">function</span> <span class="identifier">canvasSupportsWideGamutCSSColors</span>() { <span class="keyword type">let</span> <span class="identifier">context</span> <span class="operator">=</span> <span class="identifier">document</span>.<span class="identifier">createElement</span>(<span class="string">"canvas"</span>).<span class="identifier">getContext</span>(<span class="string">"2d"</span>); <span class="keyword type">let</span> <span class="identifier">initialFillStyle</span> <span class="operator">=</span> <span class="identifier">context</span>.<span class="identifier">fillStyle</span>; <span class="identifier">context</span>.<span class="identifier">fillStyle</span> <span class="operator">=</span> <span class="string">"color(display-p3 0 1 0)"</span>; <span class="keyword control">return</span> <span class="identifier">context</span>.<span class="identifier">fillStyle</span> <span class="operator">!</span><span class="operator">=</span> <span class="identifier">initialFillStyle</span>; } </code></pre> <h2>Future work</h2> <p>There are a few areas where wide gamut canvas support could be improved.</p> <ul> <li>2D canvas still exposes image data as 8 bit RGBA values through <code>ImageData</code> objects. It may be useful to support other pixel formats for a greater color depth, such as 16 bit integers, or single precision or half precision floating point values, especially when wider color gamuts are used, since increased precision can help avoid banding artifacts. This has been proposed in an <a href="https://github.com/whatwg/html/issues/4167">HTML Standard issue</a>.</li> <li>The two predefined color spaces that are supported are sRGB and Display P3, but as High Dynamic Range videos and displays that support HDR become more common, it’s worth consdering allowing 2D canvas to use these and other color spaces too. See <a href="https://www.w3.org/Graphics/Color/Workshop/slides/talk/cameron">this presentation at the W3C Workshop on Wide Color Gamut and High Dynamic Range for the Web</a> from earlier this year, which talks about proposed new color space and HDR support.</li> <li>Canvas can be used with context types other than 2D, such as WebGL and WebGPU. A proposal for <a href="https://www.w3.org/Graphics/Color/Workshop/slides/talk/russell">wide gamut and HDR support in these contexts</a> was presented at that same workshop.</li> </ul> <h2>In summary</h2> <p>WebKit now has support for creating 2D canvas contexts using the Display P3 color space, allowing authors to make best use of the displays that are becoming increasingly common. This feature is enabled in Safari on macOS Monterey 12.1 and iOS 15.1.</p> <p>If you have any comments or questions about the feature, please feel free to send me a message at <a href="https://twitter.com/heycam">@heycam</a>, and more general comments can be sent to the <a href="https://twitter.com/webkit">@webkit</a> Twitter account.</p> <h2>Further reading</h2> <ul> <li><a href="https://webkit.org/blog/6682/improving-color-on-the-web/">Improving Color on the Web</a> (Dean Jackson, WebKit blog)</li> <li><a href="https://webkit.org/blog/10042/wide-gamut-color-in-css-with-display-p3/">Wide Gamut Color in CSS with Display-P3</a> (Nikita Vasilyev, WebKit blog)</li> <li><a href="https://drafts.csswg.org/css-color-4/">CSS Color Module Level 4</a> (W3C)</li> <li><a href="https://html.spec.whatwg.org/multipage/canvas.html#2dcontext">HTML Standard — The 2D rendering context</a></a> (WHATWG)</li> <li><a href="https://www.w3.org/Graphics/Color/Workshop/">W3C Workshop on Wide Color Gamut and High Dynamic Range for the Web</a> (W3C)</li> </ul> </div> </article> <aside class="nextrouter" aria-label="Next/Previous posts"> <div class="bodycopy"> <a class="page-numbers next-post" href="https://webkit.org/blog/12156/release-notes-for-safari-technology-preview-137/" rel="next"><div class="nextrouter-copy"><span class="label">Next</span><span class="title">Release Notes for Safari Technology Preview 137</span><span class="link">Learn more</span></div></a> </div> </aside> <aside class="nextrouter previous" aria-label="Next/Previous posts"> <div class="bodycopy"> <a class="page-numbers prev-post" href="https://webkit.org/blog/12140/new-webkit-features-in-safari-15-2/" rel="prev"><div class="nextrouter-copy"><span class="label">Previously</span><span class="title">New WebKit Features in Safari 15.2</span><span class="link">Learn more</span></div></a> </div> </aside> </div><!--.page-width--> </main><!-- #content --> <footer> <div class="page-width"> <nav id="footer-nav" aria-label="Footer menu"><div class="menu-footer-menu-container"><ul id="menu-footer-menu" class="menu"><li id="menu-item-7617" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-7617"><a rel="me" href="https://front-end.social/@webkit">@webkit@front-end.social</a></li> <li id="menu-item-5365" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-5365"><a href="https://webkit.org/sitemap/">Site Map</a></li> <li id="menu-item-4185" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-4185"><a href="http://www.apple.com/legal/privacy/">Privacy Policy</a></li> <li id="menu-item-4287" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-4287"><a href="https://webkit.org/licensing-webkit/">Licensing WebKit</a></li> <li id="menu-item-4187" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-4187"><a href="https://webkit.org/terms-of-use/">WebKit and the WebKit logo are trademarks of Apple Inc.</a></li> </ul></div></nav> </div> </footer> <script type="text/javascript" src="https://webkit.org/wp-content/themes/webkit/scripts/global.js?ver=1.0" id="theme-global-js"></script> </body> </html> <!-- Dynamic page generated in 0.332 seconds. --> <!-- Cached page generated by WP-Super-Cache on 2024-11-23 15:09:24 --> <!-- super cache -->