Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8313808

Visual artifacts when using position:sticky in a scrollable grid

    XMLWordPrintable

Details

    • web
    • x86_64
    • windows_10

    Description

      ADDITIONAL SYSTEM INFORMATION :
      Windows 11
      Java 11.0.12_7 (JavaFX 11), Java 17.0.5_8 (JavaFX 17, 20)
      JavaFX versions tested: 11.0.2 (Pass), 17.0.8 (Fail), 20.0.2 (Fail)

      A DESCRIPTION OF THE PROBLEM :
      When building a grid that requires scrolling in a WebView, using the "position: sticky" attribute on a large grid can cause redraw problems when scrolling back and forth horizontally.

      While a CSS grid is provided in this example, I first noticed the problem with a table using the same "position: sticky" attribute. This was not a problem in JavaFX 11.0.2 and is not reproducible there, even with the grid case.

      The grid works fine if no columns are marked as sticky.

      REGRESSION : Last worked in version 11

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      * Run the provided code to generate a grid containing 2 sticky columns and 1 sticky header.
      * Maximize the window (often makes the issue more reproducible.)
      * Use the horizontal scroll bar to scroll the content back and forth quickly.


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      * Scrolling is smooth, sticky columns are remaining in place, no visual artifacts.
      ACTUAL -
      * Visual artifacts often will show up when scrolling back to the left.

      ---------- BEGIN SOURCE ----------
      import javafx.application.Application;
      import javafx.scene.web.WebView;
      import javafx.scene.Scene;
      import javafx.scene.layout.StackPane;
      import javafx.stage.Stage;

      public class App extends Application {

          @Override
          public void start(Stage stage) throws Exception{
              WebView wv = new WebView();
              
              // Change boolean to switch between sticky/non-sticky
              String page = generateGrid(200, 100, true);
              
              wv.getEngine().loadContent(page);
              
              var scene = new Scene(new StackPane(wv), 640, 480);
              stage.setScene(scene);
              stage.show();
          }

          public static void main(String[] args) {
              launch();
          }

          public static String generateGrid(int rows, int cols, boolean useSticky) {
           StringBuilder sb = new StringBuilder();
          
           sb.append("<html><head><style type=\"text/css\">");
          
           // Grid template
           sb.append(".test-grid {display: grid; grid-template-columns: repeat(").append(cols).append(", 30px); ");
           sb.append("grid-template-rows: repeat(").append(rows).append(", 30px); ");
           sb.append("width: ").append(cols*30).append("px; background: #fff;}\n");
          
           // Cell Template
           sb.append(".test-cell {border: 1px solid #000; border-radius: 5px;}\n");
          
           // Sticky cells
           if (useSticky) {
           // JavaFX 11 requires "position: -webkit-sticky"
      // sb.append(".sticky-left {left: 0; z-index: 1; position: -webkit-sticky; background: #999;}\n");
      // sb.append(".sticky-left-2 {left: 30px; z-index: 1; position: -webkit-sticky; background: #999;}\n");
      // sb.append(".sticky-top-left {top: 0; left: 0; z-index: 2; position: -webkit-sticky; background: #777;}");
      // sb.append(".sticky-top-left-2 {top: 0; left: 30px; z-index: 2; position: -webkit-sticky; background: #777;}");
      // sb.append(".sticky-top {top: 0; z-index: 1; position: -webkit-sticky; background: #999;}\n");

           // JavaFX 17+
           sb.append(".sticky-left {left: 0; z-index: 1; position: sticky; background: #999;}\n");
           sb.append(".sticky-left-2 {left: 30px; z-index: 1; position: sticky; background: #999;}\n");
           sb.append(".sticky-top-left {top: 0; left: 0; z-index: 2; position: sticky; background: #777;}");
           sb.append(".sticky-top-left-2 {top: 0; left: 30px; z-index: 2; position: sticky; background: #777;}");
           sb.append(".sticky-top {top: 0; z-index: 1; position: sticky; background: #999;}\n");
           }
          
           sb.append("</style></head><body>");
          
           sb.append("<div class=\"test-grid\">\n");
          
           for (int y = 0; y < rows; y++) {
           for (int x = 0; x < cols; x++) {
          
           if (y == 0) {
           if (x == 0)
               sb.append("<div class=\"test-cell sticky-top-left\">");
           else if (x == 1)
               sb.append("<div class=\"test-cell sticky-top-left-2\">");
           else
           sb.append("<div class=\"test-cell sticky-top\">");
           } else if (x == 0) {
           sb.append("<div class=\"test-cell sticky-left\">");
           } else if (x == 1) {
           sb.append("<div class=\"test-cell sticky-left-2\">");
           } else {
           sb.append("<div class=\"test-cell\">");
           }
              sb.append(x%10).append(",").append(y%10);
              sb.append("</div>\n");
           }
           }
          
           sb.append("</div>");
          
           sb.append("</body></html>");
          
           return sb.toString();
          }
      }
      ---------- END SOURCE ----------

      FREQUENCY : always

      Attachments

        Activity

          People

            jbhaskar Jay Bhaskar
            pnarayanaswa Praveen Narayanaswamy
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated: