[TextField] Lift hardcoded padding and `InputLabel` transform values into theme tokens for customization
@siriwatknp is already working on this.
Since Jun 9, 2026.
- Dominant language
- JavaScript
- Stars
- 99.1k
- Forks
- 32.5k
- Avg merge
- 2d 17h
- Merged PRs (30d)
- 106
Description
Summary
The TextField / OutlinedInput / Input components have several spacing values written as literal numbers inside their styled() definitions, rather than being exposed as theme tokens. The same is true of InputLabel, whose transform: translate(x, y) values are implicitly coupled to the input's padding but are themselves hardcoded in a separate file.
In OutlinedInput.js the relevant literals include:
paddingLeft: 14(whenstartAdornmentis present)paddingRight: 14(whenendAdornmentis present)padding: '16.5px 14px'(multiline, default)padding: '8.5px 14px'(multiline,size="small")padding: '16.5px 14px'/padding: '8.5px 14px'onOutlinedInputInput
In InputLabel.js the matching label positions are also literal:
transform: 'translate(14px, 16px) scale(1)'(outlined, default)transform: 'translate(14px, 9px) scale(1)'(outlined, small)transform: 'translate(14px, -9px) scale(0.75)'(outlined, shrink)transform: 'translate(12px, 16px) scale(1)'(filled, default), and corresponding small/shrink variantsmaxWidth: 'calc(100% - 24px)',maxWidth: 'calc(133% - 32px)'(outlined)
The horizontal 14px translate in the outlined InputLabel only aligns with the field because it happens to match the 14px horizontal padding of OutlinedInput. The two files maintain this contract by hand, and the constants 24px / 32px / 133% further depend on it.
I'd like these spacing values to be lifted into the theme so that they're a public, documented surface — ideally so that overriding the input's horizontal padding automatically propagates to the label's transform.
Internally OutlinedInput would derive its padding from those tokens, and InputLabel would derive the X component of its translate from the same paddingX (and the Y component from paddingY plus the label's font metrics). Today both numbers are written by hand in two files.
The same pattern repeats in FilledInput.js (e.g. padding: '25px 12px 8px', padding: '21px 12px 4px' for small, plus adornment-specific overrides) and to a lesser extent in Input.js and InputBase.js. Each file maintains its own set of literals that need to stay coordinated with InputLabel's filled / standard transform blocks, so the problem is structural across the input family rather than specific to OutlinedInput. Note that startAdornment / endAdornment introduce yet another layer: they don't tweak the existing padding token, they overwrite it with their own hardcoded 14px, so any override has to be re-applied conditionally for the adornment case.
I'm aware styleOverrides lets you reach these styles in principle, so this isn't strictly "impossible". But because the values live inside variants: blocks, are spread across two component slots and two files, and are tied together by an undocumented contract, doing it correctly requires re-deriving every magic number by hand.
Examples
The minimal failure case: override OutlinedInput to use a non-default horizontal padding, e.g.
MuiOutlinedInput: {
styleOverrides: {
root: { '& .MuiOutlinedInput-input': { padding: '10px 10px' } },
},
},
Now the shrunk InputLabel floats at translate(14px, -9px) while the notched outline cutout starts at 10px from the left — the label sits inside-but-misaligned. To fix it you have to additionally override MuiInputLabel.styleOverrides.outlined with a hand-computed transform, and repeat the exercise for size="small" and the shrink state.
Material Design's own text-field spec defines internal spacing semantically (edge insets, baseline alignment) rather than as fixed pixels, so making these configurable is, if anything, closer to the spec than the current hardcoded numbers.
Motivation
The built-in size: 'small' | 'medium' only gives two discrete density steps. Real-world design systems built on top of Material UI commonly need:
- Redefining the default
mediumandsmallthemselves, not just adding extra steps — so that the baseline<TextField />already matches the host design system without consumers having to opt into a custom size everywhere. - Adding further density steps (e.g. "compact" or "comfortable") beyond small/medium when needed.
- Slightly adjusted horizontal padding so text fields align with adjacent custom-sized buttons, selects, or chips.
- Density tweaks for CJK content, where body line-height and x-height differ enough from the Roboto-tuned defaults to make the stock paddings feel off.
Currently, achieving any of this means overriding MuiOutlinedInput.styleOverrides.root, MuiOutlinedInput.styleOverrides.input, and MuiInputLabel.styleOverrides.outlined in sync, and re-deriving every constant (16.5, 8.5, 14, 9, -9, 24, 32, 133%) by hand. None of these are documented as a public API, which means they could legitimately change between minor versions.
Promoting them to named theme tokens would:
- Reduce a multi-component override cascade to a single token change.
- Make the implicit input-padding <-> label-transform contract explicit and documented.
- Bring text-field density into line with the rest of MUI's theming surface (
shape,spacing,typography).
Search keywords: OutlinedInput padding hardcoded, InputLabel transform hardcoded, TextField density customization, InputLabel alignment, theme spacing tokens
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.