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.
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! 🌈
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>
<script>
console.log(window.getComputedStyle(document.getElementById("test")).backgroundColor);
</script>
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.
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. 😄