I have an HTML canvas on iOS/iPadOS devices shows a small gap between the canvas and the bottom border. I've fixed this problem in the past with a div by adding display: block; but that does not work on the canvas. Anyone have any idea how to remove this gap? I know that I can make the background color of the canvas to be the same as the border color but I am hoping to find a solution that fixes the actual problem.
Attached is a screen grab of the issue.
I am running iOS/iPadOS 26.0.1 and have seen the issue on iOS/iPadOS 18.6 as well.
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
// Set canvas dimensions
canvas.width = 300;
canvas.height = 400;
// Draw a rectangle
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas.width, canvas.height);
canvas#myCanvas
{
border: 4px solid black;
display: block; /* not working like on div for iOS devices */
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<title>Canvas Test</title>
</head>
<body>
<h1>Canvas Test</h1>
<canvas id="myCanvas"></canvas>
</body>
</html>
This looks like an antialiasing rounding issue, caused by the default user-agent rules set on the <h1> which will set its margin-block-[start|end] to 0.67em, which doesn't map to an integral pixel value. They seem to fail to round the box position of the <canvas>'s layer in this case.
Please report it, it seems it still affects Safari Technology Preview, so they might not know about this.
As a workaround before they fix the issue, you could obviously override that user-agent rule so that the layout doesn't have to deal with fraction of pixels:
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
// Set canvas dimensions
canvas.width = 300;
// I reduced the size so it fits the snippet, but the bug still occurs without the "fix"
canvas.height = 100;
// Draw a rectangle
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas.width, canvas.height);
canvas#myCanvas
{
border: 4px solid black;
display: block; /* not working like on div for iOS devices */
}
h1 {
margin-block-start: 21px;
margin-block-end: 21px;
}
<h1>Canvas Test</h1>
<canvas id="myCanvas"></canvas>
On my desktop Safari 26.0.1, this snippet without the fix looks like
With the fix, it looks like
But every element before your <canvas> that has it box's height computed to a fraction of pixel would need to be handled, and it doesn't seem very practical to change all the elements styles this way.
I couldn't find a proper CSS-only workaround that would ensure the canvas is back on the pixel grid, so instead you might want to use JS to set the <canvas> margin to manually round its position:
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
// Set canvas dimensions
canvas.width = 300;
// I reduced the size so it fits the snippet, but the bug still occurs without the "fix"
canvas.height = 100;
// Draw a rectangle
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Workaround Safari bug with floating point margins
canvas.style.marginTop = `${Math.floor(canvas.getBoundingClientRect().top) - canvas.getBoundingClientRect().top}px`;
canvas#myCanvas
{
border: 4px solid black;
display: block; /* not working like on div for iOS devices */
transform: translate(0px 0px);
}
<h1>Canvas Test</h1>
<canvas id="myCanvas"></canvas>
But this also assumes that the content before the <canvas> is relatively static.