Library / SDK
mblode/marx avatar
mblode/marx

Marx classless CSS: semantic HTML styling without utility classes

The classless CSS reset (perfect for Communists).

1,710 stars99 forksCSSMIT

At a glance

What is it?
Marx is a classless CSS framework that styles ordinary semantic HTML with one stylesheet. It suits small sites and static pages that value simple markup, but its zero-specificity element rules offer little control for interfaces requiring component-specific styling.
Who is it for?
Adopt Marx for a small site, prototype, documentation page, or static document whose presentation can safely follow HTML element semantics. Do not choose it when component-level variation, complex interaction states, or extensive responsive layout are central to the product.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 5 days ago.
What is it written in?
Mainly CSS, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Why Marx removes classes from HTML

Marx addresses a specific front-end constraint: how to give a page a coordinated visual design when adding framework classes to every element would make markup noisy and repetitive. The project targets developers who want ordinary semantic markup such as main, headings, paragraphs, forms, labels, inputs, and buttons to receive default styling. The README states that adding one stylesheet makes the page style itself, without class names, a configuration file, or a build step.

That approach is most natural for articles, documentation, small marketing pages, prototypes, and static sites whose layout follows document structure. It is a poorer match for application interfaces where the same semantic element must appear in several unrelated visual contexts. A product card button and a dialog button may both use button, but an element-only system cannot distinguish them through classes without moving the distinction into an attribute selector or another CSS convention.

Marx should therefore be read as a classless reset and baseline framework, not as a complete component library. It covers recognizable HTML elements, but the documentation does not describe cards, modal layouts, navigation behavior, grids, utility modifiers, or a JavaScript component system. Projects that need those structures will still need their own CSS.

How element selectors produce Marx's baseline

Based on the repository layout and package metadata, the distributed package contains compiled CSS under css and source CSS under src. The package entry point is css/marx.min.css, while exports also expose the unminified css/marx.css and individual files below ./css/*. Importing the package root therefore loads the minified stylesheet as a side effect.

Marx styles the semantic elements themselves rather than waiting for application classes. In the quickstart, main acts as the centered container. Headings and paragraphs receive type and spacing treatment, while form controls receive styling tied to labels, inputs, and buttons. The classless result depends on continuing to choose meaningful HTML elements instead of substituting generic containers merely to select styles.

The CSS architecture has two details that affect extension. First, every Marx rule sits inside :where() within a cascade layer and has zero specificity. Second, theming is exposed through --marx-* custom properties. Unlayered author CSS can override token values without needing to outrank Marx selectors. The source file src/_tokens.css is the documented location for the complete token list and defaults.

This is a deliberate constraint rather than an oversight. It reduces selector fights and keeps the API compact, but it also means the normal customization model is global tokens and additional CSS. A project that expects per-component overrides through utility or component classes will need another pattern.

Installing Marx and rendering the first page

The documented package installation is a single npm command. This adds marx-css to the project so a bundler can import the stylesheet directly:

bash
npm install marx-css

The README says that a bundler can load the same CSS with this import:

js
import "marx-css"

For a page that does not need package installation, the documented CDN option avoids local dependency management. Create an HTML document with semantic elements and place the stylesheet link in the head:

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Marx</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/marx-css@5/css/marx.min.css">
</head>
<body>
  <main>
    <h1>Workers of the world</h1>
    <p>Plain HTML, styled automatically.</p>
  </main>
</body>
</html>

The reader should see centered main content, styled heading and paragraph typography, and the spacing assigned by the stylesheet. No class attributes are present. The repository's index.html and docs directory provide local project material for examining or running the documentation site, although the README does not document a separate command for starting that site.

Marx custom properties and automatic dark mode

Marx exposes its entire documented API through custom properties. A small unlayered stylesheet can change the accent color, corner radius, and content width:

css
:root {
  --marx-primary: hotpink;
  --marx-radius: 0.75rem;
  --marx-measure: 60rem;
}

These values control a specific part of the design rather than merely adding arbitrary variables. The documented groups cover page and surface colors, links, focus rings, error feedback, four font-related settings, the heading scale, spacing, content width, and corner radius. The --marx-measure token is especially relevant for reading layouts because it sets the permitted content measure, while --marx-flow and --marx-leading affect vertical rhythm and text leading.

Colors use light-dark() under color-scheme: light dark. According to the README, dark mode therefore follows the visitor's operating system without a toggle or JavaScript. A site can force light presentation with this declaration:

css
:root { color-scheme: light }

That behavior is compact, but it is not a user-controlled theme preference. The README does not document persisting an explicit light or dark selection. Projects requiring an in-page color-scheme control would need additional implementation.

Browser boundaries, cascade behavior, and accessibility details

The stated browser targets are Chrome and Edge 123+, Firefox 120+, and Safari 17.5+. Marx uses logical properties for right-to-left layouts, which is a sensible fit for text direction. It also places transitions behind prefers-reduced-motion, so the baseline accounts for visitors who request less motion.

Compatibility has a defined failure mode. Browsers without light-dark() retain the static light value of each color. Those browsers still receive the page layout, but the automatic dark color scheme is lost. This is a graceful degradation for general presentation rather than for parity with the newest browser behavior.

The zero-specificity cascade design also deserves scrutiny when Marx enters an existing codebase. It lowers the effort required to override Marx's own rules, but application CSS can also style the same elements in ways the author did not intend. The documentation does not describe a namespace beyond the --marx-* theme properties, nor does it provide utility classes for locally disabling an element style. Integration should therefore include inspection of the host application's selectors and cascade layers rather than assuming the package can be dropped into any stylesheet environment unchanged.

Where Marx is cheaper to maintain than a class-based system

Marx's maintenance cost begins with unusually little application code. There are no classes to remove during a redesign because the baseline does not introduce them. A theme change can be concentrated in a small set of --marx-* values, while page authors continue using common semantic tags. This model also reduces markup noise for pages whose visual structure closely matches the HTML outline.

The repository was not archived, and its last push was on 2026-10-14. The recorded release history includes v5.3.2 on 2026-08-21, v5.3.1 on 2026-08-21, and v5.3.0 on 2026-07-19. The package scripts include separate development and minified CSS builds, linting through oxlint, formatting through oxfmt, and site generation through build:site. The.changeset directory also indicates that changes can be recorded through changesets.

For consumers, an upgrade still requires reviewing CSS output and browser support. There is no JavaScript API to assess and no documented application migration tool. A major stylesheet change could affect every page that relies on element defaults. The MIT license permits use, modification, distribution, and sublicensing under its terms, subject to the license text, but this review does not interpret those legal obligations.

Marx versus a class-based component framework

The practical alternative is a class-based CSS framework or a project-specific component stylesheet. Those systems select presentation through classes, allowing the same element type to have different appearances in different contexts. They also commonly supply reusable component structures and layout helpers. Marx instead treats the chosen HTML element as the styling request and offers one coherent baseline for that mapping.

This difference matters when visual behavior is tied to meaning. A single h1 is straightforward for Marx to style because each document should normally have a clear title hierarchy. Repeating button with primary, secondary, danger, compact, and loading states is less straightforward, since those distinctions are not encoded by the button element itself. A class-based system can attach those states directly, whereas extending Marx requires new selectors or additional markup conventions chosen by the developer.

Marx is therefore cheaper for small, consistent documents and more restrictive for dense interface systems. The repository does not document migration instructions from a named framework, so choosing it does not eliminate all selector decisions. It simply moves the primary decision from framework class names to semantic element structure and any CSS written after Marx.

Editorial conclusion

Adopt Marx for a small site, prototype, documentation page, or static document whose presentation can safely follow HTML element semantics. Do not choose it when component-level variation, complex interaction states, or extensive responsive layout are central to the product. Before adoption, verify the exact v5.3.2 package and stylesheet you will ship, test the intended browsers, and confirm that element-based styling does not conflict with existing CSS.

Frequently asked questions

How do I install Marx CSS?

Run `npm install marx-css`, then import `marx-css` from a bundler. Alternatively, link the documented jsDelivr stylesheet in an HTML page.

Does Marx CSS require class names in HTML?

No. Marx's classless design styles plain semantic HTML after one stylesheet is loaded. The quickstart uses `main`, `h1`, `p`, `form`, `label`, `input`, and `button` without classes.

How do I customize colors and dark mode in Marx?

Override documented `--marx-*` custom properties in unlayered CSS. Colors use `light-dark()` and `color-scheme: light dark`, so dark mode follows the visitor's OS unless the page forces another scheme.

Which browsers does Marx support?

The README lists Chrome and Edge 123+, Firefox 120+, and Safari 17.5+. Browsers without `light-dark()` keep the static light colors but still receive the page styles.

Can Marx CSS style different variants of the same HTML element?

The documented API is based on semantic elements and global `--marx-*` properties. The README does not document component classes for variants, so distinct same-element appearances require additional selectors and CSS.

Official sources

  1. License: MIT
  2. mblode/marx on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/mblode-marx.svg)](https://hysenlabs.com/projects/mblode-marx)

Was this useful?