Skip to content

[css-color][css-images][css-ui] Allow light-dark(<image>, <image>) in cursor #13993

Open

Description

@nt1m

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.

cc @tabatkins @LeaVerou @emilio

Activity

  1. emilio commented on May 31, 2026

    @emilio
    Collaborator

    none wouldn't be ambiguous, because it should compute to image(transparent), see #13866.

    The cursor property says supporting <image> is valid, which would include light-dark() right?

  2. SebastianZ commented on May 31, 2026

    @SebastianZ
    Contributor

    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:

    light-dark( [ <url> | <url-set> ], [ <url> | <url-set> ] )

    Sebastian

  3. nt1m commented on May 31, 2026

    @nt1m
    MemberAuthor

    none wouldn't be ambiguous, because it should compute to image(transparent), see #13866.

    It is, since cursors doesn't support generated images (which includes image(transparent))

    The cursor property says supporting <image> is valid, which would include light-dark() right?

    cursor doesn't use <image>
    https://drafts.csswg.org/css-ui/#typedef-cursor-cursor-image

  4. emilio commented on May 31, 2026

    @emilio
    Collaborator

    Well, right under that there is:

    Conforming user agents may, instead of <url> and <url-set>, support <image> which is a superset.

    But yeah I guess specifying what is the cursor size of an image without an intrinsic size would be nice.

  5. SebastianZ commented on May 31, 2026

    @SebastianZ
    Contributor

    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.

    Sebastian

  6. nt1m commented on May 31, 2026

    @nt1m
    MemberAuthor

    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.

  7. emilio commented on Jun 1, 2026

    @emilio
    Collaborator

    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?).

  8. AtkinsSJ commented on Jun 1, 2026

    @AtkinsSJ
    Contributor

    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?

  9. LeaVerou commented on Jun 2, 2026

    @LeaVerou
    Member

    Sounds like we need to make cursor a shorthand of cursor-size and cursor-image?

  10. emilio commented on Jun 2, 2026

    @emilio
    Collaborator

    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?

  11. CGQAQ commented on Jun 3, 2026

    @CGQAQ

    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?

  12. lilles commented on Jun 3, 2026

    @lilles
    Member

    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?

    No preference.

  13. weinig commented on Jun 4, 2026

    @weinig
    Contributor

    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

    <image-set-option> = [ <image> | <string> ]
                         [ <resolution> || type(<string>) || [ light | dark ] ]?
    

    Then this would happen organically.

  14. Crissov commented on Jun 8, 2026

    @Crissov
    Contributor

    I mentioned this option in #12513, but it does not seem to have been considered by the WG.

  15. tabatkins commented on Jun 8, 2026

    @tabatkins
    Member

    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.

  16. weinig commented on Jun 8, 2026

    @weinig
    Contributor

    I filed a separate issue to continue the discussion about using image-set() for light/dark - #14022.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions