Close Menu
  • Home
  • Life style
    • Celebrities
    • Exercise & Training
    • Healthline
  • Exploration
    • Beauty tips
    • Business
    • Travel guides
    • Fashion
    • Technology
  • Web tutorials
    • Hosting & Servers
    • Blogger guides
    • WordPress guides
  • English
    • Tiếng Việt
    • Hmoob
    • English
Facebook YouTube X (Twitter) Instagram
Trending
  • CPU Performance API: Make Web Interfaces Lighter for Low-End Devices
  • Move XSLT out of the browser before Chrome 158 ends support
  • Create a Draggable Desktop PWA Title Bar with `window-drag`
  • Designing a Malware Package Advisory Pipeline You Can Roll Back
  • How to Keep CI/CD Running Through a GitHub Actions Outage
  • Reduce Web Notification Spam by Auditing Chrome and FCM Permissions
  • Turn On Dependabot Malware Alerts for 8 GitHub Ecosystems
  • What Is Worth Seeing at Olivia Rodrigo: The Cure Unraveled?
Facebook YouTube X (Twitter) Instagram
SaibABCSaibABC
Chú thích cho quảng cáo
  • Home
  • Life style
    1. Celebrities
    2. Exercise & Training
    3. Healthline
    4. View All

    Michael Jackson Fashion Exhibition: When Clothing Tells the Story of the Stage

    13/09/2026

    Buy Concert Tickets Safely: 7 Ways to Avoid Social Media Scams

    13/09/2026

    How Many World Cup Goals Has Messi Scored? Year-by-Year Through 2026

    13/09/2026

    Messi’s Six World Cups: From the 2014 Defeat to 2022 Glory

    13/09/2026

    Five-Minute Office Exercises: A Snack-Sized Movement Schedule

    30/08/2026

    Strengthen Your Core with 12 Exercises from Beginner to Advanced

    30/08/2026

    Where Do Children Get Too Much Sodium? How to Cut Back

    12/09/2026

    “Tejocote root” May Not Be Safe Tejocote Root

    12/09/2026

    Outpatient Antibiotics: Safe Prescribing Takes More Than Drug Choice

    11/09/2026

    Is Glutathione Injection Safe? Don’t Confuse Food-Grade Powder with Injectable Material

    11/09/2026

    Michael Jackson Fashion Exhibition: When Clothing Tells the Story of the Stage

    13/09/2026

    Buy Concert Tickets Safely: 7 Ways to Avoid Social Media Scams

    13/09/2026

    How Many World Cup Goals Has Messi Scored? Year-by-Year Through 2026

    13/09/2026

    Messi’s Six World Cups: From the 2014 Defeat to 2022 Glory

    13/09/2026
  • Exploration
    1. Beauty tips
    2. Business
    3. Travel guides
    4. Fashion
    5. Technology
    Featured

    CPU Performance API: Make Web Interfaces Lighter for Low-End Devices

    By Nuj Coom13/09/2026
    Recent

    CPU Performance API: Make Web Interfaces Lighter for Low-End Devices

    13/09/2026

    Create a Draggable Desktop PWA Title Bar with `window-drag`

    13/09/2026

    Designing a Malware Package Advisory Pipeline You Can Roll Back

    13/09/2026
  • Web tutorials
    1. Hosting & Servers
    2. Blogger guides
    3. WordPress guides
    4. View All

    Let’s Encrypt on Vultr: Enable HTTPS and Automatic Renewal

    09/09/2026

    Install WordPress on Vultr Manually: From Ubuntu to HTTPS

    08/09/2026

    Point Your Domain to a Vultr VPS and Verify the DNS Connection

    08/09/2026

    Set Up an Ubuntu VPS on Vultr: From Account Creation to SSH

    07/09/2026

    Blogger Permissions for Collaborators: Keep Control

    07/09/2026

    Add a Blogger Report Abuse Button to Custom Themes

    07/09/2026

    Why Blogger Image SEO Takes More Than File Names and Alt Text

    07/09/2026

    Blogger Image Lazy Loading for SEO: What Googlebot Must See

    05/09/2026

    WordPress 7.1: Convert GIFs to Video to Reduce File Size

    11/09/2026

    Install WordPress on Vultr Manually: From Ubuntu to HTTPS

    08/09/2026

    WordPress 7.1 AVIF & HEIC: Reduce Server Load

    02/09/2026

    WordPress 7.1 Responsive Breakpoints: How to Test Them

    02/09/2026

    CPU Performance API: Make Web Interfaces Lighter for Low-End Devices

    13/09/2026

    Move XSLT out of the browser before Chrome 158 ends support

    13/09/2026

    WordPress 7.1: Convert GIFs to Video to Reduce File Size

    11/09/2026

    WebMCP for Websites: Turn an HTML Form into an AI Agent Tool

    11/09/2026
  • English
    • Tiếng Việt
    • Hmoob
    • English
SaibABCSaibABC
Home»Exploration»Technology»Create a Draggable Desktop PWA Title Bar with `window-drag`
Technology 11 Mins ReadNo Comments

Create a Draggable Desktop PWA Title Bar with `window-drag`

Nuj CoomBy Nuj Coom
Facebook Twitter Pinterest LinkedIn Tumblr Email
Chú thích cho quảng cáo

Contents

  1. Prepare the right environment before writing CSS
  2. Enable Window Controls Overlay in the manifest
  3. Create the title bar structure and interactive areas
  4. Leave a safe area for the window controls
  5. Detect the display mode and update the geometry with JavaScript
  6. Install and verify in the correct order
  7. Troubleshoot by symptom
    1. The title bar does not drag
    2. A button or input field is dragged instead of responding to interaction
    3. Content is obscured by the close or maximize button
    4. Works in Chrome 152 but not in another browser
  8. Usability, security, and fallback
  9. Reference source

The short answer: to move the window using a custom interface, you need to enable window-controls-overlay in the manifest, install the PWA on a computer, set window-drag: move on empty areas, and set window-drag: none directly on buttons, input fields, and other interactive elements. If you open the app in a regular tab, dragging the window will not work.

In Chrome 152, window-drag is a CSS property used to mark an area from which the window of a desktop web app can be moved. This mechanism does not turn a web page in a tab into an operating-system window; it requires an installed PWA and a display mode that supports Window Controls Overlay (according to developer.chrome.com). The examples below use a note-taking app for illustration. Replace the app name, icon paths, and content with those from your project.

Prepare the right environment before writing CSS

This example assumes that you already have a web app that can run over HTTPS or localhost, with a manifest file and app icons. For the browser to recognize and install the PWA, the app must also meet the browser’s current installation requirements, such as having the manifest linked correctly and the app’s installation mechanism ready.

  • Use Chrome 152 on a desktop operating system; this article does not assume equivalent support across all browsers.
  • Serve the app over HTTPS or localhost. Do not use a regular HTTP URL on a public server for the installation step.
  • Make sure the icon files declared in the manifest actually exist. If you use the example below, create /icons/icon-192.png and /icons/icon-512.png, or replace them with valid icon paths of your own.
  • You must be able to edit the HTML, CSS, and manifest, and open DevTools to inspect files and syntax errors.

If the app cannot yet be installed as a PWA, resolve the installation requirements first. window-drag is not a substitute for a manifest or an installed desktop app.

Enable Window Controls Overlay in the manifest

Open the manifest file in the app’s root directory, usually manifest.webmanifest. Add content similar to the following, replacing sample values such as the app name, start_url, scope and the icon paths:

Chú thích cho quảng cáo
{
  "name": "Desktop Notes",
  "short_name": "Notes",
  "start_url": "/",
  "scope": "/",
  "display_override": [
    "window-controls-overlay",
    "standalone"
  ],
  "display": "standalone",
  "background_color": "#111827",
  "theme_color": "#111827",
  "icons": [
    {
      "src": "/icons/icon-192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "/icons/icon-512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
}

Add the following HTML to the <head> section of the main page, then update the path if the manifest is not in the root directory:

<link rel="manifest" href="/manifest.webmanifest">

Chrome will try the first value in display_override; if it cannot use it, the browser may fall back to standalone. The display property provides a fallback for environments that do not support the override mechanism. After editing the manifest, reload the app and use DevTools to verify that the manifest file returns a successful HTTP status, contains valid JSON, and that the icons do not return 404 errors.

Create the title bar structure and interactive areas

In the app’s HTML, place the title bar before the main content. The example below includes branding, a search field, and a settings button:

<body>
  <header class="app-titlebar">
    <div class="titlebar-content">
      <div class="brand">
        <span class="brand-mark" aria-hidden="true">N</span>
        <span>Desktop Notes</span>
      </div>

      <label class="search-box">
        <span class="sr-only">Tìm ghi chú</span>
        <input type="search" placeholder="Tìm ghi chú">
      </label>

      <button class="settings-button" type="button">
        Cài đặt
      </button>
    </div>
  </header>

  <main class="page-content">
    <h1>Ghi chú của tôi</h1>
    <p>Nội dung ứng dụng nằm bên dưới thanh tiêu đề tùy biến.</p>
  </main>
</body>

Next, add CSS to the stylesheet loaded by the page. The window-drag: move property applies to the title bar; areas that can receive user input are excluded with window-drag: none:

:root {
  --titlebar-height: 44px;
  --surface: #111827;
  --text: #f9fafb;
  --border: #374151;
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  min-height: 100%;
}

body {
  color: #111827;
  background: #f3f4f6;
  font: 15px/1.5 system-ui, sans-serif;
}

.app-titlebar {
  min-height: var(--titlebar-height);
  color: var(--text);
  background: var(--surface);
  window-drag: move;
}

.titlebar-content {
  min-height: var(--titlebar-height);
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 12px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
  window-drag: none;
}

.brand-mark {
  display: grid;
  width: 24px;
  height: 24px;
  place-items: center;
  border-radius: 6px;
  background: #2563eb;
  font-weight: 700;
}

.search-box {
  flex: 1;
  max-width: 420px;
  window-drag: none;
}

.search-box input {
  width: 100%;
  min-height: 30px;
  padding: 4px 10px;
  color: var(--text);
  background: #1f2937;
  border: 1px solid var(--border);
  border-radius: 6px;
}

.settings-button {
  min-height: 30px;
  padding: 4px 10px;
  color: var(--text);
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
  window-drag: none;
}

.page-content {
  padding: 24px;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

In this example, the remaining empty area of .app-titlebar is the drag region. The logo, search label, input field, and button are marked none so users can select, type in, or press them instead of accidentally moving the window.

Leave a safe area for the window controls

Window Controls Overlay places web content in the area normally occupied by the title bar, but the minimize, maximize, and close buttons are still rendered by the operating system. The position of this area varies with the operating system, interface direction, display scale, and window size. The variables titlebar-area-x, titlebar-area-y, titlebar-area-width and titlebar-area-height describe the rectangle of the available title-bar area; do not mechanically interpret them as the same left and right padding (according to developer.mozilla.org).

You can use env() to create the initial inset. Place this after the previous CSS rule:

.app-titlebar {
  padding-block-start: env(titlebar-area-y, 0px);
}

.titlebar-content {
  min-height: max(
    var(--titlebar-height),
    env(titlebar-area-height, var(--titlebar-height))
  );
  padding-inline-start: max(
    12px,
    env(titlebar-area-x, 0px)
  );
  padding-inline-end: max(
    12px,
    calc(
      100% - env(titlebar-area-x, 0px) -
      env(titlebar-area-width, 100%)
    )
  );
}

This is a starting configuration, not a fixed spacing value that is correct for every design. If the title bar has a complex layout, read its actual rectangle through the API and update the application's CSS variable after the overlay geometry changes. The env() function needs a fallback value so the interface remains usable when the browser does not provide the environment variable (see developer.mozilla.org).

Detect the display mode and update the geometry with JavaScript

Detect the display mode and update the geometry with JavaScript

Do not use the User-Agent to determine whether the application is running as a PWA. Place the following code in a JavaScript file loaded after the document has document.documentElement. The code only updates the interface state and logs diagnostic information; the application's core functionality must not depend on this API:

const standaloneQuery = window.matchMedia(
  '(display-mode: standalone)'
);

function updateWindowMode() {
  const overlay = navigator.windowControlsOverlay;
  const isStandalone = standaloneQuery.matches;
  const isOverlayVisible = Boolean(overlay?.visible);

  document.documentElement.dataset.pwa =
    isStandalone ? 'true' : 'false';

  document.documentElement.dataset.titlebarOverlay =
    isOverlayVisible ? 'true' : 'false';

  if (overlay) {
    const rect = overlay.getTitlebarAreaRect();
    console.debug('Title bar area:', {
      x: rect.x,
      y: rect.y,
      width: rect.width,
      height: rect.height
    });
  }
}

updateWindowMode();

if (navigator.windowControlsOverlay) {
  navigator.windowControlsOverlay.addEventListener(
    'geometrychange',
    updateWindowMode
  );
}

standaloneQuery.addEventListener('change', updateWindowMode);

When running in a tab, isStandalone is usually false; when opened from the launcher as a PWA, this state may change to true. If navigator.windowControlsOverlay does not exist, keep the title bar as ordinary HTML instead of trying to simulate window dragging with JavaScript.

Install and verify in the correct order

  1. Serve the application: start the project's development server or HTTPS server. Open the correct application URL in Chrome 152 on a desktop computer.
  2. Check the manifest: in DevTools, open the Application panel and check the manifest, display_override, display, icons, and paths. Fix any JSON errors or file-loading errors before continuing.
  3. Install the PWA: use Chrome's PWA installation button, not merely a pinned tab. If the application was installed previously, close the application window, reload the manifest, and reinstall it when necessary to test the changes.
  4. Open the correct application: close the original tab, then open the PWA from the operating system's shortcut or launcher.
  5. Check the draggable area: click and drag an empty part of .app-titlebar. The expected result is that the PWA window moves with the mouse.
  6. Check excluded areas: click the Settingsbutton, place the pointer in the search field, enter text, and try selecting text. These actions must take place within the page rather than dragging the window.
  7. Check the system area: resize the window, try the maximized state, and inspect the area near the system buttons. The logo, title, and application buttons must not be obscured.
  8. Check the fallback: open the same URL in a regular tab or an environment without Window Controls Overlay. The content must remain readable, the controls must remain usable, and the header must not appear to be a window-drag area.

If the first check does not move the window, do not adjust colors or dimensions first. Determine whether the application is actually installed, whether the manifest was reloaded, and whether the API is present.

Troubleshoot by symptom

The title bar does not drag

  • Check that you are opening the installed PWA window, not the URL in a tab.
  • Check that the manifest contains exactly window-controls-overlay, includes a standalone fallback, and is linked from the current page.
  • Check that DevTools reports no CSS syntax errors or stylesheet-loading errors.
  • Check that the area intended for dragging is not covered by another element and that window-drag: none has not been applied unintentionally.
  • Check whether the browser provides navigator.windowControlsOverlay and the appropriate display state. If not, the inability to drag may be the correct fallback behavior rather than a CSS error.

A button or input field is dragged instead of responding to interaction

Set window-drag: none directly on interactive elements. For a title bar with multiple types of controls, you can add the following rule:

.titlebar-content button,
.titlebar-content input,
.titlebar-content select,
.titlebar-content textarea,
.titlebar-content a,
.titlebar-content label {
  window-drag: none;
}

Do not exclude only the button while overlooking the label surrounding the input field or an element overlaying the control. After updating the CSS, reload the PWA window and test both mouse and keyboard interaction.

Content is obscured by the close or maximize button

Do not position a logo or application button in the top corner without accounting for the title bar rectangle. Check the value of rect logged in the Console, compare it with the content's actual position, and adjust the inset. If the layout uses RTL or multiple displays, also check the actual text direction and display scale.

Works in Chrome 152 but not in another browser

Do not assume that every browser supports the same property or API. The following fallback disables the draggable area when the property is not recognized and disables the inset reserved for the overlay when the overlay state is false:

@supports not (window-drag: move) {
  .app-titlebar {
    window-drag: none;
  }
}

html[data-titlebar-overlay="false"] .app-titlebar {
  padding-block-start: 0;
}

Do not use Pointer Events to simulate window movement. That approach moves content within the viewport; it does not move the operating-system window.

Usability, security, and fallback

  • Keep the app name, origin identity, and navigation clear; an interface with almost no system title bar may make it difficult for users to distinguish the web content area from the window area.
  • Do not turn the entire screen into a drag region. Users must still be able to select text, scroll through content, and operate the app with the keyboard.
  • Ensure that every button and input field has an appropriate label, keyboard order, and focus state.
  • Test maximized and minimized states, multiple displays, high display scaling, and right-to-left (RTL) layouts if the app supports these scenarios.
  • Keep Window Controls Overlay only when the benefits of a custom title bar justify testing it across the target operating systems and browsers.

If the feature causes problems or becomes difficult to maintain, the safe fallback is to remove window-controls-overlay from display_overrideretain display: "standalone" and set window-drag: none for the title bar. The app can still run as a standalone PWA with its normal HTML structure and controls.

You can consider the implementation complete when all four conditions are met: the PWA is installed on the desktop; the empty title-bar area can move the window; buttons and input fields still work; and content is not obscured by the system controls area. If any condition is missing, go back and check the manifest, installation status, element overlay, and the rules window-drag: none.

Reference source

  • Chrome 152 | Release notes | Chrome for Developers
  • Chrome 152 Release Notes – Chrome Platform Status
  • Window Controls Overlay API – Web APIs | MDN
  • env() CSS function – CSS | MDN
  • Window Controls Overlay

Chú thích cho quảng cáo
Chrome 152 CSS desktop web applications PWA Window Controls Overlay window-drag
Share. Facebook Twitter Pinterest LinkedIn Tumblr Email
Previous ArticleDesigning a Malware Package Advisory Pipeline You Can Roll Back
Next Article Move XSLT out of the browser before Chrome 158 ends support
Nuj Coom
  • Website
  • Facebook
  • X (Twitter)
  • Instagram

I'm a doctor, for sure. But I also love writing and sharing knowledge, life experiences, web tricks, and useful lectures. Let's cheer for your passion.

Related Posts

CPU Performance API: Make Web Interfaces Lighter for Low-End Devices

13/09/2026

Designing a Malware Package Advisory Pipeline You Can Roll Back

13/09/2026

How to Keep CI/CD Running Through a GitHub Actions Outage

13/09/2026
Add A Comment
Leave A Reply Cancel Reply

Latest posts

How to Use ChatGPT: Features, Customization and ChatGPT Plus

What’s new in WordPress 7.1? A checklist for safe use

Strengthen Your Core with 12 Exercises from Beginner to Advanced

Passkeys in 2026: Create, Sync, and Recover After Losing a Device

15 of the World’s Most Popular Celebrities of All Time

Advertisement
Chú thích cho quảng cáo

SUBSCRIBE TO UPDATES

Get the latest creative news from SaibABC.Com on web tips, design, and business.

Copyright © 2024. Designed by NujCoom.
  • Home
  • Contact
  • Privacy
  • Tiếng Việt
  • Hmoob

Type above and press Enter to search. Press Esc to cancel.