dp and sp look almost identical — both are density-independent units, and at the default font size they produce exactly the same pixel count. The difference appears only when the user changes the system font size: sp follows it, dp does not. That one difference decides which unit belongs where.
The two formulas, side by side
Both units start from the reported density, the same number wm density prints and the find your DPI guide shows how to read. dp stops there:
px = dp × (dpi / 160)
sp adds one more factor — the user's font scale, the multiplier behind the system font-size setting:
px = sp × (dpi / 160) × fontScale
At the default font scale of 1.0 the two formulas agree, which is why 16 dp and 16 sp render identically on a fresh phone. Change the font size, and only the sp value moves. The full density side of the math is covered in the dp to px conversion guide.
Worked examples
Every row below is plain arithmetic from the formulas above — no device panel is involved, so the numbers hold for any screen at the stated density. Fractional results are what the renderer rounds when it draws; the table keeps one decimal so the scaling stays visible.
The rule of thumb
Use sp for text the user reads — body copy, labels, headings — because a user who enlarged the system font did so to read more comfortably, and text set in dp would ignore that choice. Use dp for everything that must keep its shape: button heights, icon sizes, padding, margins and layout widths. If a button's height were set in sp, enlarging the font would also enlarge the button and shift the whole layout; keeping it in dp means only the text inside grows.
One consequence to design for: text in sp can overflow a fixed-dp container. A label that fits at font scale 1.0 may wrap or clip at 1.3, as the 16 sp example above grows from 48 px to 62.4 px at 480 dpi. Layouts that must survive larger fonts need flexible heights or scrolling, not a hard-coded dp height matched to the default font size.
The one-line rule: dp keeps a layout the same physical size on every screen; sp does the same, and then also respects the user's font size. Text gets sp, structure gets dp.