css icon indicating copy to clipboard operation
css copied to clipboard

Apply multiple font properties with the same name

Open ceopaludetto opened this issue 10 months ago • 3 comments

Description

In tailwindcss@v3 it is possbile to configure fonts in this way:

theme: {
  fontFamily: {
    sans: ["Inter"]
  },
  fontSize: {
    "label-large": [14, { fontWeight: 500, letterSpacing: 0.5, lineHeight: 20 }]
  }
}

Which roughly generates the following:

<p class="text-label-large">Hi</p>
.text-label-large {
  font-family: Inter;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.5;
  line-height: 20;
}

So I tried to do the same in @master/css@v2 with the following:

variables: {
  "font-family": {
    test: ["arial", "sans-serif"],
  },
  "font-weight": {
    test: 500,
  },
  "font-size": {
    test: 20,
  },
  "line-height": {
    test: 1.5,
  },
}

But due to name collision, only font-weight is applied:

<p class="font:test">Hi</p>
.font\:test {
  font-weight: 500;
}

It is possible to achieve the same functionality? This can be really useful to implement material 3 typography scale system

ceopaludetto avatar Apr 27 '25 17:04 ceopaludetto

@ceopaludetto This is expected. In Master CSS, we deliberately map certain CSS properties ambiguously to a shared variable namespace in order to simplify the markup. https://github.com/master-co/css/blob/rc/packages/core/src/config/rules.ts#L192-L199

Therefore, if a collision occurs, you should write out the full variable name.

<div class="font-weight:font-weight-test">

However, this is admittedly a somewhat awkward behavior, and we will further evaluate how to improve it.

Alternatively, what we might need is a warning to alert developers when a collision occurs.

1aron avatar Apr 27 '25 18:04 1aron

I was able to achieve what I want by creating a new rule:

rules: {
  typography: {
    subkey: "typ",
    declare(value) {
      if (!this.css.variables.has(`font-size-${value}`))
        return {};
          
      return {
        "font-family": this.css.variables.get(`font-family-sans`)!.value.toString(),
        "font-size": toRem(this.css.variables.get(`font-size-${value}`)!.value),
        "font-weight": this.css.variables.get(`font-weight-${value}`)!.value,
        "line-height": toRem(this.css.variables.get(`line-height-${value}`)!.value),
        "letter-spacing": toRem(this.css.variables.get(`letter-spacing-${value}`)!.value),
      };
    },
  },
},

Then I just use like this:

<p class="typ:test">Hi</p>

Which generates:

.typ\:test{
  font-family: ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;
  font-size: 1.25rem;
  font-weight: 500;
  line-height: 1.25rem;
  letter-spacing: 0.03125rem;
}

ceopaludetto avatar Apr 27 '25 18:04 ceopaludetto

I was able to achieve what I want by creating a new rule:

rules: { typography: { subkey: "typ", declare(value) { if (!this.css.variables.has(font-size-${value})) return {};

  return {
    "font-family": this.css.variables.get(`font-family-sans`)!.value.toString(),
    "font-size": toRem(this.css.variables.get(`font-size-${value}`)!.value),
    "font-weight": this.css.variables.get(`font-weight-${value}`)!.value,
    "line-height": toRem(this.css.variables.get(`line-height-${value}`)!.value),
    "letter-spacing": toRem(this.css.variables.get(`letter-spacing-${value}`)!.value),
  };
},

}, }, Then I just use like this:

Hi

Which generates:

.typ:test{ font-family: ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji; font-size: 1.25rem; font-weight: 500; line-height: 1.25rem; letter-spacing: 0.03125rem; }

Nice! Or you can just use config.components

export default {
    components: {
        typ: 'font-family:font-family-sans ...'
    }
}

1aron avatar Apr 28 '25 01:04 1aron