Mantine's internal styling

case study: Mantine's implementation of Button

The Button source code includes the typescript file (Button.tsx) and the stylesheet (Button.module.css).

HTML element structure

There are several, nested elements:

  • the root button is the top level container.
  • the inner span is an intermediate container for the label and the sections
  • a section is a container for an icon.
  • the label span contains the button's text.
  • the loader span is an intermediate container for a loader.
/* root */
<button>
    {/* 1.0 loader container*/}
    <span />
    {/* 2.0 inner */}
    <span>
        {/* 2.1 section  */}
        <span>
            <svg /> {/* 2.1.0 icon */}
        </span>
        {/* 2.2 label  */}
        <span>{/* 2.2.0 text */}</span>
    </span>
</button>

Both the mantine-implemented internal classes and empty classes are present, on each inner-element:

<button class="m-77c9d27d mantine-Button-root .." ..>
    <span class="m-80f1301b mantine-Button-inner">
        <span class="m-811560b9 mantine-Button-label">
          Save
      </span>
    </span>
</button>

some inner-elements have some data-attributes, which may be shared across inner-elements of distinct components, such as the mantine-active and mantine-focus-auto attributes.

For example, mantine-active allows to receive style that activates when the element is active. The attribute is always there, and the stylesheet discriminates to the :active state.

mantine-active:active {
    transform: translateY(calc(0.0625rem));
}

Button's stylesheet

The stylesheet is a CSS module and follows the pattern where classes are named after inner-elements of the Button component. We reproduce parts of the root class.

The .tsx file imports the CSS module.

style shipped on npm

the style is mostly the same. It is probably processed by PostCSS. It does not use CSS nesting.

It is then processed even more and merged to a gigantic 232kb stylesheet, shipped on npm too, the one we import from our app.

earlymorning logo

© Antoine Weber 2026 - All rights reserved

Mantine's internal styling

case study: Mantine's implementation of Button

The Button source code includes the typescript file (Button.tsx) and the stylesheet (Button.module.css).

HTML element structure

There are several, nested elements:

  • the root button is the top level container.
  • the inner span is an intermediate container for the label and the sections
  • a section is a container for an icon.
  • the label span contains the button's text.
  • the loader span is an intermediate container for a loader.
/* root */
<button>
    {/* 1.0 loader container*/}
    <span />
    {/* 2.0 inner */}
    <span>
        {/* 2.1 section  */}
        <span>
            <svg /> {/* 2.1.0 icon */}
        </span>
        {/* 2.2 label  */}
        <span>{/* 2.2.0 text */}</span>
    </span>
</button>

Both the mantine-implemented internal classes and empty classes are present, on each inner-element:

<button class="m-77c9d27d mantine-Button-root .." ..>
    <span class="m-80f1301b mantine-Button-inner">
        <span class="m-811560b9 mantine-Button-label">
          Save
      </span>
    </span>
</button>

some inner-elements have some data-attributes, which may be shared across inner-elements of distinct components, such as the mantine-active and mantine-focus-auto attributes.

For example, mantine-active allows to receive style that activates when the element is active. The attribute is always there, and the stylesheet discriminates to the :active state.

mantine-active:active {
    transform: translateY(calc(0.0625rem));
}

Button's stylesheet

The stylesheet is a CSS module and follows the pattern where classes are named after inner-elements of the Button component. We reproduce parts of the root class.

The .tsx file imports the CSS module.

style shipped on npm

the style is mostly the same. It is probably processed by PostCSS. It does not use CSS nesting.

It is then processed even more and merged to a gigantic 232kb stylesheet, shipped on npm too, the one we import from our app.