HandCursor for Flutter Web

Flutter logo and a hand cursor

Flutter released, some months ago, a Flutter for web implementation (currently available as a technical preview).

I'm quite new to the Dart programming language and to the entire Flutter way of doing things, but I started to like it.

In my exploration of its (current) web capabilities, I stumbled upon several issues, and one of the most visually annoying (in the web browser) is the lack of support for cursor customization.

For example, the classic hand cursor that pops up when we hover a button/link is missing. Without it, people are unable to make a difference between what is an actionable item or just a decorative one.

⚠ Starting with dev channel build version 1.19.0–3.0.pre there is built-in support for the pointer cursor. ⚠

A workaround for this is the following:

1. You have to set an id (for example app-container on the entire body of the app’s index.html template).

This is how your index.html will look like:

<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<title>Your awesome app</title>
<script defer src="main.dart.js" type="application/javascript"></script>
<body id="app-container">

2. Next, you have to create a wrapper dart class. I called it hand_cursor.dart:

import 'package:flutter_web/gestures.dart';
import 'package:flutter_web/widgets.dart';
import 'dart:html' as html;
class HandCursor extends Listener { static final appContainer = html.window.document.getElementById('app-container'); HandCursor({Widget child}) : super(
onPointerHover: (PointerHoverEvent evt) {
onPointerExit: (PointerExitEvent evt) {
child: child

The code is quite simple: we extend the Listener class and capture a reference to the appContainer (the HTML body element we just set the app-container id on); then we make sure to listen to the hover/exit events and change the cursor's style accordingly (pointer/default) and pass on the child.

As a choice of cursor styles there are plenty: help, wait, move, crosshair, text or, the one we just used, pointer. More choices and details on this can be found here.

3. After that, wherever you want to have the hand cursor shown, you have to wrap your element in this HandCursor wrapper.

See the awesome_button.dart class bellow:

import 'package:awesome_app/widgets/containers/hand_cursor.dart';
import 'package:flutter_web/material.dart';
import 'package:flutter_web/widgets.dart';
class AwesomeButton extends StatelessWidget { @override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
child: IconButton(
onPressed: () {
// let others know
// you can
// do some magic
icon: Icon(Icons.star)

Next possible steps would be to style the cursor only in non mobile web browsers and to customize the Cursor via a parameter (the default one being pointer). That would mean a refactoring of the current class and maybe a new name: CustomCursor

Tha(nk|t’)s all!




Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Benefits of Migrating Your Business to the Cloud

Git: Basic Terms and Commands quick guide-Beginner-friendly

AWS Scaling Horizontally vs Vertically

I was thinking NGINX was the best until i knew OPENRESTY

How to monitor AWS EC2 PPS allowance limits

Dockerizing Strapi (v4) and CI/CD Setup with Gitlab (Part 1)

READ/DOWNLOAD=< Dependency Injection Principles, P

Using Firebase Analytics with Expo

Firebase Analytics dashboard

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Constantin Stan

Constantin Stan

More from Medium

How to Speed Up UI Development with KnowCode for Flutter

Localizing Flutter Packages

History Of Flutter

Briefly Explanied — How Flutter framework optimizes widget rendering?