DEV Community

Cover image for How I Built a Silent Communication Tool with Pure HTML, CSS & JS (No Framework)
ByteKits
ByteKits

Posted on

How I Built a Silent Communication Tool with Pure HTML, CSS & JS (No Framework)

I built a small tool called Pixel Mode that lets you flash big bold text
on your screen to communicate silently — no talking needed.

Think: holding up your phone in a meeting to say "URGENT 🚨" or "BRB 👀"
without interrupting anyone. Or a teacher silently signaling students.
Or just fun time pass with friends.

🔗 Live site: https://pixelmode.free.nf/


The Problem I Wanted to Solve

Ever been on a call and someone walks into the room needing your attention?
Or in a library, classroom, or open office where you can't speak freely?

Most solutions are clunky — hand signals, sticky notes, typing on your phone
and showing the screen. I wanted something instant, fullscreen, and readable
from across the room.

So I built Pixel Mode in a single HTML file. No React. No build tools.
Just vanilla HTML, CSS, and JavaScript.


What It Does

  • Flash Mode — type anything, hit Apply, it goes fullscreen in giant bold text
  • Silent Talker — pre-loaded office phrases like "Can we talk?", "I'm on a call", "URGENT"
  • Quick React — one-tap YES/NO/MAYBE/👍/👎/😂 reactions
  • FX Mode — glitch, pulse, typewriter effects
  • Double-tap to edit — edit text directly on the fullscreen screen
  • Orientation lock — rotate and lock portrait/landscape
  • XP & Streaks — gamification to make it fun
  • Share via URL — any text is shareable as a link

Key Technical Bits

1. Text favicon with Canvas

Instead of an image file, I generate the favicon dynamically:

const c = document.createElement('canvas');
c.width = 64; c.height = 64;
const ctx = c.getContext('2d');
ctx.fillStyle = '#070b14';
ctx.beginPath();
ctx.roundRect(0, 0, 64, 64, 14);
ctx.fill();
ctx.fillStyle = '#00f0ff';
ctx.font = 'bold 26px Arial';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('PM', 32, 34);
const link = document.createElement('link');
link.rel = 'icon';
link.href = c.toDataURL();
document.head.appendChild(link);
Enter fullscreen mode Exit fullscreen mode

No favicon.ico file needed. Works in all modern browsers.

2. Auto-scaling font size

The flash text needs to fit any length — from "Hi 👋" to a full sentence:

function autoScaleFlashText(text) {
  const len = text.length;
  let size;
  if      (len <= 10)  size = 'clamp(60px, 14vw, 180px)';
  else if (len <= 25)  size = 'clamp(44px, 10vw, 130px)';
  else if (len <= 50)  size = 'clamp(32px, 7vw, 90px)';
  else if (len <= 100) size = 'clamp(24px, 5vw, 64px)';
  else                 size = 'clamp(20px, 4vw, 48px)';
  document.getElementById('flashText').style.fontSize = size;
}
Enter fullscreen mode Exit fullscreen mode

clamp() handles both tiny phones and large monitors automatically.

3. Double-tap detection (no library)

Mobile browsers don't have a native double-tap event. I built it manually:

let lastTapTime = 0;

element.addEventListener('click', function() {
  const now = Date.now();
  const delta = now - lastTapTime;
  lastTapTime = now;

  if (delta < 350 && delta > 0) {
    triggerInlineEdit(); // double tap!
  }
});
Enter fullscreen mode Exit fullscreen mode

350ms window feels natural — not too tight, not too loose.

4. Orientation lock with CSS fallback

The Screen Orientation API isn't supported on iOS Safari. So I fall back
to a CSS transform rotation:

function rotateFallback(to) {
  const overlay = document.getElementById('flashOverlay');
  const isPortrait = window.innerHeight > window.innerWidth;
  const needsRotation = (to === 'landscape' && isPortrait) 
                     || (to === 'portrait' && !isPortrait);
  if (!needsRotation) return;

  const vw = window.innerWidth;
  const vh = window.innerHeight;
  const angle = to === 'landscape' ? 90 : -90;

  overlay.style.transform = `rotate(${angle}deg)`;
  overlay.style.width = vh + 'px';
  overlay.style.height = vw + 'px';
  overlay.style.left = (vw - vh) / 2 + 'px';
  overlay.style.top = (vh - vw) / 2 + 'px';
  overlay.style.inset = 'unset';
}
Enter fullscreen mode Exit fullscreen mode

5. Persistent XP with localStorage

All progress — XP, level, streak, badges — survives page refreshes:

let xp = parseInt(localStorage.getItem('pm_xp') || '0');

function earnXP(amount) {
  xp += amount;
  localStorage.setItem('pm_xp', xp);
  updateXP();
}
Enter fullscreen mode Exit fullscreen mode

Simple but effective. No backend needed.


What I Learned

Single file is underrated. The entire app — including all CSS, JS,
fonts, and logic — lives in one HTML file. It loads instantly, works
offline after first visit, and is trivially easy to deploy anywhere.

CSS clamp() is magic. Responsive typography without a single
media query breakpoint for font sizes. I use it everywhere now.

The Screen Orientation API is a mess. Chrome supports it,
Firefox partially, Safari not at all. Always build a fallback.

Gamification works even in utility apps. Adding XP, levels,
streaks, and badges made me actually want to use my own tool more.
Users spending more time = more likely to share.


Try It

🔗 https://pixelmode.free.nf/

It's completely free, no login, no install. Works on any device.

If you're in a meeting right now and need to silently tell someone
something — open it, type, hit Apply. Done in 3 seconds.


Also building ByteKits — a collection of tools and resources for
developers and AI users. Check out the Prompt Engineering Master PDF
at https://bytekits.free.nf if that's your thing.

Top comments (0)