skip to content

In Flutter, what does setting debugPaintSizeEnabled to true draw on screen, and how do you switch it on during a debug session?

level: middleimportance: should knowfreq 40%

answer

  1. top-level bool in the rendering library
  2. defaults to false
  3. outlines every RenderBox
  4. padding and alignment get their own marks
  5. p key, or Show guidelines

basics

~20 s

debugPaintSizeEnabled, a top-level bool in package:flutter/rendering.dart that defaults to false, makes every RenderBox paint its bounds, with padding shaded and alignment offsets drawn as arrows. Set it before runApp, press p in flutter run, or use the inspector's Show guidelines.

solid answer

~40 s

`debugPaintSizeEnabled` is a top-level `bool` in `package:flutter/rendering.dart`, `false` by default. When it is `true`, every `RenderBox` paints a thin cyan outline of its bounds; `RenderPadding` shades its padding in blue, `Align` and `Center` draw yellow arrows for the child's offset, and empty spacers show grey. The check runs inside an `assert`, so it only has an effect in debug builds. I turn it on by assigning it in `main()` before `runApp`, by pressing `p` in the `flutter run` terminal ("Toggle the display of construction lines"), or with **Show guidelines** in the DevTools inspector; the last two go through a service extension that also forces a repaint.

code

dart · 19 lines
dart
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

void main() {
  // Read inside an assert: debug builds paint the lines, release builds ignore it.
  debugPaintSizeEnabled = true;
  runApp(
    const MaterialApp(
      home: Scaffold(
        body: Center(
          child: Padding(
            padding: EdgeInsets.all(24),
            child: Text('Guidelines on'),
          ),
        ),
      ),
    ),
  );
}

go deeper

for a junior

Remember the name, that it is a global bool in the rendering library defaulting to false, and the quick toggles: p in flutter run and Show guidelines in DevTools.

for a middle

Explain what each mark means (outline, padding fill, alignment arrows, spacer), why it is debug-only (read inside an assert) and why a runtime assignment needs a repaint.

for a senior

Show how you combine it with Select Widget Mode to tell padding, alignment and oversized boxes apart quickly, and pick the related flag (baselines, pointers, layers) that fits the symptom.

for a principal

Treat visual debug flags as team tooling: a debug-only settings panel or launch configuration that toggles them, so layout reviews stay fast and nothing leaks into release.

## What the flag is `debugPaintSizeEnabled` is a **global debug flag** declared as a top-level variable in Flutter's rendering library (`package:flutter/rendering.dart`). Its default is `false`. When you set it to `true`, the framework adds **construction lines** on top of the normal paint so you can see how big each box is and where the space between boxes comes from. The DevTools inspector exposes the same switch as **Show guidelines**, and the `flutter run` terminal exposes it as the `p` key. ## What it draws | Render object | Mark | Colour in the source | |---|---|---| | every `RenderBox` | a one-pixel outline of its bounds | cyan (`0xFF00FFFF`) | | `RenderPadding` (the `Padding` widget) | a translucent fill for the padding, with the inner edge outlined | blue (`0x900090FF`) | | `RenderPositionedBox` (`Align`, `Center`) | arrows showing the child's offset inside the parent | yellow (`0xFFFFFF00`) | | a spacer with no child | a solid translucent area | grey (`0x90909090`) | Scroll views and clips also get marks in the inspector's guideline mode (green arrows for scrolling content, a dashed pink line for a clip), which helps when a gap is really a clip or scroll edge. The result is that every rectangle on the screen becomes visible, so a mysterious gap resolves into either a padding fill, an alignment arrow or an outlined box that is bigger than its content. ## Why it is debug-only The painting happens in `RenderBox.debugPaint`, and the flag is read inside an `assert(() { ... }())` block. Release builds strip asserts, so setting the flag in a release build has no visible effect. Treat it as a development switch, never as something to ship. ## Three ways to switch it on 1. **In code.** Import `package:flutter/rendering.dart` and assign `debugPaintSizeEnabled = true;` at the top of `main()` before `runApp`. Every frame after that paints the lines. 2. **From the terminal.** In a `flutter run` session, press `p`; the tool's help text calls it "Toggle the display of construction lines." 3. **From DevTools.** Click **Show guidelines** in the Flutter inspector toolbar. Options 2 and 3 call a service extension that flips the flag and then **forces a repaint**, which is why the lines appear immediately. If you flip the variable yourself in the middle of a running app, nothing changes until something repaints, so the code route is best used from `main()`. ## Related flags in the same library - `debugPaintBaselinesEnabled` draws text baselines, green for alphabetic and yellow or orange for ideographic, to check text alignment. - `debugPaintPointersEnabled` highlights objects that receive a tap, which helps when a widget fails to hit-test. - `debugPaintLayerBordersEnabled` outlines compositing layers in orange. - `debugRepaintRainbowEnabled` recolours a layer each time it repaints; that one is a performance aid rather than a layout aid. All of them default to `false`, and all of them are checked inside asserts. ## How to use it well - Turn it on, then use the inspector's **Select Widget Mode** to name the box you are looking at; the lines tell you *where* space is, the inspector tells you *which widget* owns it. - Use it to separate three look-alike causes of a gap: padding (blue fill), alignment inside a larger parent (yellow arrows) and an oversized box (cyan outline far bigger than its content). - Turn it off before taking screenshots or recording golden images.

  • You set debugPaintSizeEnabled = true inside a button handler in a running Flutter app and nothing changes; why?
    The flag is only read while painting, and flipping a global variable does not schedule a frame. Until something repaints, the old frame stays on screen. The `p` key and Show guidelines go through a service extension that sets the flag and then forces a repaint, which is why they take effect immediately.
  • How does Flutter's debugPaintBaselinesEnabled differ from debugPaintSizeEnabled?
    `debugPaintBaselinesEnabled` draws a line at each text baseline of every render box that has one, green for alphabetic and yellow or orange for ideographic, to check vertical text alignment. `debugPaintSizeEnabled` draws box bounds, padding and alignment offsets. Both are debug-only flags in the rendering library and default to false.

saying these in an interview costs you the question

  • debugPaintSizeEnabled also draws its outlines in release builds if you forget to reset it.
  • debugPaintSizeEnabled lives in the widgets library and is set per widget as a parameter.
  • debugPaintSizeEnabled defaults to true in debug mode.
  • The outlines show only widgets you wrote, not framework render boxes.
  • Assigning the flag at runtime always repaints the screen instantly.