Six Creative Techniques to Build a Guide Overlay Without Images

This tutorial explains six different approaches—using z-index, opacity, borders, box‑shadow, element cloning, and canvas—to create a guide overlay (mask layer) that highlights specific page areas without relying on image assets, complete with code examples and visual demos.

WecTeam
WecTeam
WecTeam
Six Creative Techniques to Build a Guide Overlay Without Images

Understanding Guide Overlays

First, get to know the guide overlay concept: a semi‑transparent mask that highlights a specific area of the page.

A guide overlay has two core elements: the highlighted content area and the semi‑transparent mask.

Why Not Use Images?

Large image files affect loading speed.

Image content is fake and may not align with real page content.

Full‑screen images often mismatch screen dimensions, leaving black bars or distortion.

Overlay images cannot be clicked.

Using images for overlays feels outdated.

Six Ways to Implement a Guide Overlay

Use z-index to stack a mask and highlighted element.

Adjust opacity to make non‑target elements semi‑transparent.

Leverage border tricks to create shapes like triangles.

Apply box‑shadow with a large spread.

Clone the target node into a top‑layer mask.

Draw the overlay with canvas using XOR composition.

All six methods can satisfy business needs; z‑index is the simplest, canvas is the most flexible, and the dynamic opacity (skeleton screen) approach is my personal favorite because it’s fun and cool!

Method 1: Using z-index

Add a full‑screen semi‑transparent div with a higher z-index than page elements.

Place the highlighted content div above the mask with an even higher z-index.

This is easy to understand: set the highlighted area as the top layer and the mask beneath it.

.z1{position:absolute;left:50px;top:50px;width:50px;height:50px;background:blue;z-index:1;}
.z2{position:absolute;left:60px;top:60px;width:50px;height:50px;background:red;z-index:2;}
.z3{position:absolute;left:70px;top:70px;width:50px;height:50px;background:yellow;z-index:3;}

Modify .z2 as needed:

.z2{position:absolute;left:50px;top:50px;width:50px;height:50px;background:black;opacity:0.5;z-index:2;animation:z_index 2s linear infinite alternate;}

By dynamically setting z-index and opacity with JavaScript, you can achieve a functional guide overlay.

let arry = Array.from(document.querySelectorAll('.z'));
let index = -1;
let direct = 1;
setInterval(()=>{
  if(index>=5) direct=-1;
  else if(index<=0) direct=1;
  index+=direct;
  arry.forEach((d,i)=>{d.style.opacity=1;});
  setTimeout(()=>{
    arry.forEach((d,i)=>{if(i===index) return; d.style.opacity=0.1;});
  },1000);
},2000);

Method 2: Using opacity

Keep the highlighted content unchanged.

Make all other page nodes semi‑transparent.

This mimics a skeleton‑screen effect where only the target area remains fully visible.

.wrap{display:flex;flex-wrap:wrap;}
.z{width:50px;height:50px;background:blue;}
.z1{background:blue;}
.z2{background:black;}
.z3{background:yellow;}
.z4{background:red;}
.z5{background:green;}
.z6{background:orange;}

JavaScript toggles opacity of non‑target elements:

let arry = Array.from(document.querySelectorAll('.z'));
let index = -1;
let direct = 1;
setInterval(()=>{
  if(index>=5) direct=-1;
  else if(index<=0) direct=1;
  index+=direct;
  arry.forEach((d,i)=>{d.style.opacity=1;});
  setTimeout(()=>{
    arry.forEach((d,i)=>{if(i===index) return; d.style.opacity=0.1;});
  },1000);
},2000);

Method 3: Using border

Create a div with four borders.

Make three borders transparent and one colored to form a triangle.

.border_1{width:100px;height:100px;border-top:50px solid red;border-right:50px solid transparent;border-bottom:50px solid transparent;border-left:50px solid transparent;box-sizing:border-box;}

This produces an inverted triangle useful for tips and pointers.

.border_2{width:100px;height:100px;background-color:green;border-style:solid;border-color:red yellow blue black;}

To create a mask, set the inner area transparent and the borders semi‑transparent.

.border_5{width:150px;height:150px;border-top:50px solid rgba(0,0,0,0.5);border-right:50px solid rgba(0,0,0,0.5);border-bottom:50px solid rgba(0,0,0,0.5);border-left:50px solid rgba(0,0,0,0.5);box-sizing:border-box;}

Animate the border width to expand the mask:

@keyframes border_ani{from{border-width:20px;}to{border-width:100px;}}

Method 4: Using box‑shadow

Add a div matching the target size.

Apply a huge, semi‑transparent box‑shadow (e.g., 2000px) to cover the rest of the page.

.boxshadow_1{width:50px;height:50px;background:blue;box-shadow:10px 10px 5px 4px #000;}

Make the shadow transparent:

.boxshadow_2{width:50px;height:50px;background:blue;box-shadow:10px 10px 5px 4px rgba(0,0,0,0.5);}

Increase the shadow spread to achieve a full‑screen mask:

.boxshadow_3{width:50px;height:50px;background:blue;box-shadow:0 0 5px 0 rgba(0,0,0,0.5);animation:box_ani 2s linear infinite alternate;}
@keyframes box_ani{from{box-shadow:10px 10px 5px 0 rgba(0,0,0,0.5);}to{box-shadow:10px 10px 5px 100px rgba(0,0,0,0.5);}}
Setting the shadow size beyond 2000px may fail on some mobile browsers; 2000px is a safe limit.

Method 5: Cloning page nodes

Create a fixed mask div covering the viewport.

Create a content div inside the mask.

Copy the target element’s HTML into the content div and position it to match the original.

<div class="content one">我是第一个div,我是第一个div</div>
<div class="content two">我是第二个div,我是第二个div</div>
<div class="content three">我是第三个div,我是第三个div</div>
<div class="content four">我是第四个div,我是第四个div</div>
<div class="mask"></div>
<div id="maskContent"></div>
.content{padding:10px;z-index:0;}
.mask{position:fixed;left:0;top:0;width:100%;height:100%;background:rgba(0,0,0,0.8);z-index:900;}
#maskContent{position:fixed;z-index:999;display:inline-block;background:#fff;}

JavaScript copies and positions the element:

function renderContent(cls){
  let targetNode = document.querySelector(`.${cls}`);
  let maskContent = document.getElementById('maskContent');
  maskContent.innerHTML = targetNode.outerHTML;
  let pos = targetNode.getBoundingClientRect();
  maskContent.style.top = pos.top + 'px';
  maskContent.style.left = pos.left + 'px';
  maskContent.style.width = pos.width + 'px';
  maskContent.style.height = pos.height + 'px';
}
let arr = ['one','two','three','four'];
let i = 0;
setInterval(()=>{
  renderContent(arr[i]);
  i++;
  if(i>=4) i = 0;
},1000);

Method 6: Using canvas

Add a full‑screen canvas element.

Draw a semi‑transparent rectangle covering the whole viewport.

Set globalCompositeOperation = 'xor' and draw a rectangle matching the target element; the overlapping area becomes transparent, revealing the target.

function mask(cls){
  let targetNode = document.querySelector(`.${cls}`);
  let pos = targetNode.getBoundingClientRect();
  let canvas = document.getElementById('mask');
  let width = window.innerWidth;
  let height = window.innerHeight;
  canvas.setAttribute('width', width);
  canvas.setAttribute('height', height);
  var ctx = canvas.getContext('2d');
  ctx.globalCompositeOperation = 'source-over';
  ctx.fillStyle = 'rgba(255,255,255,0.9)';
  ctx.fillRect(0,0,width,height);
  ctx.fillStyle = 'white';
  ctx.globalCompositeOperation = 'xor';
  ctx.fillRect(pos.left, pos.top, pos.width, pos.height);
}
let arr = ['one','two','three','four'];
let i = 0;
setInterval(()=>{
  mask(arr[i]);
  i++;
  if(i>=4) i = 0;
},1000);

Which implementation do you prefer?

JavaScriptWeb developmentOverlayguide
WecTeam
Written by

WecTeam

WecTeam (维C团) is the front‑end technology team of JD.com’s Jingxi business unit, focusing on front‑end engineering, web performance optimization, mini‑program and app development, serverless, multi‑platform reuse, and visual building.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.