I have a WWWeb page with stacked <canvas>
elements. The goal is to draw something persistent in the lower canvas and draw, clear, and redraw, repeatedly, in the upper canvas. According to w3.org and this StackOverflow article (How do I make a transparent canvas in html5?), canvas elements are, by default, transparent. What I am seeing is that not only are they not transparent, but that overlaying via z-index
is not working. Here's a "vanilla" version of the page's code (complete and used to generate the images):
<html>
<head>
<title>Canvas Stack</title>
<script>
function doStuff() {
drawStuff(document.getElementById("lowerCanvas"), 0, 1);
drawStuff(document.getElementById("upperCanvas"), 1, 0);
}
function drawStuff(cvs, p0X, p1X) {
var ctx = cvs.getContext("2d");
ctx.clearRect(0, 0, cvs.width, cvs.height);
ctx.strokeStyle = cvs.style.color;
ctx.beginPath();
ctx.moveTo(p0X * cvs.width, 0);
ctx.lineTo(p1X * cvs.width, cvs.height);
ctx.stroke();
}
</script>
</head>
<body onload="doStuff();" style="border:solid;">
<canvas id="lowerCanvas" style="color:red;height:200px;left:0;position:inherit;top:0;width:300px;z-index:0;" />
<canvas id="upperCanvas" style="color:blue;height:200px;left:0;position:inherit;top:0;width:300px;z-index:1;" />
</body>
</html>
and here's the result:
If I swap the order of the canvas elements
<canvas id="upperCanvas" style="color:blue;height:200px;left:0;position:inherit;top:0;width:300px;z-index:1;" />
<canvas id="lowerCanvas" style="color:red;height:200px;left:0;position:inherit;top:0;width:300px;z-index:0;" />
the result is
It seems as if the z-index
has been ignored and that the order of declaration has primacy.
What I want is
(synthetic image)
The behavior is identical in Chrome, Edge, Firefox, and Internet Explorer under Windows 10. That makes me confident that I'm just missing some detail rather than experiencing an anomaly. However, I'm getting a flattened forehead from whacking my head against a wall and would really appreciate some guidance, here.
Thank you, all!
Some notes (maybe irrelevant; maybe not):
style="position:absolute;
... (without the left
and top
entries) seems to do the same thing as style="left:0;position:absolute;top:0;
...style="position:inherit;
... is probably necessary if the canvas is to reside within a table's <td>
and that <td>
is other than the first one in a <tr>
. <html>
<head>
<title>Canvas Stack</title>
<script>
function doStuff() {
drawStuff(document.getElementById("lowerCanvas"), 0, 1);
drawStuff(document.getElementById("upperCanvas"), 1, 0);
}
function drawStuff(cvs, p0X, p1X) {
var ctx = cvs.getContext("2d");
ctx.clearRect(0, 0, cvs.width, cvs.height);
ctx.strokeStyle = cvs.style.color;
ctx.beginPath();
ctx.moveTo(p0X * cvs.width, 0);
ctx.lineTo(p1X * cvs.width, cvs.height);
ctx.stroke();
}
</script>
</head>
<body onload="doStuff();" style="border:solid;">
<div style="position:relative;min-height:200px">
<canvas id="lowerCanvas" style="color:red;height:200px;left:0;position:absolute;top:0;width:300px;z-index:0;"></canvas>
<canvas id="upperCanvas" style="color:blue;height:200px;left:0;position:absolute;top:0;width:300px;z-index:1;"></canvas>
</body>
</html>
You need to close your canvas elements explicitly. Simply close it with:
<canvas id="lowerCanvas" style="color:red;height:200px;left:0;position:inherit;top:0;width:300px;z-index:0;"></canvas>
instead of the embedded close "/>"
I also enclosed them in a div and used position:absolute so that they actually overlap...