You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[css-color][css-images][css-ui] Allow light-dark(<image>, <image>) in cursor #13993
light-dark(<image>, <image>) was added recently, but the current definition of cursor doesn't allow it. I don't see why we should not allow it, as long as the arguments both follow the restrictions from cursor.
The only ambiguous case is light-dark(none, url(...)) or light-dark(none, none). I've disallowed this for now in WebKit since it wouldn't roundtrip, but maybe that's not the right way to go. It might also be confusing given the meaning of cursor: none.
The cursor property says supporting <image> is valid, which would include light-dark() right?
Yeah, but no UA currently supports the full range of <image> values at the moment and the browser vendors where reluctant to add support, as far as I know. Therefore, only <url> and <url-set> are required at the moment.
So I guess that limitation would continue to apply for light-dark(), right? So we'd basically have a third variant of that function that looks like this:
But yeah I guess specifying what is the cursor size of an image without an intrinsic size would be nice.
Currently that's up to the UA:
The UA may also support additional file formats, including SVG, as defined in [SVG11], in secure static mode or secure animated mode [SVG2], even if it does not have a natural size.
...
The default object size for cursor images is a UA-defined size that should be based on the size of a typical cursor on the UA’s operating system.
So, technically, the spec already allows for light-dark(<image>, <image>) in cursorwhile not enforcing it. But given the currently restricted syntax ofcursor, I think it should be made explicit that light-dark()is allowed to work incursor` even with the restricted syntax by defining it in the syntax as outlined in my previous comment plus a clarifying sentence.
Or we go further and define a new <natural-size-image> data type for cursor replacing the existing [ <url> | <url-set> ] that is specified to support everything <image> supports but is restricted to images with a natural size referenced by URL. This includes everything URL-related like <url>, <image-set()>, light-dark(), and also <cross-fade()>. Basically, the existing restriction is kept but extended to include light-dark() and cross-fade().
Therefore, my concrete proposal would be to change the <cursor-image> to this:
<cursor-image>= <natural-size-image> <number>{2}?
<natual-size-image> is a limited version of <image>, where the <image> sub-production is restricted to <url> only.
If we allow light-dark(none, *), this means image(...) needs to be allowed, for round-tripping. For now WebKit forbids it, since image(...) is not allowed.
Right. FWIW the restriction to <url> is kind of arbitrary because there can be <url>s without intrinsic sizes (like SVGs). I think the right thing to do is for the spec to define what the size should be (1em or something?).
Defining a default size would be helpful. Ladybird supports <image> cursors but basically just guesses what a reasonable cursor size might be. SVGs (IIUC) always have an aspect-ratio, but something like a gradient does not.
As for SVGs, if a default cursor size is defined, it needs to take into account that the image might not be square. If it has a 2:1 w:h ratio, would that then be shrunk to be 1em wide, or would it be 1em tall?
Why? It seems tangential. I agree you probably want to be able to define a cursor size for these maybe in the future, but that seems like a separate extension, and doesn't need shorthands?
Was there ever consideration of instead of having a new light-dark() image function, having image-set() support color scheme options by expanding the <image-set-option> production to something like
Apparently not recorded in that issue, but it was briefly considered, yes. I actually want to do less with image(); loading too much functionality into a single function is rarely a good idea. If the different pieces are actually intertwined it can make sense, sure, but the choice of light/dark is completely orthogonal to resolution, so it's probably better to have them be separate functions.
Activity
emilio commentedon May 31, 2026
nonewouldn't be ambiguous, because it should compute toimage(transparent), see #13866.The cursor property says supporting
<image>is valid, which would includelight-dark()right?SebastianZ commentedon May 31, 2026
Yeah, but no UA currently supports the full range of
<image>values at the moment and the browser vendors where reluctant to add support, as far as I know. Therefore, only<url>and<url-set>are required at the moment.So I guess that limitation would continue to apply for
light-dark(), right? So we'd basically have a third variant of that function that looks like this:Sebastian
nt1m commentedon May 31, 2026
It is, since cursors doesn't support generated images (which includes
image(transparent))cursor doesn't use
<image>https://drafts.csswg.org/css-ui/#typedef-cursor-cursor-image
emilio commentedon May 31, 2026
Well, right under that there is:
But yeah I guess specifying what is the cursor size of an image without an intrinsic size would be nice.
SebastianZ commentedon May 31, 2026
Currently that's up to the UA:
So, technically, the spec already allows for
light-dark(<image>, <image>) incursorwhile not enforcing it. But given the currently restricted syntax ofcursor, I think it should be made explicit thatlight-dark()is allowed to work incursor` even with the restricted syntax by defining it in the syntax as outlined in my previous comment plus a clarifying sentence.Or we go further and define a new
<natural-size-image>data type forcursorreplacing the existing[ <url> | <url-set> ]that is specified to support everything<image>supports but is restricted to images with a natural size referenced by URL. This includes everything URL-related like<url>,<image-set()>,light-dark(), and also<cross-fade()>. Basically, the existing restriction is kept but extended to includelight-dark()andcross-fade().Therefore, my concrete proposal would be to change the
<cursor-image>to this:<natual-size-image>is a limited version of<image>, where the<image>sub-production is restricted to<url>only.Sebastian
nt1m commentedon May 31, 2026
If we allow light-dark(none, *), this means image(...) needs to be allowed, for round-tripping. For now WebKit forbids it, since image(...) is not allowed.
emilio commentedon Jun 1, 2026
Right. FWIW the restriction to
<url>is kind of arbitrary because there can be<url>s without intrinsic sizes (like SVGs). I think the right thing to do is for the spec to define what the size should be (1em or something?).AtkinsSJ commentedon Jun 1, 2026
Defining a default size would be helpful. Ladybird supports
<image>cursors but basically just guesses what a reasonable cursor size might be. SVGs (IIUC) always have an aspect-ratio, but something like a gradient does not.As for SVGs, if a default cursor size is defined, it needs to take into account that the image might not be square. If it has a 2:1 w:h ratio, would that then be shrunk to be 1em wide, or would it be 1em tall?
LeaVerou commentedon Jun 2, 2026
Sounds like we need to make
cursora shorthand ofcursor-sizeandcursor-image?emilio commentedon Jun 2, 2026
Why? It seems tangential. I agree you probably want to be able to define a cursor size for these maybe in the future, but that seems like a separate extension, and doesn't need shorthands?
CGQAQ commentedon Jun 3, 2026
cc @lilles
Related to the crash you assigned to me, maybe the cursor should've never been allowed to support
light-dark(gradient, none)What is your options on this issue?
lilles commentedon Jun 3, 2026
No preference.
weinig commentedon Jun 4, 2026
Was there ever consideration of instead of having a new
light-dark()image function, havingimage-set()support color scheme options by expanding the<image-set-option>production to something likeThen this would happen organically.
Crissov commentedon Jun 8, 2026
I mentioned this option in #12513, but it does not seem to have been considered by the WG.
tabatkins commentedon Jun 8, 2026
Apparently not recorded in that issue, but it was briefly considered, yes. I actually want to do less with
image(); loading too much functionality into a single function is rarely a good idea. If the different pieces are actually intertwined it can make sense, sure, but the choice of light/dark is completely orthogonal to resolution, so it's probably better to have them be separate functions.weinig commentedon Jun 8, 2026
I filed a separate issue to continue the discussion about using image-set() for light/dark - #14022.