Skip to content

[css-fonts] font-weight: bolder and lighter are counter-intuitive #2764

Open

Description

@Wes1262

I'm not sure if it will be possible with future calc() improvements, but it would be great if it was possible to write:

strong {
    font-weight: calc(inherit + 100); /*
    font-weight: calc(inherit + 200);
    font-weight: calc(inherit + 300);
    font-weight: calc(inherit + 400);
    font-weight: calc(inherit + 500);
    font-weight: calc(inherit + 600);
    font-weight: calc(inherit + 700);
    font-weight: calc(inherit + 800); */    
}

As opposed to bolder and lighter that are really hard to use and that never do what the designer wants.

Thanks in advance.

Activity

  1. upsuper commented on Jun 14, 2018

    @upsuper
    Member

    Allowing inherit in calc is probably a major CSS syntax change which may relate to CSS Syntax and probably CSS Cascading.

  2. tabatkins commented on Jun 14, 2018

    @tabatkins
    Member

    There's nothing wrong with it Syntax-wise (global keywords aren't handled at that level). Handling global keywords in the middle of other properties isn't problematic either - you can already do that in font-family. (font-family: foo inherit; is fine, it refers to a font named "foo inherit".)

    It's just putting keywords into calc() that's problematic right now. But grabbing the inherited value of a property via a function or something shouldn't be problematic.

  3. Wes1262 commented on Jun 15, 2018

    @Wes1262
    ContributorAuthor

    Actually, maybe it's better to have a special value like "bolder" and "lighter" that instead selects the immediately larger or lighter weights available for the current font.

    In other words, font-weight: calc(inherit + 100) will have no effect if inherit is 300 and there is no 400 font-weight for the current font.

  4. upsuper commented on Jul 3, 2018

    @upsuper
    Member

    But grabbing the inherited value of a property via a function or something shouldn't be problematic.

    I moderately disagree with this. It may not be a problem for font-weight especially given that it doesn't seem likely that we are going to extend it to a multi-value property. But it could happen that a property which currently only accepts a single numeric value can be extended to support non-numeric (computed) value, multiple values, or even be converted into shorthand. In those cases, we may have trouble to continue supporting this mechanism in those properties.

    (Actually it's not even clear to me whether font-weight is going to be stuck in its current form. For example, could there be some new kind of font variation axis which supports adjusting vertical and horizontal direction weight differently, and its request becomes common so that we want to have font-weight support it directly?)

  5. WebMechanic commented on Jan 25, 2020

    @WebMechanic

    came here via #2764 (reference)
    so.. bump!

    The above problem could be fixed if the bolder and lighter keywords would actually do what their name suggests; at least for variable fonts. No need for keyword handling in calc() then.

    Maybe some variation of current() or inherited() could do the trick if nesting functions in calc() is supposedly easier. But that's a different story to than using an unknown variable set of bolder/lighter fonts.

    Variable Fonts are a thing now!

    Unfortunately neither "bolder" nor "lighter" move to the next weight variation within a variable font, but act binary as "bold" or "un-bold" aka "normal". That was fine when most ordinary fonts typically featured a binary state for normal/bold as well.

    Also going bolder or lighter (font wise) within nested elements does not imply moving in steps of 100 only. A variable font could contain just three presets for its the "wght" axis using 200, 400, 600 or any other set of arbitrary numbers between 1 and 1000.
    The same is true for an equivalent set of carefully crafted @font-face declarations using classic single font files.

    With a fallback list of different variable fonts such as font-family: "Bahnschrift", "League Spartan Variable", "Source Sans Pro" one could build a working ramp of the proper font-weights of such fonts whilst being ignorant about what "wght" values actually exist.

    Using "bolder" or "lighter" could (should) continiously select the next available weight variation.

    Here each letter of the words "Fonts" and "Mood" is a set of nested <b> elements that might progressively get bolder from whatever weight <p> currently has set and eventually reaches whatever weight ("wght") the font's upper limit would be.

    b {font-weight:bolder} /* life could be easy ... */
    <!-- crudo ma bello -->
    <p>Variable <b>F<b>o<b>n<b>t<b>s</b></b></b></b></b> R <strong>côôl</strong></p>
    <p>G<b>o<b>o<b>o<b>o<b>o<b>d</b> Morning</b></b></b></b></b></p>

    variable-bolder-fonts
    Although the markup is ugly, the CSS remains fairly simple and intuitive.

    Today I can do the same thing but with much more effort and have to use an explicit amount of nested B selectors - unlike the oneliner above. I also need to keep the ramp values at a specific start/end point or the result could look choppy when used in a possibly different context.
    If <p> happens to be set elsewhere to the usual normal (400), the effect would not look as intended.

    /* ... but it's not ... */
    p {font: 200 2rem/1 "League Spartan","Bahnschrift","Source Sans Pro",sans-serif;}
    p > b { font-weight: 300 }
    p > b > b { font-weight: 400 }
    p > b > b > b { font-weight: 500 }
    p > b > b > b > b { font-weight: 600 }
    p > b > b > b > b > b { font-weight: 700 }
    p > b > b > b > b > b > b, strong { font-weight: 800 }

    Using CSS properties the CSS can become simpler ...

    p {--w:1 }
    p b { font-weight: calc(var(--w) * 200) }

    but the HTML gets even worse:

    <p>G<b style="--w:1">o<b style="--w:2">o<b style="--w:3">o<b style="--w:4">o<b style="--w:5">d</b> Morning!</b></b></b></b></p>

    Cheers.

  6. svgeesus commented on Jan 28, 2020

    @svgeesus
    Collaborator

    Unfortunately neither "bolder" nor "lighter" move to the next weight variation within a variable font, but act binary as "bold" or "un-bold" aka "normal". That was fine when most ordinary fonts typically featured a binary state for normal/bold as well.

    And tat is the crux of the issue. bolder and lighter date from a time when:

    • CSS was vastly simpler and less used than now
    • there were no WebFonts
    • there were no variable fonts
    • CSS was seen as a set of "hints" to affect presentation, not a completer visual design system

    Looking at the definition (bolder means _bolder, if available, or the same weight, but at least not lighter _) which is as close to meaningless as can be while still being somewhat testable, I would class the bolder and lighter keywords as legacy compat features only.

    Achieving the desired effect using calc, though, seems like a much better approach.

  7. Crissov commented on Jan 28, 2020

    @Crissov
    Contributor

    With few additional tools, i. e. functions, authors could build individual stepping patterns.

    :root {
      --font-weights: 100, 200, 300, 400, 500, 600, 700, 800, 900;
      --i: 4;
    } 
    foo, bar {
      font-weight: index(var(--i), var(--font-weights));
    } 
    foo {
      --i: max(var(--i) + 1, 9);
    } 
    bar {
      --i: min(var(--i) - 1, 1);
    } 
  8. WebMechanic commented on Jan 28, 2020

    @WebMechanic

    [EDIT: my memory failed me miserably onthis. See comments below about the confusion.]
    @Crissov ignoring the non-existing index() function, I had mixed results with setting a var that refers to itself (--i: max(var(--i) + 1, 9);), esp. in Edge/18 - although that'll be history soon.
    I just noticed min(()/max() are now supported in Blink !! 😎🥰

    Sidenote> increments/decrements could/should work like counters, if we could store their value in a variable at runtime...

  9. tabatkins commented on Jan 28, 2020

    @tabatkins
    Member

    I had mixed results with setting a var that refers to itself

    Because that's not allowed and immediately causes the variable to be invalid-at-computed-value-time ^_^.

  10. svgeesus commented on Jan 28, 2020

    @svgeesus
    Collaborator

    I had mixed results with setting a var that refers to itself

    Hopefully you had consistent reults i.e. that didn't work anywhere. CSS is declarative. All uses of a variable have the same value. There is no order of execution. It is no an imperative programming language.

    That and other reasons (inheritance, initial value) is why 'CSS Variables' is now termed 'Custom Properties'.

  11. WebMechanic commented on Jan 28, 2020

    @WebMechanic

    You're right of course! 🤐
    I dug up the test file I confused this with.

    --val: calc(2 + 2); 
    --foo: calc(2 * var(--val)); /* Edge chokes */

    The snippet's from a comment in an experiment I did ages ago toying with hsl() utilizing tons of calc() and var()s en masse to build basic color schemes and ramps.
    Edge choked if calc() contained a var() that itself had calc() as it's only value. Very occult behaviour.

    I can't reproduce this today as the above code for --foo works fine in Edge/18, and given the file's age it must have been an earlier release.

  12. litherum commented on Jan 29, 2020

    @litherum
    Contributor

    How about adding two new functions with the same names as the existing keywords?

    font-weight: bolder(250); /* add 250 to the weight */
    font-weight: lighter(250); /* subtract 250 from the weight */
    font-weight: bolder; /* use the legacy behavior */

    This doesn’t require a CSS-wide change.

  13. Crissov commented on Jan 29, 2020

    @Crissov
    Contributor

    Yes, I should have checked my made-up code better. (In actual production code, Iʼve only used very simple vars yet.) I could have tried solving it with counters or the current font weight or the actual width of 1ch instead, but I hope the general idea came across.

    As for dedicated functions suggested by @litherum, why not more generic ones? For instance: increase(<amount-to-add-to-inherited-value>, <clamp-fallback>) and decrease(<amount-to-substract-from-inherited-value>, <clamp-fallback>). The fallback value would be used if the increment or decrement operation resulted in a value outside the valid range or used incompatible units. These functions would need to work anywhere calc() does and use the appropriate (partial) inherited single value, e. g. in background-position: decrease(10px, center) increase(10%, 100%);.

  14. WebMechanic commented on Jan 29, 2020

    @WebMechanic

    coming back to @tabatkins earlier remark:

    But grabbing the inherited value of a property via a function or something shouldn't be problematic.

    Since multiple weights are a variable font thing anyways, I'd then suggest to use a property that already officially deals with it, instead of teaching and old dog new tricks.
    With regular var()s that'd be:

    font-variation-settings: "wght" calc( var(--normal) + 250);

    Not sure if this is also animatable (some would certainly want that). I remember a CodePen doing that, but there might've been some JS involved - I don't remember that ;)

    So if there were a "function or something", maybe sth. like this could get us much further:

    font-variation-settings: "wght" calc( current() + 250);
    font-variation-settings: "wght" calc( current(wght) + 42 * 100);

    I have no opinion onits name, but thing is: this is a multi value property like there are many in CSS. The syntax and smartness of this "gimme the current|inherited value" function will be interesting to draft and for implementors to code :)

    Cheers.

  15. litherum commented on Jan 29, 2020

    @litherum
    Contributor

    As for dedicated functions suggested by @litherum, why not more generic ones?

    We already have generic ones. They are calc(), +, and -. The title of this issue is “font-weight: bolder and lighter are counter intuitive.”

    If a generic function is preferred, we should close this issue as “no change” because calc() already exists.

  16. svgeesus commented on Jan 29, 2020

    @svgeesus
    Collaborator

    font-variation-settings: "wght" calc( current() + 250);
    this is a multi value property like there are many in CSS

    Right. In particular, this sets the wght and resets everything else that font-variation-settings might have contained.

  17. Crissov commented on Jan 30, 2020

    @Crissov
    Contributor

    calc() is too generic, though, unless inherited, inherit, parent or something like that would be added as a local math constant (as suggested in the OP), similar to the new global math constants pi and e #4688. I think this recent development could solve the concerns initially raised by @upsuper.

    Dedicated increment and decrement functions would avoid this new concept, but they would be limited to addition and subtraction, respectively, when you sometimes want multiplication or division (e g. in font size steps). In conclusion, they would probably be an inferior solution.

    If a generic function is preferred, we should rename this issue (or create a new one).

  18. WebMechanic commented on Jan 30, 2020

    @WebMechanic

    font-variation-settings: "wght" calc( current() + 250);
    this is a multi value property like there are many in CSS

    Right. In particular, this sets the wght and resets everything else that font-variation-settings might have contained.

    oh, I forgot that part :/ Thanks for the heads up!
    However, this should work though (not tested):

    --mo-variations: "wght" 300, "xhgt" 0;
    font-variation-settings: "wght" calc( current() + 250) , var(--mo-variations);

    [edit typo]

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