54

I want my app to have no title bar but still be closeable, draggable, minimizable, maximizable, and resizable like a regular window. I can do this in OS X since there is a [titleBarStyle] 1 option called hidden-inset that I can use but unfortunately, it's not available for Windows, which is the platform that I'm developing for. How would I go about doing something like this in Windows?

Example Above is an example of what I'm talking about.

Sundeep Pidugu
  • 2,377
  • 2
  • 21
  • 43
antonky
  • 768
  • 1
  • 8
  • 14

4 Answers4

103

Assuming you don't want window chrome, you can accomplish this by removing the frame around Electron and filling the rest in with html/css/js. I wrote an article that achieves what you are looking for on my blog here: http://mylifeforthecode.github.io/making-the-electron-shell-as-pretty-as-the-visual-studio-shell/. Code to get you started is also hosted here: https://github.com/srakowski/ElectronLikeVS

To summarize, you need to pass frame: false when you create the BrowserWindow:

mainWindow = new BrowserWindow({width: 800, height: 600, frame: false});

Then create and add control buttons for your title bar:

 <div id="title-bar">
      <div id="title">My Life For The Code</div>
      <div id="title-bar-btns">
           <button id="min-btn">-</button>
           <button id="max-btn">+</button>
           <button id="close-btn">x</button>
      </div>
 </div>

Bind in the max/min/close functions in js:

(function () {

      var remote = require('remote'); 
      var BrowserWindow = remote.require('browser-window'); 

     function init() { 
          document.getElementById("min-btn").addEventListener("click", function (e) {
               var window = BrowserWindow.getFocusedWindow();
               window.minimize(); 
          });

          document.getElementById("max-btn").addEventListener("click", function (e) {
               var window = BrowserWindow.getFocusedWindow(); 
               window.maximize(); 
          });

          document.getElementById("close-btn").addEventListener("click", function (e) {
               var window = BrowserWindow.getFocusedWindow();
               window.close();
          }); 
     }; 

     document.onreadystatechange = function () {
          if (document.readyState == "complete") {
               init(); 
          }
     };

})();

Styling the window can be tricky, but the key use to use special properties from webkit. Here is some minimal CSS:

body {
 padding: 0px;
 margin: 0px; 
}

#title-bar {
 -webkit-app-region: drag;
 height: 24px; 
 background-color: darkviolet;
 padding: none;
 margin: 0px; 
}

#title {
 position: fixed;
 top: 0px;
 left: 6px; 
}

#title-bar-btns {
 -webkit-app-region: no-drag;
 position: fixed;
 top: 0px;
 right: 6px;
}

Note that these are important:

-webkit-app-region: drag;
-webkit-app-region: no-drag;

-webkit-app-region: drag on your 'title bar' region will make it so that you can drag it around as is common with windows. The no-drag is applied to the buttons so that they do not cause dragging.

Shawn Rakowski
  • 5,644
  • 2
  • 27
  • 29
  • 1
    To toggle Maximize and Un-Maximize use: if(window.isMaximized()){ window.unmaximize(); }else{ theWindow.maximize(); } – Siddhartha Maji Dec 29 '18 at 20:52
  • 2
    First link is dead but accessible on wayback machine https://web.archive.org/web/20190817105708/http://mylifeforthecode.com/making-the-electron-shell-as-pretty-as-the-visual-studio-shell – Thomas Harris Feb 27 '20 at 13:38
  • This does not seem to work when `#title-bar-btns` is `float: right`. Do you have an idea why @ShawnRakowski? Linked question: https://stackoverflow.com/questions/65383156/electron-titlebar-floating-buttons-no-drag-not-working – Basj Dec 20 '20 at 18:53
  • @Basj I suspect, but haven't checked, that your #titlebar element is overlaying the buttons and intercepting events. Does it work if you re-order the elements such that #topright is below #titlebar in the DOM? e.g.
    _&square;X
    – Shawn Rakowski Dec 21 '20 at 20:05
34

I was inspired by Shawn's article and apps like Hyper Terminal to figure out how to exactly replicate the Windows 10 style look as a seamless title bar, and wrote this tutorial (please note: as of 2022 this tutorial is somewhat outdated in terms of Electron).

It includes a fix for the resizing issue Shawn mentioned, and also switches between the maximise and restore buttons, even when e.g. the window is maximised by dragging the it to the top of the screen.

Quick reference

  • Title bar height: 32px
  • Title bar title font-size: 12px
  • Window control buttons: 46px wide, 32px high
  • Window control button assets from font Segoe MDL2 Assets (docs here), size: 10px
  • Minimise: &#xE921;
  • Maximise: &#xE922;
  • Restore: &#xE923;
  • Close: &#xE8BB;
  • Window control button colours: varies between UWP apps, but seems to be
  • Dark mode apps (white window controls): #FFF
  • Light mode apps (black window controls): #171717
  • Close button colours
  • Hover (:hover): background #E81123, colour #FFF
  • Pressed (:active): background #F1707A, colour #000 or #171717

Note: in the tutorial I have switched to PNG icons with different sizes for pixel-perfect scaling, but I leave the Segoe MDL2 Assets font characters above as an alternative

binaryfunt
  • 6,401
  • 5
  • 37
  • 59
  • How does this interoperate with scaling? Do these values just get multiplied by the percent scaling normally? – ProgramGamer Jun 24 '19 at 13:07
  • 4
    @ProgramGamer I have tested this on a standard 100% scaled 1080p monitor and the 125% scaled 1080p screen of my Dell XPS 13 and the scaling is correct for both – binaryfunt Jun 28 '19 at 15:13
4

I use this in my apps:

const { remote } = require("electron");
var win = remote.BrowserWindow.getFocusedWindow();

var title = document.querySelector("title").innerHTML;
document.querySelector("#titleshown").innerHTML = title;

var minimize = document.querySelector("#minimize");
var maximize = document.querySelector("#maximize");
var quit = document.querySelector("#quit");

minimize.addEventListener("click", () => {
  win.minimize();
});

maximize.addEventListener("click", () => {
  win.setFullScreen(!win.isFullScreen());
});

quit.addEventListener("click", () => {
  win.close();
});

nav {
  display: block;
  width: 100%;
  height: 30px;
  background-color: #333333;
  -webkit-app-region: drag;
  -webkit-user-select: none;
  position: fixed;
  z-index: 1;
}

nav #titleshown {
  width: 30%;
  height: 100%;
  line-height: 30px;
  color: #f7f7f7;
  float: left;
  padding: 0 0 0 1em;
}

nav #buttons {
  float: right;
  width: 150px;
  height: 100%;
  line-height: 30px;
  background-color: #222222;
  -webkit-app-region: no-drag;
}

nav #buttons #minimize,
nav #buttons #maximize,
nav #buttons #quit {
  float: left;
  height: 100%;
  width: 33%;
  text-align: center;
  color: #f7f7f7;
  cursor: default;
}

nav #buttons #minimize:hover {
  background-color: #333333aa;
}
nav #buttons #maximize:hover {
  background-color: #333333aa;
}
nav #buttons #quit:hover {
  background-color: #ff0000dd;
}

main {
  padding-top: 30px;
  overflow: auto;
  height: calc(100vh - 30px);
  position: absolute;
  top: 30px;
  left: 0;
  padding: 0;
  width: 100%;
}
<html>
  <head>
      <meta charset="UTF-8">
      <title>Hello World!</title>
  </head>
  <body>
    <nav>
      <div id="titleshown"></div>
      <div id="buttons">
          <div id="minimize"><span>&dash;</span></div>
          <div id="maximize"><span>&square;</span></div>
          <div id="quit"><span>&times;</span></div>
      </div>
    </nav>
    <main>
      <div class="container">
          <h1>Hello World!</h1>
      </div>
    </main>
  </body>
</html>
shreyasm-dev
  • 2,711
  • 5
  • 16
  • 34
Amine Beihaqi
  • 177
  • 2
  • 8
  • It does not resemble the windows shell very much. It might look a lot better if you use the windows ui font – Luke Oct 13 '19 at 21:29
  • This is a great start if you need a frame-less window with a custom top bar that retains essential functionality. – Llama D'Attore Apr 09 '21 at 05:24
1

Ran into this problem and my solution was to keep the frame but set the title to blank i.e.

document.querySelector("title").innerHTML ="";

That solved my problem i.e. I got a window which can be closed, maximized or minimized without a title on it.

N.P
  • 245
  • 1
  • 12