Действительно, алгоритмы кажутся разными.
Не совсем уверен, почему, но я бы сказал, что CSS не рассматривает rgba(0,0,0,0)
как прозрачный черный пиксель , как это делает холст, а вместо этого просто как прозрачный .
2D-холст будет скомпонован прямо из всех значений 4 каналов RGBA, вплоть до значений следующей остановки, в то время как CSS, кажется, воспринимает прозрачность как частный случай.
Чтобы получитьтот же результат, что и CSS на холсте, вам придется установить первый прозрачный стоп на следующий, изменив только значение альфа:
var ctx = c.getContext('2d'),
grad = ctx.createLinearGradient(0,0,0,150);
grad.addColorStop(0, 'rgba(255,0,0,0)'); // transparent red
grad.addColorStop(1, 'rgba(255,0,0)');
ctx.fillStyle = grad;
ctx.fillRect(0,0,300,150);
#html{
background: linear-gradient(rgba(0, 0, 0, 0), rgb(255, 0, 0));
height: 150px;
width: 300px;
display: inline-block;
}
<div id="html"></div>
<canvas id="c"></canvas>