<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p>Well, it is coming as a surprise to many. With the fix for the
      CSS caching bug since JavaFX 21, this "normal" behavior is
      becoming much more obvious.</p>
    <p>Let me repeat one more time:</p>
    <p>If I have a Label, and I manually set its text fill with a setter
      to YELLOW. In JavaFX 17, when I now add a stylesheet that is empty
      aside from `-fx-base: WHITE`, the label's text fill stays YELLOW. 
      <br>
    </p>
    <p>Now do this in JavaFX 21.  As soon as you add the stylesheet with
      `-fx-base: WHITE` in it, the set value to YELLOW is overridden,
      even though technically this value for -fx-text-fill is defined by
      Modena (which should not be overriding set values).  Nowhere did
      we **actualy** override -fx-text-fill, yet the CSS subsystem now
      sees **all** values defined by Modena that are somehow linked to
      -fx-base as defined directly by the developer...</p>
    <p>The reason this didn't happen in JavaFX prior to 21 is because
      there was a bug where a CSS value was not fully calculated if the
      property it encountered was overridden via a set value. That was a
      bug however as cache entries are shared amongst similar styled
      nodes, and so not calculating it fully could have effects on other
      nodes that shared that cache entry but did NOT have a property set
      directly.  Now that this bug is fixed, this problem is odd
      behavior is popping up where simply specifying -fx-base in an
      empty stylesheet is somehow overriding a programmatically set text
      fill.  Users are confused by this, as nowhere in their stylesheet
      do they themselves override text fill.</p>
    <p>This entire mechanism is not specified by CSS, but is unique to
      FX.  The most similar mechanism in CSS (see Michael's answer) says
      the priority of a style should not be changed when it is using a
      reference.<br>
    </p>
    <p>--John<br>
    </p>
    On 09/07/2024 17:43, Andy Goryachev wrote:<br>
    <blockquote type="cite"
cite="mid:BL3PR10MB61857B8E5D1F9C55118C2C40E5DB2@BL3PR10MB6185.namprd10.prod.outlook.com">
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <meta name="Generator" content="Microsoft Word 15 (filtered
        medium)">
      <style>@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}@font-face
        {font-family:"Yu Gothic";
        panose-1:2 11 4 0 0 0 0 0 0 0;}@font-face
        {font-family:Aptos;
        panose-1:2 11 0 4 2 2 2 2 2 4;}@font-face
        {font-family:"Iosevka Fixed SS16";
        panose-1:2 0 5 9 3 0 0 0 0 4;}@font-face
        {font-family:"Times New Roman \(Body CS\)";
        panose-1:2 11 6 4 2 2 2 2 2 4;}@font-face
        {font-family:Consolas;
        panose-1:2 11 6 9 2 2 4 3 2 4;}@font-face
        {font-family:"\@Yu Gothic";
        panose-1:2 11 4 0 0 0 0 0 0 0;}p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        font-size:10.0pt;
        font-family:"Aptos",sans-serif;}a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}span.EmailStyle21
        {mso-style-type:personal-reply;
        font-family:"Iosevka Fixed SS16";
        color:windowtext;}.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;
        mso-ligatures:none;}div.WordSection1
        {page:WordSection1;}</style>
      <div class="WordSection1">
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">> all styles used in Modena that rely on
            -fx-base directly or indirectly suddenly have a higher
            priority<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">I think it works as designed (and as expected).<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">-andy<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <div id="mail-editor-reference-message-container">
          <div>
            <div style="border:none;border-top:solid #B5C4DF
              1.0pt;padding:3.0pt 0in 0in 0in">
              <p class="MsoNormal" style="margin-bottom:12.0pt"><b><span
                    style="font-size:12.0pt;color:black">From:
                  </span></b><span style="font-size:12.0pt;color:black">John
                  Hendrikx <a class="moz-txt-link-rfc2396E" href="mailto:john.hendrikx@gmail.com"><john.hendrikx@gmail.com></a><br>
                  <b>Date: </b>Tuesday, July 9, 2024 at 08:25<br>
                  <b>To: </b>Andy Goryachev
                  <a class="moz-txt-link-rfc2396E" href="mailto:andy.goryachev@oracle.com"><andy.goryachev@oracle.com></a>, openjfx-dev
                  <a class="moz-txt-link-rfc2396E" href="mailto:openjfx-dev@openjdk.org"><openjfx-dev@openjdk.org></a><br>
                  <b>Subject: </b>[External] : Re: CSS Lookups and
                  their origins (possible regression)<o:p></o:p></span></p>
            </div>
            <p>It's not that you can't use -fx-base, but that as it is
              currently that all styles used in Modena that rely on
              -fx-base directly or indirectly suddenly have a higher
              priority (above setters) even though you didn't
              specifically specify them in your own stylesheet.  All
              such styles are being elevated from USER_AGENT to AUTHOR
              level (which is above USER level which is used for
              setters).<o:p></o:p></p>
            <p>--John<o:p></o:p></p>
            <div>
              <p class="MsoNormal"><span style="font-size:12.0pt">On
                  09/07/2024 17:03, Andy Goryachev wrote:<o:p></o:p></span></p>
            </div>
            <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
              <div>
                <p class="MsoNormal">I've used this feature in the past
                  to change the colors in all the controls, so to me
                  this is the expected behavior.<o:p></o:p></p>
                <p class="MsoNormal"> <o:p></o:p></p>
                <p class="MsoNormal">So in your case (if I got it
                  right), you need to set the direct style on the label
                  (.setStyle("-fx-text-fill:yellow")) instead of setting
                  the text fill programmatically.  Right?<o:p></o:p></p>
                <p class="MsoNormal"> <o:p></o:p></p>
                <p class="MsoNormal">-andy<o:p></o:p></p>
                <p class="MsoNormal"> <o:p></o:p></p>
                <p class="MsoNormal"> <o:p></o:p></p>
                <p class="MsoNormal"> <o:p></o:p></p>
                <p class="MsoNormal"> <o:p></o:p></p>
                <div id="mail-editor-reference-message-container">
                  <div>
                    <div style="border:none;border-top:solid #B5C4DF
                      1.0pt;padding:3.0pt 0in 0in 0in">
                      <p class="MsoNormal" style="margin-bottom:12.0pt"><b><span
                            style="font-size:12.0pt;color:black">From:
                          </span></b><span
                          style="font-size:12.0pt;color:black">openjfx-dev
                          <a href="mailto:openjfx-dev-retn@openjdk.org"
                            moz-do-not-send="true">
                            <openjfx-dev-retn@openjdk.org></a> on
                          behalf of John Hendrikx <a
                            href="mailto:john.hendrikx@gmail.com"
                            moz-do-not-send="true">
                            <john.hendrikx@gmail.com></a><br>
                          <b>Date: </b>Monday, July 8, 2024 at 17:11<br>
                          <b>To: </b>openjfx-dev <a
                            href="mailto:openjfx-dev@openjdk.org"
                            moz-do-not-send="true"><openjfx-dev@openjdk.org></a><br>
                          <b>Subject: </b>Re: CSS Lookups and their
                          origins (possible regression)</span><o:p></o:p></p>
                    </div>
                    <p>I realized I worded the TLDR poorly.<o:p></o:p></p>
                    <p>Let me try again:<o:p></o:p></p>
                    <p>TLDR; should styles which use references (like
                      -fx-base used in Modena) become AUTHOR level
                      styles if -fx-base is specified in an AUTHOR
                      stylesheet?  The act of simply specifying -fx-base
                      in your own AUTHOR stylesheet elevates hundreds of
                      styles from Modena to AUTHOR level, as if you
                      specified them directly...<o:p></o:p></p>
                    <p>--John<o:p></o:p></p>
                    <div>
                      <p class="MsoNormal"><span
                          style="font-size:12.0pt">On 09/07/2024 02:07,
                          John Hendrikx wrote:</span><o:p></o:p></p>
                    </div>
                    <blockquote
                      style="margin-top:5.0pt;margin-bottom:5.0pt">
                      <p>Hi List,<o:p></o:p></p>
                      <p>TLDR; should a CSS reference like -fx-base
                        convert all styles that use this value (or
                        derive from it) become AUTHOR level styles
                        (higher priority than setters) ?<o:p></o:p></p>
                      <p>Long version:<o:p></o:p></p>
                      <p>In JavaFX 21, I did a fix (see #1072) to solve
                        a problem where a CSS value could be reset on an
                        unrelated control.<o:p></o:p></p>
                      <p>This happened when the CSS engine encountered a
                        stylable that is overridden by the user (with a
                        setter), and decided NOT to proceed with the
                        full CSS value calculation (as it could not
                        override the user setting if that CSS value had
                        lower priority).  However, not proceeding with
                        the calculation meant that a "SKIP" was stored
                        in a shared cache which was incorrect.  This is
                        because when this "SKIP" is later encountered
                        for an unrelated control (the cache entries are
                        shared for controls with the same styles at the
                        same level), they could get their values reset
                        because they were assumed to be unstyled.<o:p></o:p></p>
                      <p>However, this fix has exposed what seems to be
                        a deeper bug or perhaps an unfortunate default:<o:p></o:p></p>
                      <p>JavaFX has a special feature where you can
                        refer to certain other styles by using a
                        reference (which is resolved, recursively, to a
                        final value).  This does not seem to be a CSS
                        standard, but is a feature only FX has.<o:p></o:p></p>
                      <p>It works by saying something like:<o:p></o:p></p>
                      <p>    -fx-base: RED;<o:p></o:p></p>
                      <p>And then using it like this:<o:p></o:p></p>
                      <p>    -fx-text-fill: -fx-base;<o:p></o:p></p>
                      <p>This feature works accross stylesheets of
                        different origins, so an AUTHOR stylesheet can
                        specify -fx-base, and when a USER_AGENT refers
                        to -fx-base, the value comes from the AUTHOR
                        stylesheet.<o:p></o:p></p>
                      <p>JavaFX then changes the origin of the style to
                        the highest priority encountered while resolving
                        the reference.  This means that Modena can
                        specify "-fx-text-fill: -fx-base", and when
                        "-fx-base" is then part of the AUTHOR style
                        sheet, that ALL Modena styles that use -fx-base
                        will be considered AUTHOR level styles, as per
                        this comment:<o:p></o:p></p>
                      <div>
                        <div>
                          <p style="margin:0in;background:white"><span
                              style="font-size:11.0pt;font-family:Consolas;color:#3F7F5F">//
                              The origin of this parsed value is the
                              greatest of</span><o:p></o:p></p>
                          <p style="margin:0in;background:white"><span
                              style="font-size:11.0pt;font-family:Consolas;color:#3F7F5F">//
                              any of the resolved reference. If a
                              resolved reference</span><o:p></o:p></p>
                          <p style="margin:0in;background:white"><span
                              style="font-size:11.0pt;font-family:Consolas;color:#3F7F5F">//
                              comes from an inline style, for example,
                              then the value</span><o:p></o:p></p>
                          <p style="margin:0in;background:white"><span
                              style="font-size:11.0pt;font-family:Consolas;color:#3F7F5F">//
                              calculated from the resolved lookup should
                              have inline</span><o:p></o:p></p>
                          <p style="margin:0in;background:white"><span
                              style="font-size:11.0pt;font-family:Consolas;color:#3F7F5F">//
                              as its origin. Otherwise, an inline style
                              could be</span><o:p></o:p></p>
                          <p style="margin:0in;background:white"><span
                              style="font-size:11.0pt;font-family:Consolas;color:#3F7F5F">//
                              stored in shared cache.</span><o:p></o:p></p>
                        </div>
                      </div>
                      <p>I feel that this is a really unfortunate
                        choice.  The style after all was specified by
                        Modena, only its value came from another (higher
                        priority) style sheet.  I think a more logical
                        choice would have been to not change the
                        priority at all, unless a "-fx-text-fill" is
                        explicitly made part of the AUTHOR stylesheet.<o:p></o:p></p>
                      <p>A consequence of this (and which is much more
                        visible after the fix) is that creating a Label
                        with a setTextFill(Color.YELLOW) in its
                        constructor will only result in a yellow text
                        fill if the AUTHOR stylesheet did not override
                        any of the Modena colors involved in calculating
                        the Modena -fx-text-fill default.  Overriding
                        -fx-base in any way will result in the text fill
                        of the label to be overridden (as the reference
                        came from an AUTHOR stylesheet, which trumps a
                        setter which is of a lower style origin).<o:p></o:p></p>
                      <p>The comment also alludes to a potential
                        problem.  If an inline style would specify
                        "-fx-base", but would be treated as if it came
                        from Modena (USER_AGENT level), then this value
                        could get stored in the cache as everything
                        except INLINE styles can be cached.  However, I
                        feel that the changing of style origin level was
                        then probably done to solve a CACHING problem,
                        instead of what made logical sense for users. 
                        If we agree that a resolved reference should not
                        change the style origin level, then this would
                        need to be addressed, by perhaps marking such a
                        calculated value as uncacheable, instead of
                        overloading the meaning of style origin.<o:p></o:p></p>
                      <p>I'd like to hear your thoughts, and also how to
                        proceed.  JavaFX versions before 21 seemingly
                        allowed overriding reference without much
                        consequence because if the user overrode the
                        value manually, the cache entry would be set to
                        "SKIP".  Now that this is no longer the case,
                        JavaFX more aggressively overrides user set
                        values if they happen to use a referenced
                        value.  See code below.<o:p></o:p></p>
                      <p>--John<o:p></o:p></p>
                      <div>
                        <div>
                          <p style="margin:0in;background:white"><span
                              style="font-size:11.0pt;font-family:Consolas;color:black">.root
                              {</span><o:p></o:p></p>
                          <p style="margin:0in;background:white"><span
                              style="font-size:11.0pt;font-family:Consolas;color:black">-fx-base:
                              #ff0000;</span><o:p></o:p></p>
                          <p style="margin:0in;background:white"><span
                              style="font-size:11.0pt;font-family:Consolas;color:black">}</span><o:p></o:p></p>
                          <div>
                            <div>
                              <p style="margin:0in;background:white"><b><span
style="font-size:11.0pt;font-family:Consolas;color:#0000A0">package</span></b><span
style="font-size:11.0pt;font-family:Consolas;color:black"> app;</span><o:p></o:p></p>
                              <p style="margin:0in;background:white"><b><span
style="font-size:11.0pt;font-family:Consolas;color:#0000A0">import</span></b><span
style="font-size:11.0pt;font-family:Consolas;color:black">
                                  javafx.application.Application;</span><o:p></o:p></p>
                              <p style="margin:0in;background:white"><b><span
style="font-size:11.0pt;font-family:Consolas;color:#0000A0">import</span></b><span
style="font-size:11.0pt;font-family:Consolas;color:black">
                                  javafx.scene.Scene;</span><o:p></o:p></p>
                              <p style="margin:0in;background:white"><b><span
style="font-size:11.0pt;font-family:Consolas;color:#0000A0">import</span></b><span
style="font-size:11.0pt;font-family:Consolas;color:black">
                                  javafx.scene.control.Label;</span><o:p></o:p></p>
                              <p style="margin:0in;background:white"><b><span
style="font-size:11.0pt;font-family:Consolas;color:#0000A0">import</span></b><span
style="font-size:11.0pt;font-family:Consolas;color:black">
                                  javafx.scene.paint.Color;</span><o:p></o:p></p>
                              <p style="margin:0in;background:white"><b><span
style="font-size:11.0pt;font-family:Consolas;color:#0000A0">import</span></b><span
style="font-size:11.0pt;font-family:Consolas;color:black">
                                  javafx.stage.Stage;</span><o:p></o:p></p>
                              <p style="margin:0in;background:white"><b><span
style="font-size:11.0pt;font-family:Consolas;color:#0000A0">public</span></b><span
style="font-size:11.0pt;font-family:Consolas;color:black">
                                </span><b><span
                                    style="font-size:11.0pt;font-family:Consolas;color:#0000A0">class</span></b><span
style="font-size:11.0pt;font-family:Consolas;color:black"> TestApp
                                </span><b><span
                                    style="font-size:11.0pt;font-family:Consolas;color:#0000A0">extends</span></b><span
style="font-size:11.0pt;font-family:Consolas;color:black"> Application {</span><o:p></o:p></p>
                              <p style="margin:0in;background:white"><b><span
style="font-size:11.0pt;font-family:Consolas;color:#0000A0">public</span></b><span
style="font-size:11.0pt;font-family:Consolas;color:black">
                                </span><b><span
                                    style="font-size:11.0pt;font-family:Consolas;color:#0000A0">static</span></b><span
style="font-size:11.0pt;font-family:Consolas;color:black">
                                </span><b><span
                                    style="font-size:11.0pt;font-family:Consolas;color:#0000A0">void</span></b><span
style="font-size:11.0pt;font-family:Consolas;color:black"> main(String[]
                                  args) {</span><o:p></o:p></p>
                              <p style="margin:0in;background:white"><i><span
style="font-size:11.0pt;font-family:Consolas;color:black">launch</span></i><span
style="font-size:11.0pt;font-family:Consolas;color:black">(args);</span><o:p></o:p></p>
                              <p style="margin:0in;background:white"><span
style="font-size:11.0pt;font-family:Consolas;color:black">}</span><o:p></o:p></p>
                              <p style="margin:0in;background:white"><span
style="font-size:11.0pt;font-family:Consolas;color:#646464">@Override</span><o:p></o:p></p>
                              <p style="margin:0in;background:white"><b><span
style="font-size:11.0pt;font-family:Consolas;color:#0000A0">public</span></b><span
style="font-size:11.0pt;font-family:Consolas;color:black">
                                </span><b><span
                                    style="font-size:11.0pt;font-family:Consolas;color:#0000A0">void</span></b><span
style="font-size:11.0pt;font-family:Consolas;color:black"> start(Stage
                                  primaryStage) {</span><o:p></o:p></p>
                              <p style="margin:0in;background:white"><span
style="font-size:11.0pt;font-family:Consolas;color:black">Scene scene =
                                </span><b><span
                                    style="font-size:11.0pt;font-family:Consolas;color:#0000A0">new</span></b><span
style="font-size:11.0pt;font-family:Consolas;color:black"> Scene(</span><b><span
style="font-size:11.0pt;font-family:Consolas;color:#0000A0">new</span></b><span
style="font-size:11.0pt;font-family:Consolas;color:black"> MyLabel());</span><o:p></o:p></p>
                              <p style="margin:0in;background:white"><span
style="font-size:11.0pt;font-family:Consolas;color:#3F7F5F">// See the
                                  difference with/without -fx-base in
                                  the
                                  <u>stylesheet</u></span><o:p></o:p></p>
                              <p style="margin:0in;background:white"><span
style="font-size:11.0pt;font-family:Consolas;color:black">scene.getStylesheets().add(TestApp.</span><b><span
style="font-size:11.0pt;font-family:Consolas;color:#0000A0">class</span></b><span
style="font-size:11.0pt;font-family:Consolas;color:black">.getResource(</span><span
style="font-size:11.0pt;font-family:Consolas;color:#2A00FF">"/style.css"</span><span
style="font-size:11.0pt;font-family:Consolas;color:black">).toExternalForm());</span><o:p></o:p></p>
                              <p style="margin:0in;background:white"><span
style="font-size:11.0pt;font-family:Consolas;color:black">primaryStage.setScene(scene);</span><o:p></o:p></p>
                              <p style="margin:0in;background:white"><span
style="font-size:11.0pt;font-family:Consolas;color:black">primaryStage.show();</span><o:p></o:p></p>
                              <p style="margin:0in;background:white"><span
style="font-size:11.0pt;font-family:Consolas;color:black">}</span><o:p></o:p></p>
                              <p style="margin:0in;background:white"><span
style="font-size:11.0pt;font-family:Consolas;color:black">}</span><o:p></o:p></p>
                              <p style="margin:0in;background:white"><b><span
style="font-size:11.0pt;font-family:Consolas;color:#0000A0">class</span></b><span
style="font-size:11.0pt;font-family:Consolas;color:black"> MyLabel
                                </span><b><span
                                    style="font-size:11.0pt;font-family:Consolas;color:#0000A0">extends</span></b><span
style="font-size:11.0pt;font-family:Consolas;color:black"> Label {</span><o:p></o:p></p>
                              <p style="margin:0in;background:white"><b><span
style="font-size:11.0pt;font-family:Consolas;color:#0000A0">public</span></b><span
style="font-size:11.0pt;font-family:Consolas;color:black"> MyLabel() {</span><o:p></o:p></p>
                              <p style="margin:0in;background:white"><span
style="font-size:11.0pt;font-family:Consolas;color:black">setTextFill(Color.</span><span
style="font-size:11.0pt;font-family:Consolas;color:#0000C0">YELLOW</span><span
style="font-size:11.0pt;font-family:Consolas;color:black">);</span><o:p></o:p></p>
                              <p style="margin:0in;background:white"><span
style="font-size:11.0pt;font-family:Consolas;color:black">setText(</span><span
style="font-size:11.0pt;font-family:Consolas;color:#2A00FF">"Hello
                                  world"</span><span
                                  style="font-size:11.0pt;font-family:Consolas;color:black">);</span><o:p></o:p></p>
                              <p style="margin:0in;background:white"><span
style="font-size:11.0pt;font-family:Consolas;color:black">}</span><o:p></o:p></p>
                              <p style="margin:0in;background:white"><span
style="font-size:11.0pt;font-family:Consolas;color:black">}</span><o:p></o:p></p>
                            </div>
                          </div>
                        </div>
                      </div>
                      <p> <o:p></o:p></p>
                    </blockquote>
                  </div>
                </div>
              </div>
            </blockquote>
          </div>
        </div>
      </div>
    </blockquote>
  </body>
</html>