Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gradient type feedback #101

Open
c1rrus opened this issue Jan 13, 2022 · 10 comments
Open

Gradient type feedback #101

c1rrus opened this issue Jan 13, 2022 · 10 comments

Comments

@c1rrus
Copy link
Member

c1rrus commented Jan 13, 2022

Is the gradient composite type fit for purpose? Does it need to also specify the type of gradient (.e.g linear, radial, concial, etc.)?

Please share your feedback, thoughts and ideas in this issue.

@c1rrus c1rrus added the dtcg-format All issues related to the format specification. label Jan 13, 2022
@drwpow
Copy link
Contributor

drwpow commented Jan 13, 2022

Does it need to also specify the type of gradient (.e.g linear, radial, concial, etc.)?

I do really like the proposal here, and I like the simplicity of having the gradient stops be universal, where you decide linear, radial, conical when generating code for a specific component (which in one part makes sense because a rotated gradient is still the same gradient).

But there also seems like an opportunity here to make linear-gradient, radial-gradient, and conic-gradient their own types to fill in the missing data (which exist as a concept both in CSS and Figma). Overall I fear that people may just abuse metadata on gradients here and put all the missing parts in there, at which point distinct types would be more useful. I could go either way—one gradient type with stops only, or distinct gradient types with complete properties.

@TravisSpomer
Copy link

Omitting details like the type of gradient doesn't make much sense to me. A reasonable expectation is that for any given token, a design tool has everything it needs to display that gradient (like a Figma style), and a dev tool has everything it needs to turn that token definition into code. The current gradient spec doesn't work for either case. As it stands, I'm not really sure how I could use a gradient token for anything at all, without encoding all of the missing information as extensions.

At absolute minimum, I think that a gradient token needs to also include:

  • The type of gradient
  • The start and end points (0-1)

It would also be unfortunate if gradient stops were limited to specifying stops as a number 0-1. Other systems also allow stops to be defined as absolute units. For example, you might specify a gradient as going from black at 0, to transparent at 10px, to transparent at 1—that would get you a "poor man's shadow" that was always 10px wide no matter the size of the object you paint with it. That's admittedly a less common case, but it's something that I'm using today to support web and WinUI, and to continue supporting it I'd need to add an extension property like "actuallyTheseAreTheRealGradientStops": [ 0, "10px", 1 ].

@kaelig kaelig added the Needs Feedback/Review Open for feedback from the community, and may require a review from editors. label Mar 8, 2022
@solemone
Copy link

solemone commented Apr 4, 2022

Hello everyone,

I have a question about the number of gradients. How about multiple gradients? Is the value then an array with arrays? Like like this:

{
  "blue-to-red": {
    "$type": "gradient",
    "$value": [
      [
        {
          "color": "rgba(0, 0, 255, 0.5)",
          "position": 0
        },
        {
          "color": "rgba(0, 0, 255, 1)",
          "position": 1
        }
      ],
      [
        {
          "color": "rgba(255, 0, 0, 1)",
          "position": 0
        },
        {
          "color": "rgba(255, 0, 0, 0.5)",
          "position": 1
        }
      ]
    ]
  }
}

Or is this a different type like »multifill«?
And what about when gradients are to be mixed with solid color? Could this be something like this:

{
  "blue-and-red": {
    "$type": "multifill",
    "$value": [
      {
        "$type": "color",
        "$value": "rgba(0, 0, 255, 0.5)",
      },
      {
        "$type": "gradient",
        "$value": [
          {
            "color": "rgba(255, 0, 0, 0.5)",
            "position": 0
          },
          {
            "color": "rgba(255, 0, 0, 1)",
            "position": 1
          }
        ]
      }
    ]
  }
}

Thanks for all the work!

@NateBaldwinDesign
Copy link

I agree supporting other gradient types is necessary, but I am of the opinion it doesn't need to be a different token type itself.

I would like a few things here:
First, it would be nice to have a default inferred from a list of values. Ie, values: [#ff0000, #0000ff] will automatically infer placement to be [0,1]. Reason being, it may be unnecessary, bloat, or redundant based on certain use cases. My next ask will shed more light.

Secondly, I would like the option to just pass an array of values. I go at great lengths to make perceptually balanced gradients, and given technological restrictions, most of the time an array of many values (spaced equidistant in the range) is the best way to replicate the gradient. For instance, if I have a gradient with 20 unique colors, it would be tedious to write all the intervals in the proposed format.

Thirdly, it would be great to include an option for interpolation color space. Technology is working to catch up on this notion and certain design tools support it. For instance, defaulting to rgb interpolation is ok, however I may want to use OKLCH for a multi hue gradient. Interpolation color space options can reduce the number of individual color values needed to replicate a perceptually balanced gradient (within these examples)

@kitgrose
Copy link

kitgrose commented Jul 8, 2022

It's a shame to see that there's no spec support for opacity stops being defined independently of colour stops. I recognise that many modern design tools don't make this easy (or even possible) either, but it's something I'd expect to be able to specify in an interchange format.

As a simplified example, if I have a gradient that blends across some number of stops (e.g. black → white), and simultaneously an alpha blend with a different number of stops (e.g. from 100% → 0% → 100% opacity), or with stops at different locations, the final result requires all intermediate stops (in this example case middle grey) be computed at export time. That prevents these gradients from being properly round-tripped back into design software that separates these two concepts (e.g. Photoshop), and also prevents the use of colour aliases for the individual stop values.

Ideally computing all the individual distinct stop values would be a transformation step performed afterwards based on the technical capabilities of the output format (so that if some output language supported the distinction between opacity and colour stops, that could be supported by the same design token file).

Here's an example of an online tool that attempts to support computing interpolated colour stops based on independent alpha and colour stops to give you a sense of what I mean (although in practice, CSS has issues properly representing colour stops that have zero opacity, effectively ignoring their colour—the "correct" output can be obtained using SVG, though).

@kevinmpowell kevinmpowell added this to the Next Draft Priority milestone Oct 3, 2022
@kevinmpowell kevinmpowell removed Needs Feedback/Review Open for feedback from the community, and may require a review from editors. dtcg-format All issues related to the format specification. labels Oct 3, 2022
@putchom
Copy link

putchom commented Jan 4, 2023

I think $value needs an angle property because Figma, CSS, etc. allow angles to be specified for gradients.

like this:

{
  "blue-to-red": {
    "$type": "gradient",
    "$value": {
      "angle": 45,
      "colors": [
        {
          "color": "#0000ff",
          "position": 0
        },
        {
          "color": "#ff0000",
          "position": 1
        }
      ]
    }
  }
}

@PavelLaptev
Copy link
Contributor

PavelLaptev commented Jun 26, 2023

Agreed with @drwpow gradient tokens is a very abstract entity. So there should be a definition:

GradientToken {
  $type: "gradient";
  $value: {
    type: "linear" | "radial" | "angular" | "conic";
    angle: number;
    stops: {
      position: number;
      color: ColorToken | string;
    }[];
  };
}

@PavelLaptev
Copy link
Contributor

For "radial" gradients, there also should be a size property, e.g.:

GradientToken {
  $type: "gradient";
  $value: {
    type: "linear" | "radial" | "angular" | "conic";
    angle: number;
    size: "30% 50%"
    stops: {
      position: number;
      color: ColorToken | string;
    }[];
  };
}

@pcjmfranken
Copy link

pcjmfranken commented Aug 6, 2023

Colour stop easing functions could very well end up making it into the CSS Images Module Level 4 spec. It is actively being discussed here: w3c/csswg-drafts#1332. Additionally, use of this technique seems surprisingly common amongst designers, but I've only seen it done by means of third party plugins (design tools lacking native support, I assume).

The eased transition between two colours will be different when those are interpolated to different colour spaces. Preserving the actual function type and parameter values as a token value is therefore essential.

Additional resources:

@jorenbroekema
Copy link

jorenbroekema commented May 13, 2024

I wanted to add to this discussion that the gradient types I've heard here are mostly static by nature, even though the shapes can be defined as "linear", "conicol", "angular", "radial", "diamond", whatever, the color stops are a single dimensional array and the shape of the gradient can be defined "statically" with a string enum.

There are also types of gradient which I see used more and more in modern designs, which cannot be defined by a string enum to describe statically what the shape of the gradient looks like:

  • Gradient meshes
  • Freeform gradients
    E.g. in Adobe Illustrator, example video: https://www.youtube.com/watch?v=fhB5tTTLqDU
    Especially for freeform gradients, I can imagine huge platform-specific differences in how they are rendered, which is already a factor for simple gradients.

I think it would be smart to at least distinguish between these two types of gradients, once that have a standardized "shape" and those that do not. And at least not jam those two into the same token type 😅 .

For the standardized shapes gradients, the main thing I'm missing:

  • color stops are defined on a 1 dimensional plane, so the angle of the gradient is not included, I think it makes sense that gradient stops have X Y and maybe even Z coordinates for 3D gradients, which could be used in 3D rendering software where 3D color interpolation is actually pretty common. This also means we don't need a separate "angle" property. I think this aligns more with how design tools currently let you work with gradients (Illustrator gradient tool, figma gradient paint)
  • easing, e.g. a percentage or number between 0 and 1 that describes the relationship between 2 stops in how strong one is compared to the other, I wonder whether that should be defined inside the stops or in a sibling property that is indexed to the stops array somehow.

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

No branches or pull requests