Open In App

Frameless Window in ElectronJS

Improve
Improve
Like Article
Like
Save
Share
Report

ElectronJS is an Open Source Framework used for building Cross-Platform native desktop applications using web technologies such as HTML, CSS, and JavaScript which are capable of running on Windows, macOS, and Linux operating systems. It combines the Chromium engine and NodeJS into a Single Runtime.

In a complex desktop application, a situation might occur wherein the developers may have to carry out additional background processes and computational tasks in parallel frames without interrupting the user experience. These background processes running within parallel frames should not be visible to the user as additional GUI windows but should be activated accordingly whenever the need arises. We can see this behavior in many modern desktop applications such as the Google Chrome web browser. Additionally, the developers might want to restrict the user to a specific frame with limited functionality such as when displaying a License Agreement or Terms & Conditions window. In such windows, the Title Bar, Navigational Bar, and Context Menus are disabled and the user should not be able to close/skip/minimize the window frame. Electron provides us with a way by which we can open a window without toolbars, borders, or any other graphical components or make the entire window transparent using the properties in options of a new BrowserWindow object. Such windows are known as Frameless windows in Electron. This tutorial will demonstrate how to create and feature of a Frameless window in Electron. 

We assume that you are familiar with the prerequisites as covered in the above-mentioned link. For Electron to work, node and npm need to be pre-installed in the system.

Project Structure: 

Project Structure
Example: Follow the Steps given in Dynamic Styling in ElectronJS to set up the basic Electron Application. Copy the Boilerplate code for the main.js file and the index.html file as provided in the article. Also, perform the necessary changes mentioned for the package.json file to launch the Electron Application. We will continue building our application using the same code base. The basic steps required to set up the Electron application remain the same.

package.json: 

{
  "name": "electron-frameless",
  "version": "1.0.0",
  "description": "Frameless Window in Electron",
  "main": "main.js",
  "scripts": {
    "start": "electron ."
  },
  "keywords": [
    "electron"
  ],
  "author": "Radhesh Khanna",
  "license": "ISC",
  "dependencies": {
    "electron": "^8.3.0"
  }
}

Output: 

Frameless Window in Electron: The BrowserWindow Instance is part of the Main Process. To import and use BrowserWindow in the Renderer Process, we will be using Electron remote module.  A frameless window is a window that has no chrome. Chrome is any visible aspect of a window aside from the webpages themselves (e.g., toolbars, menu bar, borders, etc). We can define a BrowserWindow Instance as a Frameless or a Transparent window by specifying the properties of the BrowserWindow object. 

index.html: Add the following snippet in that file.

html




<body style="-webkit-app-region: drag">
    <h3>Frameless Window in Electron</h3>
    <button id="frame" style="-webkit-app-region: no-drag;">
        Create a Frameless Window
    </button>
    <br><br>
    <button id="frameless" style="-webkit-app-region: no-drag;">
        Create a Frameless Draggable Window
    </button>
    <br><br>
    <!-- Adding Individual Renderer Process JS File -->
    <script src="index.js"></script>
</body>


index.js: The Create a Frameless Window and Create a Frameless Draggable Window buttons do not have any functionality associated with them yet. To change this, add the following code in the  index.js file.

javascript




const electron = require('electron')
// Import BrowserWindow using Electron remote
const BrowserWindow = electron.remote.BrowserWindow;
// let win = BrowserWindow.getAllWindows()[0];
 
let frame = document.getElementById('frame');
frame.addEventListener('click', (event) => {
    const win = new BrowserWindow({
        width: 800,
        height: 600,
        // Creating a Frameless Window
        frame: false,
        webPreferences: {
            nodeIntegration: true
        }
    });
    win.loadURL('https://www.google.com/');
});
 
let frameless = document.getElementById('frameless');
frameless.addEventListener('click', (event) => {
    const win = new BrowserWindow({
        width: 800,
        height: 600,
        frame: false,
        webPreferences: {
            nodeIntegration: true
        }
    });
    win.loadFile('src/index.html');
    win.show();
});


To create a Frameless window in Electron, the frame: false property is set in the options of the BrowserWindow Instance. By setting this property, only the webpage itself will be visible to the user without any additional Chrome or GUI components. Refer to the output for a better understanding. By default, the frameless window is non-draggable. Applications need to specify the -webkit-app-region: drag CSS property to tell Electron which regions are draggable. To make the whole window draggable, this CSS property is set to the style of the body tag in HTML. Applications can also use -webkit-app-region: no-drag CSS property to indicate the non-draggable area. Once we have defined a frameless window, we can customize it to our look and feel and provide a custom titlebar along with custom window controls. 
Note – When the -webkit-app-region: drag CSS property is set to the body tag, we need to set -webkit-app-region: no-drag CSS property to the Buttons or any clickable components within the window. Else, we will not be able to click on those clickable components. 

Note: Sometimes in Frameless windows, the dragging behavior may conflict with the text selection. For example, when dragging a window via the title bar, we may accidentally select the text on the title bar. This occurs when the size of the custom title bar is especially small. To prevent this we need to disable the text selection by using the -webkit-user-select: none; CSS property. 

Note: As of v8.3.0 of Electron, only rectangular shapes are currently supported for draggable regions. Also, -webkit-app-region: drag CSS property is known to have problems while the Chrome Dev tools are open. 
Note – In some environments, the draggable region within a window can be treated as a non-client frame. This means that whenever we right-click on the draggable region, the system context menu may open. To make the context menu behave correctly, we should never use a custom context menu on draggable regions. 

The frame: false property of the BrowserWindow Instance is supported on all OS platforms. Additionally, in macOS, we have some more properties to define chromeless windows instead of the frame property. If we use the frame property in macOS, it disables the titlebar and the windows controls (a.k.a traffic lights in macOS). Instead, we can use the titleBarStyle property in the options of the BrowserWindow Instance to hide the titlebar and make the content extend the entire window size while still preserving the window controls. 

  • titleBarStyle: ‘hidden’ This property hides the titlebar, makes the content extend the full size of the window, yet still displays the windows controls in the top-left corner of the chromeless window.
  • titleBarStyle: ‘hiddenInset’ This property hides the titlebar but provides an alternative look wherein the windows controls are slightly more inset from the edge of the chromeless window.
  • titleBarStyle: ‘customButtonsOnHover’ This property uses miniature buttons as window controls and displays a custom drawer on hover near the top-left of the chromeless window. This property can only be used together with the frame: false property.

At this point, upon launching the Electron application, we should be able to activate a Frameless window and a Frameless draggable window in the application. In this tutorial, we have loaded an external website in the frameless window and the index.html file once again in the frameless draggable window respectively for demonstration purposes. 

Output: 

index.html: Now we will see how to make a frameless window completely transparent in the application and see some of the features and limitations of a Transparent window in Electron.

html




<body style="-webkit-app-region: drag">
    <h3>Frameless Window in Electron</h3>
    <button id="transparent" style="-webkit-app-region: no-drag;">
        Create a Frameless Transparent Window
    </button>
    <!-- Adding Individual Renderer Process JS File -->
    <script src="index.js"></script>
</body>


index.js: The Create a Frameless Transparent Window button does not have any functionality associated with it yet. To change this, add the following code in the index.js file.

javascript




const electron = require('electron')
// Import BrowserWindow using Electron remote
const BrowserWindow = electron.remote.BrowserWindow;
// let win = BrowserWindow.getAllWindows()[0];
 
let transparent = document.getElementById('transparent');
transparent.addEventListener('click', (event) => {
    const win = new BrowserWindow({
        width: 800,
        height: 600,
        frame: false,
        webPreferences: {
            nodeIntegration: true
        },
        transparent: true,
    });
    win.show();
});


Explanation: To create a Transparent window in Electron, the transparent: true property is set in the options of the BrowserWindow Instance. These transparent windows can be used for loading external scripts, perform background processes, and additional computation tasks. However, as of v8.3.0 of Electron, certain limitations are associated with transparent windows.  Some of the more important limitations are listed below: 

  • We cannot click through transparent windows.
  • Transparent windows are not resizable. Setting the resizable: true property in the options of the BrowserWindow Instance makes the transparent windows stop working on some OS environments.
  • We cannot apply the blur filter to the contents below the Transparent window since it can only be applied to the webpage itself and hence the contents below the transparent window will be clearly visible. As mentioned above, we will not be able to click through the transparent window as well. This has been demonstrated in the output as well. 

To get the current BrowserWindow Instance in the Renderer Process, we can use some Static Methods provided by the BrowserWindow object.

  • BrowserWindow.getAllWindows(): This method returns an Array of active/opened BrowserWindow Instances. In this application, we have only one active BrowserWindow Instance and it can be directly referred from the Array as shown in the code.
  • BrowserWindow.getFocusedWindow(): This method returns the BrowserWindow Instance which is focused on the Application. If no current BrowserWindow Instance is found, it returns null. In this application, we only have one active BrowserWindow Instance and it can be directly referred to using this method as shown in the code. 

At this point, upon launching the Electron application, we should be able to activate a Transparent window in the application. 

Output: 

Note: While creating Transparent windows, when we specify the transparent: true property in the options but also at the same time use the win.loadFile(filepath) or win.loadURL(url) Instance methods of the BrowserWindow object, the Instance methods take precedence, and the respective windows with the content are loaded into the application. However, in the case of the win.loadFile(filepath) Instance method, only the content of the file without any background is loaded into the application. This can also be used to enhance the GUI of the application. Refer to the Output below for a better understanding. 
Output: 



Last Updated : 05 Apr, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads