diff --git a/src/controllers.jl b/src/controllers.jl
index 1f2671f96bb57443bb159ffb8c050d9608bc55bd..777a04ee555b92863efd4211985c78ddd556d5f2 100644
--- a/src/controllers.jl
+++ b/src/controllers.jl
@@ -269,17 +269,33 @@ end
 
 #
 
-function computebbox(data; resolution=1)
+function computebbox(data; resolution=1, ratio=nothing)
     bb = Meshes.boundingbox(data)
     xy0 = coordinates(minimum(bb))
     x0, y0 = @. floor(xy0 / resolution - 0.1) * resolution
     xy1 = coordinates(maximum(bb))
     x1, y1 = @. ceil(xy1 / resolution + 0.1) * resolution
+    if !isnothing(ratio)
+        width = x1 - x0
+        height = y1 - y0
+        if width / height < ratio
+            # enlarge width
+            width′= height * ratio
+            x0 -= (width′- width) / 2
+            x1 = x0 + width′
+        else
+            # enlarge height
+            height′= width / ratio
+            y0 -= (height′- height) / 2
+            y1 = y0 + height′
+        end
+    end
     return (x0, x1, y0, y1)
 end
 
 function setbounds!(view::Axis, ctrl::Union{LarvaController, ControllerHub}, data)
-    bbox = computebbox(data; resolution=10)
+    # ratio should match size of AssayPlot and TrackPlot in wgl.jl
+    bbox = computebbox(data; resolution=10, ratio=FIGSIZE[1] / FIGSIZE[2])
     setboundingbox!(ctrl, bbox)
     limits!(view, bbox...)
 end
diff --git a/src/plots.jl b/src/plots.jl
index a424f665cdc49a2c8e62fca334b9cc182bb21b14..bdee891a3c0664d8edfd3d6df6963387f0bfe97d 100644
--- a/src/plots.jl
+++ b/src/plots.jl
@@ -597,3 +597,28 @@ function setmouseevents!(scene, plot::DecoratedLarvae, ctrl; consume=false)
         return Consume(consumed)
     end
 end
+
+const FIGSIZE = (1000, 750)
+
+function autosize!(axis, size)
+    target_ratio = Float32(size[1] / size[2])
+    on(axis.targetlimits) do limits
+        width, height = limits.widths
+        ratio = width / height
+        if 1e-3 <= abs(ratio - target_ratio)
+            # enlarge the shortest dimension at constant aspect ratio to approach the target
+            # width/height ratio
+            x0, y0 = limits.origin
+            if ratio < target_ratio
+                width′= height * target_ratio
+                origin = [x0 - (width′- width) / 2, y0]
+                widths = [width′, height]
+            else#if target_ratio < ratio
+                height′= width / target_ratio
+                origin = [x0, y0 - (height′- height) / 2]
+                widths = [width, height′]
+            end
+            axis.targetlimits[] = typeof(limits)(origin, widths)
+        end
+    end
+end
diff --git a/src/wgl.jl b/src/wgl.jl
index 264b3e1b04a57c8f8a88b5b2bfc44b975576742a..b770297d8e5b96c369d29afd65ebb375e4af21f5 100644
--- a/src/wgl.jl
+++ b/src/wgl.jl
@@ -101,7 +101,7 @@ function homebutton(kwargs...)
     simpletrigger(HomeButton,
                   with_attributes(kwargs;
                                   class=css_button,
-                                  style="position:absolute;top:15px;right:40px;"))
+                                  style="position:absolute;top:25px;right:30px;"))
 end
 
 function JSServe.jsrender(session::Session, b::HomeButton)
@@ -117,9 +117,13 @@ struct AssayPlot
     homebutton::HomeButton
 end
 
-function AssayPlot(ctrl, larvae::DecoratedLarvae; size=(1000, 750))
+function AssayPlot(ctrl, larvae::DecoratedLarvae; size=FIGSIZE)
     fig = Figure(resolution=size)
-    ax = Axis(fig.layout[1, 1], aspect=DataAspect())
+    width = 0.1f0 # try to get 1px
+    color = RGBAf(0, 0, 0, 0.36)
+    ax = Axis(fig.layout[1, 1], aspect=DataAspect(), xgridwidth=width, ygridwidth=width,
+              xgridcolor=color, ygridcolor=color)
+    autosize!(ax, size)
     larvaplot!(ax, larvae)
     setbounds!(ax, ctrl, larvae)
     button = homebutton()
@@ -175,10 +179,14 @@ struct TrackPlot
 end
 
 function TrackPlot(controller, larvae::Vector{LarvaModel};
-        size=(1000, 750), editabletags::Bool=true)
+        size=FIGSIZE, editabletags::Bool=true)
     view = SingleLarvaView(larvae, controller; editabletags=editabletags)
     fig = Figure(resolution=size)
-    ax = Axis(fig.layout[1, 1], aspect=DataAspect())
+    width = 0.1f0 # try to get 1px
+    color = RGBAf(0, 0, 0, 0.36)
+    ax = Axis(fig.layout[1, 1], aspect=DataAspect(), xgridwidth=width, ygridwidth=width,
+              xgridcolor=color, ygridcolor=color)
+    autosize!(ax, size)
     larvaplot!(ax, view)
     setbounds!(ax, controller, larvae)
     on(async_latest(getactivelarva(controller))) do id