Details
-
Bug
-
Resolution: Unresolved
-
P3
-
jfx11, jfx17, jfx20, jfx21
-
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
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