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

Return numeric values in precomputeValues #82

Open
souporserious opened this issue Mar 25, 2022 · 4 comments
Open

Return numeric values in precomputeValues #82

souporserious opened this issue Mar 25, 2022 · 4 comments
Labels
enhancement New feature or request

Comments

@souporserious
Copy link

Hello again 😊 I've been using Capsize recently with REM units and ThreeJS which relies on World units and was wondering if you'd be interested in simplifying precomputeValues to numeric values to better serve these use cases? This would be a breaking change so totally understand if you'd rather not change the API this much, but I think something along the lines of this would help:

const values = precomputeValues({ fontMetrics, capHeight: 2, lineGap: 1 })
const textStyles = {
  fontSize: `${values.fontSize}rem`,
  lineHeight: `${values.lineHeight}rem`,
  marginTop: `${values.capHeightTrim}rem`,
  marginBottom: `${values.baselineTrim}rem`
}

So you'd get numeric values back that are more flexible to work with and instead of using em units for the trim values, I propose multiplying the value by the font size so it can be used with libraries like ThreeJS where relative values don't exist.

Right now I simply parse and round the incoming values myself which is working well:

export const roundValue = (value) => {
  return Math.round(parseFloat(value) * 10000) / 10000
}

export function createTextStyles({
  capHeight,
  lineGap,
}: {
  capHeight: number
  lineGap: number
}) {
  const values = precomputeValues({ fontMetrics, capHeight, lineGap })
  return {
    fontSize: roundValue(values.fontSize),
    lineHeight: roundValue(values.lineHeight),
    leadingTrim: roundValue(lineGap / 2),
  }
}

Happy to work on a PR for this if it sounds like something you'd want to add 🙂

@souporserious souporserious changed the title Simplify precomputeValues Return numeric values in precomputeValues Mar 25, 2022
@michaeltaranto
Copy link
Contributor

Hey Travis, very much interested in supporting relative units but have not found the right approach just yet. Curious to see what direction you've taken things and see what is working.

@souporserious
Copy link
Author

Awesome! Yeah, for sure! I think it should be a simple tweak. Here is a working Codesandbox to see an example.

@robertpiosik
Copy link

My relative units workaround is based on 62.5% font-size on html trick, with that, just dividing numeric values of font-size and line-height by 10 do the job.

@andriytyurnikov
Copy link

@michaeltaranto , @souporserious I have found a solution, which also allows CSS-heavy implementation, yet I would have to dive into details, because I have faced two serious browser limitations:

  • one can not divide rem/rem in css calc()
  • Chrome limits on calc(calc(...)) nesting prevent one from using full formula in CSS calc.

There are two aspects of workaround:

  • use values of same size units (rem), but use them as numeric values, and only cast rem type on usage.
  • pre-compute some values at compile-time

Example:

    --pro-rata-cap-height-trim:
      calc(
        (
          var(--pro-rata-precomputed-cap-height-trim-factors)
          -
          (
            (
              (
                var(--pro-rata-precomputed-line-height-scale) /* 1.362 */
                *
                var(--pro-rata-font-size)
              )
              - 
              var(--pro-rata-line-height) /* Dynamic numeric, latter converted to rem */
            )
            /
            2
            / 
            var(--pro-rata-font-size) /*  Dynamic numeric, latter converted to rem  */
          )
        )
        * 
        (-1) /* you may use (-1em) here and only here, if you want, actually */
      );
  }
  • Here you may see --pro-rata-precomputed-cap-height-trim-factors and --pro-rata-precomputed-line-height-scale parameters, values of those may be statically pre-computed in JS, and injected into utility class for any given font-family to work around CSS calc(calc(...)) call stack limitations.
    In fact it is an inlined memoization of statically calculated value of expression:
(ascentScale - capHeightScale + lineGapScale)

inlined to offset some portion of calculations into compile-time.

  • CSS variables --pro-rata-font-size and --pro-rata-line-height are set as numeric values, not as rem, and type casted at final stage:
/* utility class for font-size */
.pro-rata-cap-size-2 {
    --pro-rata-cap-size: 0.5; /* numeric, not rem */
    --pro-rata-font-size: 
      calc(
        var(--pro-rata-cap-size) 
        / var(--pro-rata-cap-height-scale)
      );
    
    font-size: calc(var(--pro-rata-font-size) * 1rem);
  }

Illustrative draft implementation is visible here: https://github.com/andriytyurnikov/andriytyurnikov.github.io/blob/main/src/pro-rata.css,
tailwind plugin is planned sometime later.

@michaeltaranto michaeltaranto added the enhancement New feature or request label Feb 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants