64

Can I use the canvas element as a css background?

Trott
  • 66,479
  • 23
  • 173
  • 212
Ben Shelock
  • 20,154
  • 26
  • 92
  • 125
  • You can use a canvas element as a background, but CSS doesn't have anything to do with that. – tcooc Aug 03 '10 at 14:15
  • 1
    Yes you can!!!! $('body').css({'background-image':"url(" + Canvas.toDataURL("image/png")+ ")" }); See my answer below: one line of code and cross-browser compatible too. – frenchie Feb 20 '12 at 23:57
  • 1
    That's is **NOT** making the canvas a background. That is making a copy of the content of the canvas as an image and then using the image as a background. – gman Jul 20 '16 at 05:40

8 Answers8

63

This has been possible in WebKit since 2008, see here.

<html>
 <head>
 <style>
 div { background: -webkit-canvas(squares); width:600px; height:600px; border:2px solid black }
 </style>

 <script type="application/x-javascript">
function draw(w, h) {
 var ctx = document.getCSSCanvasContext("2d", "squares", w, h);

 ctx.fillStyle = "rgb(200,0,0)";
 ctx.fillRect (10, 10, 55, 50);

 ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
 ctx.fillRect (30, 30, 55, 50);
}
 </script>
 </head>
 <body onload="draw(300, 300)">
   <div></div>
 </body>

</html>

Currently, Firefox 4 contains a feature, which allows you to use any element (including canvas) as a CSS background, in this fashion:

<p id="myBackground1" style="background: darkorange; color: white;  width: 300px; height: 40px;">
  This element will be used as a background.
</p>
<p style="background: -moz-element(#myBackground1); padding: 20px 10px; font-weight: bold;">
  This box uses #myBackground1 as its background!
</p>

See Mozilla hacks for specifics.

atiquratik
  • 1,296
  • 3
  • 27
  • 34
livedo
  • 1,069
  • 9
  • 6
  • 1
    Nice!! I had no idea you could do this. I made a jsfiddle from your code here: [http://jsfiddle.net/cRqf6/](http://jsfiddle.net/cRqf6/) – Eric Rowell Sep 20 '11 at 18:13
  • I've just wanted to mention -moz-element trick, but you was first. So, I've just live an example - http://jsfiddle.net/U72dt/1/ – shabunc Dec 30 '11 at 14:01
  • 1
    See my answer below: one line of code and cross-compatible on all browsers – frenchie Feb 22 '12 at 09:58
  • Here's another jsfiddle example of a canvas background: http://jsfiddle.net/jarble/U72dt/8/ – Anderson Green Jan 27 '13 at 06:26
  • would be possible to set percentual values to the canvas height/width? – QUB3X Sep 26 '14 at 19:32
  • 3
    `document.getCSSCanvasContext()` has been deprecated and removed from all Chromium platforms. What else could be used instead? – see Dec 15 '16 at 12:23
  • 4
    This was deprecated, here: https://bugs.chromium.org/p/chromium/issues/detail?id=161699 – Jonathan Mar 29 '17 at 22:50
59

Yes!!!! You can put a canvas in CSS background.

var Canvas = document.createElement("canvas");
... do your canvas drawing....
$('body').css({'background-image':"url(" + Canvas.toDataURL("image/png")+ ")" });

I know this is a pretty old question but I felt like posting my answer for people who'd visit this page because this is the correct answer, in just one line of code, using the .toDataURL function. It works in every browser that supports canvas.

frenchie
  • 51,731
  • 109
  • 304
  • 510
  • 8
    The only problem with this is that the canvas can't be modified after being set as the background. – Tom Wright Mar 02 '12 at 16:31
  • 2
    True but there's an easy workaround, if needed. Just create a copy of the canvas and store it as a global so that when you apply .toDataURL() there's still a canvas available. Overall, I can't see how any of other proposed answers can beat this one-liner solution. – frenchie Mar 02 '12 at 18:07
  • 7
    @frenchie The other answers beat your one-liner because: Using toDataURL was already proposed in the other answers, 18 months before you did. Also it doesn't answer the question. It's a work around. Your code does not put a canvas in CSS background. It puts the momentary image data from a canvas in CSS background. – Robert Mar 15 '12 at 15:14
  • 1
    My answer simply decouples the canvas from the css background: instead of inserting the actual canvas, you insert an image of the canvas. The actual canvas is still editable and can always be reinserted into the background via my solution. After all, the goal is to visually render the background and I think most of those who'll come here for help will appreciate the simplicity of my solution. – frenchie Mar 15 '12 at 17:09
  • 1
    You can't really call it a 'one-liner' solution if it requires a library... It's a pretty solid fallback for the webkit/moz-specific solutions though, so I voted it up – JuanOjeda Mar 25 '12 at 08:50
  • 4
    This isn't even remotely making the canvas a background. It's making an image of the contents of a canvas and then using the image as a background. This solution if used to constantly update (arguably the reason people generally want a canvas background) will use massive amounts of CPU and memory. Let's say you have a full window canvas. So calling toDataUrl stalls the graphics pipeline, pulls out 4-8meg of pixels, zip compresses it, converts it to base64 string. That string is the copied, converted back to binary, unzipped, reconverted into pixels, and then copied to the GPU. What a mess. – gman Jul 20 '16 at 05:43
  • 1
    The overhead for this is at least 33% https://developers.google.com/web/updates/2012/12/Canvas-driven-background-images – Jonathan Mar 29 '17 at 22:51
12

I think the closest you could get is to render into a canvas, call toDataUrl() on it to retrieve the contents as an image, and assignment that result to the desired element's background-image property. This will only give a static background, though. If you want to be able to further update the canvas, however, then you'll need to instead position the canvas behind another element, as Johan has already suggested.

bcat
  • 8,833
  • 3
  • 35
  • 41
3

Try -moz-element(#id) for CSS background in Firefox.

And -webkit-canvas(name) for CSS background in WebKit based browsers.

atiquratik
  • 1,296
  • 3
  • 27
  • 34
user1635543
  • 97
  • 1
  • 3
3

You can use CSS Paint API

.elem {
  backgound: paint(squares);
}

See more details here:

Blog posts:

https://vitaliy-bobrov.github.io/blog/exploring-the-css-paint-api/ https://vitaliy-bobrov.github.io/blog/css-paint-in-action-bar-chart/

Demos: https://vitaliy-bobrov.github.io/css-paint-demos/

  • 2
    This appears to only be supported by Chrome: https://caniuse.com/#feat=css-paint-api – Adam Lydick Dec 30 '18 at 07:10
  • 1
    Chrome starting from v65, Safari in development (Safari TP). It is easy to fallback to solid color/bg image. – Vitalii Bobrov Dec 31 '18 at 08:48
  • Unfortunatelly this is just a "limited version of Canvas API. Why limited? For security reasons, you are not able to read pixels from an image or render text. But you can draw arcs, rectangles, paths, etc." (Source: https://vitaliy-bobrov.github.io/blog/exploring-the-css-paint-api/) – Tamás Bolvári Feb 21 '19 at 17:21
3

I've been triying to achieve this same feature past weeks, the best solution I've found its the same proposed by bcat:

  1. Render canvas (visible or hidden)
  2. Get canvas image with "canvas.toDataURL"
  3. Asign this image-data as background image for the element (I use MooTools)

The bad news, for static images works great, but with animation in Chrome sometimes "blinks", and in Firefox blinks-a-lot. Maybe someone knows a workaround to get rid of this "nasty blinking".

Best regards.
P:.

<!DOCTYPE html>
<html>
<head>
<title>Asign canvas to element background</title>
<script type="text/javascript" src="/js/mootools.1.2.4.js"></script>
<style type="text/css">
* {
    outline:0;
    padding:0;
    margin:0;
    border:0;
}
body {
    color:#fff;
    background:#242424;
}
</style>
<script>
window.addEvent('domready',function() {

//GET BODY
var mibodi = $('mibodi');
var viewportSize = mibodi.getSize();

//GET CANVAS
var micanvas = $('micanvas');
var ctx = micanvas.getContext('2d');
var playAnimation = true;

//GET DIV
var midiv = $('midiv');

//VARIABLES
var rotate_angle = 0;
var rotate_angle_inc = 0.05;

//FUNCIÓN DE INICIALIZACIÓN
function init(){

    ctx.clearRect (0, 0, 512, 512); //CLEAR CANVAS
    ctx.fillStyle = 'rgba(128,128,128,1)';
    ctx.strokeStyle = 'rgba(255,255,255,1)';

    if (playAnimation) {
    setInterval(draw,100);//
  }

} //INIT

//FUNCIÓN DE DIBUJADO
function draw() {

    //CLEAR BACKGROUND
    ctx.clearRect (0, 0, 512, 512);

    //DRAW ROTATING RECTANGLE
    ctx.save();
    ctx.translate( micanvas.width / 2, micanvas.height / 2 );
    ctx.rotate( rotate_angle );
    ctx.fillRect(0, 0, 100, 100);
    ctx.restore();

    //GET CANVAS IMAGE
    var dataURL = micanvas.toDataURL("image/png");

    //SET IMAGE AS BACKGROUND OF THE ELEMENTS
    midiv.setStyle('background-image', 'url(' + dataURL + ')');
    mibodi.setStyle('background-image', 'url(' + dataURL + ')');

    //ANGLE INCREMENT
    rotate_angle = rotate_angle + rotate_angle_inc;

} //DRAW

//BEGIN TO DRAW
init();

});//domeady

</script>
</head>
<body id="mibodi" >

<canvas id="micanvas" width="512" height="512" style="float:left;" style="display:none;">
Este texto se muestra para los navegadores no compatibles con canvas.
<br>
Por favor, utiliza Firefox, Chrome, Safari u Opera.
</canvas>

<div id="midiv" style="width:512px;height:512px;background:#f00;float:left;">
    Sample
</div>

</body>
</html>
Carlos Cabo
  • 741
  • 1
  • 7
  • 14
2

You can emulate this behavior quickly without the performance drop of toDataURL() using z-index (granted, it's a workaround, since CSS images 4 / CSS Houdini hasn't implemented "background: element(#mycanvas)" as of 2017))

Working JSFiddle here. I didn't write this, all credit goes to Derek Leung:

http://jsfiddle.net/DerekL/uw5XU/

Jonathan
  • 6,741
  • 7
  • 52
  • 69
0

Unable to comment so I will create my own answer for this.

This answer is based off of @livedo, @Eric Rowell, and @shabunc

http://jsfiddle.net/MDooley47/yj26psdb/

window.i = 0;
function draw(w, h) {
    window.i+=5;
    if (window.webkitURL != null) {
        var ctx = document.getCSSCanvasContext("2d", "squares", 100, 100);


        ctx.fillStyle = "rgb(200,0,0)";
        ctx.fillRect (10, 10, w, h);

        ctx.fillStyle = "rgba(0, 0, 200, 0.5)";

        ctx.fillRect (30, 30, w, h);
    }
    else {
        var ctxmozc = document.getElementById("squares");
        var ctxmoz = ctxmozc.getContext("2d");

        ctxmoz.fillStyle = "rgb(200,0,0)";
        ctxmoz.fillRect (10, 10, w, h);

        ctxmoz.fillStyle = "rgba(0, 0, 200, 0.5)";

        ctxmoz.fillRect (30, 30, w, h);
    }
}
setInterval(function(){draw(window.i, window.i);}, 500);
 div {
     background: -webkit-canvas(squares);
     background: -moz-element(#squares) repeat-x;
     width:575px;
     height:475px;
     border:2px solid black
 }
<body>
    <div></div>
    <canvas id="squares" name="squaresmoz" style="display: none;" ></canvas>
</body>
marzvrover
  • 91
  • 7