Rego’s Everyday Life

A blog about my work at Igalia.

Coloring the insertion caret

On the last weeks Igalia has been working in adding support for caret-color property on Blink. This post is a summary of the different tasks done to achieve it.

First steps #

Basically I started investigating a little bit the state of art. caret-color is defined in the spec called CSS Basic User Interface Module Level 3, it’s a Candidate Recommendation so browsers should be happy to implement it. However the property is marked as at-risk due to the lack of implementations (I talked to the spec editor, Florian Rioval, to confirm it).

Update: caret-color is no longer at-risk thanks to Chromium and Firefox implementations.

Then the first thing was to send the Intent to Implement and Ship: CSS UI: caret-color property mail to blink-dev. The feedback was possitive as it’s a small change without a big impact, and the intent was approved.

Initial support #

My colleague Claudio Saavedra had already implemented caret-color support for Bloomberg in their downstream port a few years ago. And they have been using it successfully on the terminals. In addition, as you can see in this mail by Lea Verou on the CSS Working Group (CSS WG) mailing list, there’s a clear author demand for more control over the caret color.

Basically the task was adding a new CSS property to the Blink parser and change the color of the insertion caret to use it. The latter was basically changing a line and using caret-color instead of color to determine it.

Adding the CSS property was not hard, but there’s something special regarding caret-color as it’s the first color property that accepts auto as value. So far auto is going to be implemented as currentColor, but in the future it can be tweaked to “ensure good visibility and contrast with the surrounding content”. For that reason the patch needed some extra work on top of a regular color.

caret-color example `caret-color` example

Making caret-color animatable #

The next step was making caret-color animatable. Again this would be fairly easy if it was a regular color, but due to the auto value it needed some special changes.

The important thing here is that auto is not interpolable, so if you do something like this:

  .foo {
color: initial;
caret-color: auto;
transition: all 1s;
.foo:hover {
color: green;
caret-color: lime;

The color of the text will interpolate from black to green, but the color of the insertion caret will do a discrete jump from black to lime. This might be seen as a weird behavior, but it was discussed and verified with the CSS WG.

Anyway the patch has landed and you can now enjoy your rainbow caret! 🌈

caret-color animation example

The resolved value #

Another thing that was clarified with the CSS WG is related to the resolved value of caret-color property.

In CSS you can have specified value, computed value, used value and resolved value. This is not the post to explain on this, so I’ll jump directly into the details of what was related to caret-color implementation.

For color properties we’re used to have as resolved value (the one returned by getComputedStyle()) the used value, a numeric color with a format like rgb(X, X, X). For example, in the following snippet you would get as resolved value rgb(0, 255, 0) in the console log:

  <div id="test" style="color: lime; background-color: currentColor;"></div>

However, that was not in the specs, and initially caret-color tests were checking that the resolved value was auto or currentColor. This has been modified and now it’ll behave like the rest of the color properties.

W3C Test Suite #

Of course we need tests for all this stuff, but Florian had already created a few tests related to caret-color on the csswg-test repository. So I used them as base and contributed a few more to check all the stuff needed regarding the implementation.

The good news is that now there are 21 tests checking caret-color that are upstream on the W3C repository and can be used by the rest of browsers to verify the interoperability.

This test suite is being used in Blink to verify that the current implementation is spec compatible. Right now only 1 test is failing due to a known bug regarding animations.

Conclusions #

caret-color support is already available on Chrome Canary, and it’ll be hitting stable in Chrome 57. Please start playing with it and let me know if you find any issue.

The good news is that thanks to all the discussions inside the CSS WG, Firefox implementation got reactivated and caret-color is supported there now too! It’ll be included in Firefox 53. Also Mozilla folks have wrote the documentation at MDN.

Regarding other browsers, in WebKit the bug has been reported and Blink patches could be somehow ported; in Edge I added a new feature request vote for it if you’re interested.

Acknowledgements #

First I’d like to thank Bloomberg for sponsoring, once again, Igalia to do this work. It’s really nice to keep adding valuable features to the web.

This is the kind of things where Igalia can be the perfect partner for your company. Some features that might be interesting for your organization but are not in the roadmap or priorities of the browser vendors. We can help to discuss the feature with the standards body and push to get it implemented on the open source browsers. Of course, not everything will be accepted upstream, but in some situations (like the caret-color property), it’s possible to make it for real.

If you’d like to do this kind of work in Igalia, don’t miss the opportunity to join us. We’ve recently opened a position for a Chromium developer, take a look to it and send us your application if you’re interested.

Igalia logo Bloomberg logo
Igalia and Bloomberg working together to build a better web

Also thanks to Florian Rioval for replying so fast to all my questions and doubts regarding caret-color and the spec. He was very kind quickly reviewing all my tests for the W3C csswg-test repo.

Finally thanks to the reviewers (specially Alan Cutter and Timothy Loh) and other people commenting on the different issues for all your patience with me. 😄