Fullscreen Mode

element.requestFullscreen() fills the screen with any element, but only from a user gesture. document.fullscreenElement names it, document.exitFullscreen() leaves, and fullscreenchange fires both ways: resize the bitmap there. The API is not Baseline, since iPhone Safari 10 offers full screen for video only.

Full screen on a click, with the bitmap resized on every changeHTML
<button id="full">Full screen</button>
<canvas id="designer" style="width:600px; height:190px"></canvas>
<script src="hidpi.js"></script>
<script>
  full.onclick = () => designer.requestFullscreen();          // Esc also leaves
  designer.ondblclick = () => document.fullscreenElement && document.exitFullscreen();
  document.addEventListener('fullscreenchange', () => {
    hidpi(designer);                                     // new size, new bitmap; then redraw
    const shown = document.fullscreenElement?.id ?? 'page';
    console.log(`${shown}: ${designer.width} x ${designer.height}`);
  });
  designer.requestFullscreen().catch(e => console.log(`on load: ${e.name}: ${e.message}`));
</script>
Output
on load: TypeError: Permissions check failed
designer: 1600 x 1200
page: 1200 x 380

In headless Chrome 154 1 (800 x 600, ratio 2) the request on load was refused, a click entered full screen and a double-click left. CSS styles that state with :fullscreen.

Requesting full screen for a canvas and redrawing it at the new size on fullscreenchangeHTMLLive
<!doctype html>
<style>
  body { margin: 0; padding: 8px; font: 13px system-ui, sans-serif; background: #fafaf7; }
  #designer { width: 600px; max-width: 100%; height: 200px; display: block; background: #fff; border: 1px solid #ddd; }
  #designer:fullscreen { width: 100vw; height: 100vh; max-width: none; border: 0; }
</style>
<button id="full">Full screen</button>
<canvas id="designer"></canvas>
<p id="status"></p>
<script>
  function hidpi(c, r = devicePixelRatio) {
    c.width = c.clientWidth * r;  c.height = c.clientHeight * r;
    const ctx = c.getContext('2d');  ctx.scale(r, r);  return ctx;
  }
  const designer = document.getElementById('designer');
  const status = document.getElementById('status');

  // Redraw the shelf to fit whatever size the canvas has now
  function draw() {
    const ctx = hidpi(designer), w = designer.clientWidth, h = designer.clientHeight;
    const colors = ['#1f5f8b', '#5b3f99', '#e09a10', '#3f7d3a', '#b5452f', '#2a9d8f'];
    const bw = w / 8, bh = h * 0.7;
    ctx.fillStyle = '#8d6e63';  ctx.fillRect(0, h * 0.85, w, h * 0.06);          // the shelf
    colors.forEach((color, i) => {
      ctx.fillStyle = color;
      ctx.fillRect(bw * (i + 1), h * 0.85 - bh * (0.8 + 0.2 * Math.sin(i * 2)), bw * 0.8, bh * (0.8 + 0.2 * Math.sin(i * 2)));
    });
    ctx.fillStyle = '#263238';  ctx.font = `${Math.round(h / 12)}px sans-serif`;
    ctx.fillText(`${designer.width} × ${designer.height} bitmap pixels`, 10, h / 10);
  }

  // requestFullscreen() works only from a user gesture (and in frames allowed to use it)
  document.getElementById('full').onclick = () => {
    designer.requestFullscreen()
      .catch(e => status.textContent = `Refused: ${e.name}. Embedded frames need allow="fullscreen".`);
  };
  designer.ondblclick = () => document.fullscreenElement && document.exitFullscreen();
  // fullscreenchange fires on entering and leaving: resize the bitmap and redraw
  document.addEventListener('fullscreenchange', () => {
    draw();
    status.textContent = document.fullscreenElement ? 'In full screen: double-click or Esc to leave' : 'Back on the page';
  });

  draw();
  status.textContent = document.fullscreenEnabled
    ? 'Click the button to enter full screen.'
    : 'Full screen is disabled in this frame (fullscreenEnabled is false).';
</script>