
How to build Find-in-Page in Electron
In Chrome browser, we naturally use Cmd + F to call the Find-in-Page Popover. But unlike the built-in feature in Chrome, implementing this functionality in an Electron app requires manually invoking APIs.
The composition of Find-in-Page
As a useful feature in web browsers, Find-in-Page allows users to search for specific text within the current page. In this image shown below, we can see the ① is search input field, ② is the position of active match and the total match count, ③ is the previous match button, ④ is the next match button, ⑤ is the close button, ⑥ is the active match that can be switched from previous and next match buttons. Other yellow background highlights are the all search results.

Relevant APIs
In Electron's documentation, the following APIs are relevant for Find-in-Page functionality:
`webContents.findInPage(text, options)`
: Starts a Find-in-Page operation.`webContents.stopFindInPage(action)`
: Stops the Find-in-Page operation.

To retrieve the the position of active match and the total match count, we can listen to the `found-in-page`
event. The `activeMatchOrdinal`
property indicates the position of the active match, and the `matches`
property indicates the total number of matches found.

The layer of Find-in-Page Component
An original Electron APP includes main process, preload process and renderer process. When the main process is launched, you can use `BrowserWindow`
to create a window to load `index.html`
or a remote URL, this is the UI to display to users.
function createWindow(): void { // Create the browser window. mainWindow = new BrowserWindow({ width: 1280, height: 960, show: false, autoHideMenuBar: true, ...(process.platform === 'linux' ? { icon } : {}), webPreferences: { preload: join(__dirname, '../preload/index.js'), sandbox: false, contextIsolation: true, nodeIntegration: true } }) mainWindow.on('ready-to-show', () => { mainWindow?.show() }) mainWindow.webContents.setWindowOpenHandler((details) => { shell.openExternal(details.url) return { action: 'deny' } }) // HMR for renderer base on electron-vite cli. // Load the remote URL for development or the local html file for production. if (is.dev && process.env['ELECTRON_RENDERER_URL']) { mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL']) mainWindow.webContents.openDevTools({ mode: 'undocked' }) } else { mainWindow.loadFile(join(__dirname, '../renderer/index.html')) } }
But, if you create your Find-in-Page component in this `BrowserWindow`
instance, you will get wrong results. Because the `webContents.findInPage(text, options)`
search the entire page, including the Find-in-Page component itself. That means if your search query is `hello`
, the highlighted blocks not only include the text `hello`
in the main content of the page, but also include the text `hello`
in your search input element.
To avoid this issue, you can create a separate View instance for the Find-in-Page component. This way, the search will only target the main content of the page, excluding the Find-in-Page UI itself.

PREVIOUS POST
How to manually install Electron in your APP