Eliminate Ghost Margin Below HTML5 Canvas Element

Eliminate ghost margin below HTML5 canvas element?

Add vertical-align: bottom to it.

This is caused by the canvas being an inline element. As such, it is effectively considered a character. As such, it must follow the baseline rule, which is to leave a little space below the line in case of characters such as gjpqy which drop below the baseline. By setting the vertical-align to bottom, you are actually aligning the canvas to the bottom of the drop-down letters. So long as the canvas itself is taller than the line-height, you will have no problems. Should the canvas be shorter than the line-height, you will start seeing "ghost margins" above the canvas as it reserves room for bdfhklt, the taller letters. This can be fixed by adding a line-height: 1px rule.

Canvas has white space at the bottom and scrolls too far

Make the canvas a block element or use vertical-align:top. By default, canvas is an inline element and it will behave similary to an img; thus you will have the whitespace issue due to vertical alignement (Image inside div has extra space below the image)

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillStyle = '#00aa00'
ctx.fillRect(0, 0, c.width, c.height);
ctx.fillStyle = '#fff'
ctx.font='12pt A'
ctx.fillText("scroll here to see red from screen div", 30, 50);
.screen {
background: red;
height: 100px;
width: 300px;
overflow: auto;
border-radius: 20px;
}
canvas {
display:block;
}

::-webkit-scrollbar {
width: 0px;
height: 0px;
}
<div class="screen">
<canvas id="myCanvas" width="300" height="120">
</canvas>
</div>

Removing space below canvas when within li

Adding vertical-align:top to the canvas will fix it.

jsFiddle example

How can I stop HTML5 Canvas Ghosting?

Try having a list of positions, this won't leave a ghost trail!

my code:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var Positions = [];
var maxlength = 20;

canvas.style.cursor = 'none'; // remove regular cursor inside canvas

var V2 = function(x, y){this.x = x; this.y = y;};

function getMousePos(canvas, e) {
// ctx.clearRect(0, 0, canvas.width, canvas.height);
var rect = canvas.getBoundingClientRect();
return {
x: e.clientX - rect.left,
y: e.clientY - rect.top
};
}

function fadeCanvas() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for(var e = 0; e != Positions.length; e++)
{
ctx.fillStyle = ctx.fillStyle = "rgba(0, 0, 0, " + 1 / e + ")";
ctx.fillRect(Positions[e].x, Positions[e].y, 8, 8);

}
if(Positions.length > 1)
Positions.pop()

//ctx.save();
//ctx.globalAlpha = 0.5; // the opacity (i.e. fade) being applied to the canvas on each function re-run
//ctx.fillStyle = "#fff";
//ctx.fillRect(0, 0, canvas.width, canvas.height); // area being faded (whole canvas)
//ctx.restore();
requestAnimationFrame(fadeCanvas); // animate at 60 fps
}
fadeCanvas();

function draw(e) {
var pos = getMousePos(canvas, e);
Positions.unshift(new V2(pos.x, pos.y));
if(Positions.length > maxlength)
Positions.pop()
//ctx.fillStyle = "black";
//ctx.fillRect(pos.x, pos.y, 8, 8); // the new cursor
}
addEventListener('mousemove', draw, false);

JSFiddle: https://jsfiddle.net/L6j71crw/9/

Edit: made the cursor constant.

Get rid of padding/margin around canvas element?

As you've correctly noted, browsers implement default styles for various HTML elements (and they're not standardised, so every browser implements slightly different defaults). For your purposes, given your posted HTML, you'd need something like the following:

html, body, div, canvas {
margin: 0;
padding: 0;
}

This does, of course, over-simplify things and it might be worth setting font-size and default color and background-color properties too (among many, many others).

References:

  • CSS Reset Reloaded, by Eric Meyer.
  • YUI reset.
  • And there are many others, though I really can only think of those two, the css-reset might be of use to you, though.

Unexpected HTML5 drag & drop ghost image behaviour

This might be just a bug in Chrome (seems to work in Firefox, once you actually .setData())

If you're just looking for an easy, albeit somewhat nasty work-around: .setDragImage() explicitly, based on the canvas.

function dragstart(e) {
var di = new Image();
di.src = this.toDataURL("image/png");
e.dataTransfer.setDragImage(di, 10, 10);
// Run in firefox
e.dataTransfer.setData("text/plain", this.id);
}

Fiddle (you might want to fiddle with the position of the image a bit).

Style drag ghost element

You can do this by implementing dragging of the element yourself in JavaScript. That way, you can apply a CSS class to the element while it is being dragged, which styles it in any way you wish.

const d = 'dragging';

const container = document.getElementById('container');
const el = document.getElementById('drag');

var cOffX = 0;
var cOffY = 0;

el.addEventListener('mousedown', dragStart);

function dragStart(e) {
e = e || window.event;
e.preventDefault();

cOffX = e.clientX - el.offsetLeft;
cOffY = e.clientY - el.offsetTop;

document.addEventListener('mousemove', dragMove);
document.addEventListener('mouseup', dragEnd);

el.classList.add(d);
container.style.cursor = 'move';
};

function dragMove(e) {
e = e || window.event;
e.preventDefault();

el.style.top = (e.clientY - cOffY).toString() + 'px';
el.style.left = (e.clientX - cOffX).toString() + 'px';
};

function dragEnd(e) {
e = e || window.event;
e.preventDefault();

document.removeEventListener('mousemove', dragMove);
document.removeEventListener('mouseup', dragEnd);

el.classList.remove(d);
container.style.cursor = null;
};
#container {
width: 100vw;
height: 100vh;
margin: 0;
padding: 0;
}

#drag {
position: absolute;
height: 100px;
width: 100px;
background-color: lime;
border-radius: 0;
transition: background-color 0.25s, border-radius 0.25s;
cursor: move;
}

#drag.dragging {
background-color: navy;
border-radius: 50%;
}
<div id="container">
<div id="drag"></div>
</div>

setDragImage not removing ghost image on Chrome?

The problem is coming from the image. If you try dragging the red border, it will work correctly. The problem will appear only when the drag begins on the image inside the draggable element. Maybe Chrome has some special treatment for images; I don't know.

You can mitigate this by disabling pointer events on the image:

.item img {
pointer-events: none;
}

Here is a working example: