Web App
by Xidorn Quan
Using an eyedropper to pick a color from the screen is ubiquitous for design software, yet Canva has lacked such a functionality on the web app until very recently. With the release of browsers based on Chromium 95, including Microsoft Edge 95 and Google Chrome 95, web users can now enjoy the eyedropper inside Canva.
While an eyedropper looks like a simple and innocent feature, it’s hard to implement with existing web APIs. To pick a color from the screen, the web app needs the ability to read the color of an arbitrary pixel, which could then be used to generate a full image on the screen; even if the user only wants to give one pixel of color. Granting such access to websites would implicitly be a disaster for privacy. An adversarial website might be able to know what applications you’re using, what tabs are opened in your browser, what files are on your desktop, etc.
The Screen Capture API already exists to capture the screen content, but it requires user authorization on both the browser and sometimes the operating system. This authorization would look confusing and scary for users especially because it is rarely used. They wouldn’t expect the website to record their screen when they are just asking for a tool to pick a color. Another problem with this API is that it is designed for screen sharing, so the content it captures is in the form of a video stream. A video stream might not be a pixel-perfect match to the color on the screen, and for color picking, we want the color to be as precise as possible.
While showing an eyedropper to pick an arbitrary color on the screen is impossible without user permission, it’s not impossible to offer one for content inside the boundary of a specific web page. In many cases, our users probably just want to pick a color from within their design.
However, this is still not easy for us to implement.
In Canva, designs are rendered mostly with native CSS, HTML, and SVG. These technologies enable us to utilize browser functionalities without having to reinvent some significant parts of the rendering stack from scratch, especially for features around text and video but there are always trade-offs. Using native CSS and HTML means it’s hard to rasterize page content within the browser, again for security and privacy reasons.
Historically, websites are allowed to load resources they don’t own, including pages in iframes, images, stylesheets, and scripts, and those resources are loaded with user cookies attached by default. If a website has access to the pixel data of the page, it might gain access to cross-origin information that it shouldn’t know by loading those resources, such as your avatar on Facebook.
Worse, the infamous CSS selector, :visited
, allows websites to style an element with different colors based on whether a link was visited before. For example, on Google or DuckDuckGo, you can see the link to a page you visited before being purple, while unvisited pages are blue. This is very useful for users to know what pages they’ve visited, but if the website can read the colors, it could be able to partially extract the browsing history from it by putting a lot of links on a page and rasterizing them.
It is possible to rasterize an arbitrary DOM tree throug