Library / SDK
uikit/uikit avatar
uikit/uikit

uikit's stylesheets come from Less, and build-scss is not part of the build

A lightweight and modular front-end framework for developing fast and powerful web interfaces

18,535 stars2,284 forksHTMLMIT

At a glance

What is it?
UIkit is YOOtheme's MIT licensed front-end framework, distributed as prebuilt CSS and JS, through three package managers, or from a CDN, and it is built with a small set of Node scripts in `build/`. The details that decide how you consume it are in the manifest rather than the README: the stylesheets are authored in Less with a separate SCSS script that the main compile never calls, right-to-left is a build target the README never mentions, and there is no exports map, so module resolution goes through `main`.
Who is it for?
uikit fits a team that wants a complete CSS and JavaScript layer dropped into a server-rendered or static site without a build step of its own, and that is happy to take a whole framework rather than assemble components. It does not fit a team that needs to import one component's script through a bundler, because the manifest has no exports map and no module field, or one that expects the README to describe the right-to-left build that the scripts and dependencies implement.
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 received new commits within the last day.
What is it written in?
Mainly HTML, according to GitHub's language statistics.

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

From daily snapshots

Star history

  • uikit/uikit18,535 ★ · -2
Star history
Repository2026-09-212026-11-14
uikit/uikit18.5k18.5k

-2 Stars in the last 54 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

The CSS is authored in Less, and the SCSS script is not in the build

The scripts make this clear if you read them in the right order. The top-level `compile` script runs:

bash
pnpm compile-less && pnpm compile-js

And `compile-less` is `pnpm icons && node build/less`, while `compile-js` is `node build/build`.

So the stylesheet in a release is compiled by `node build/less`, and the icon generation is a prerequisite of that step. There is also a separate script called `build-scss`, which runs `node build/scss`, and it is not called by `compile` and not mentioned in the README.

That is a genuine trap for a contributor. The name `build-scss` reads like the CSS build, and a person looking for the stylesheet pipeline will find a Less script and an SCSS script and have to work out which one the release uses. The dependency list settles it: `less` is there at a caret range, and no Sass compiler appears in the listed development dependencies.

Either the SCSS path is kept for a specific use the README does not mention, or it is a leftover. Nothing in the README or package.json says which, and that ambiguity is the cost.

Right-to-left is a build target, and the README never mentions it

There is a script for it and a dependency for it. The script is:

bash
pnpm compile-less rtl

and `rtlcss` is in the development dependencies at a caret range.

So a complete right-to-left pipeline exists: author in Less, compile, flip direction with rtlcss. The `rtl` argument is passed to the parent `compile-less` script rather than to the compiler directly, which means the build wrapper reads it and chooses the flip, so the mechanism is the project's own rather than a flag a user would pass to Less.

What is missing is any mention of it. The README covers installation, contributing, versioning, browser support and the licence, and none of those sections refers to right-to-left, directionality or a language-specific build. The README has no section on distribution, and the root listing does not name a file that would cover it.

For a framework used outside English-language interfaces this is a real gap in the documentation and not in the software. The capability is there, the build target is named, and a reader has to find it in the manifest to know it exists.

There is no exports map, so resolution goes through main

The manifest declares two entry points and nothing else:

json
    "main": "dist/js/uikit.js",
    "style": "dist/css/uikit.css",

There is no `exports` field, no `module` field, and no `types` field. Resolution therefore goes through `main`, which points at a built JavaScript file under `dist/`, and the stylesheet is reached through `style`, a convention rather than a standard.

The consequence is specific. A bundler that prefers an ES module entry has nothing to prefer, because there is no field declaring one and no condition map to consult. And a project that wants to import a single component's script rather than the whole bundle has no documented subpath to use, which is the normal escape hatch a package with a build step would offer.

Compare that with the amount of care in the rest of the manifest. The `sideEffects` list, the nine scripts and the pinned `packageManager` are all specific. The entry point declaration is the one place that looks like it was written years ago and left alone, and it is the place a consumer touches first.

sideEffects lists the stylesheet, so tree-shaking is off for CSS and those paths

The `sideEffects` field is an array, not a boolean:

json
    "sideEffects": [
        "*.css",
        "./src/js/*.js",
        "./dist/**/*.js"
    ],

Three globs, covering every stylesheet, the JavaScript sources at the top level of `src/js`, and everything under `dist` that is JavaScript.

This is the correct setting for a framework whose stylesheet is global rather than per-component, and getting it wrong would let a bundler drop rules that are only reachable through CSS. But it is a blunt instrument in the other direction too. A bundler that honours this list will not remove any of those JavaScript files, so the JavaScript payload is kept whole as well, and a project that imports one thing from the framework is likely to end up with the framework.

The third glob is the one that matters for the published package, because it covers everything the build produces under dist. In practice no part of the distributed JavaScript is a candidate for removal, however the consumer's bundler is configured.

Three of the six install routes are explicitly for source

The Getting started section lists six ways to get UIkit, and the wording of three of them is the same: install with npm, yarn or pnpm to get all source files as they are available on GitHub.

bash
npm install uikit

`yarn add uikit` and `pnpm add uikit` are the other two. The remaining three routes are different in kind: download the latest release with pre-built CSS and JS, load UIkit directly from jsDelivr, or clone the repository to get all source files including build scripts.

So the six are not six equivalent choices. Three are the same thing under three package manager names, and the framing of all three is source access rather than a packaged build, which is unusual for a framework that publishes `dist`.

The clone command is worth noting on its own:

bash
git clone [email protected]:uikit/uikit.git

That is an SSH URL, so it needs a configured key. A reader without one has to rewrite it to https, and the README gives no alternative form for that route.

A dev dist-tag moves ahead of every release, on all three registries

There is a Developers section, and its purpose is a channel that is not a release:

bash
npm install uikit@dev

`yarn add uikit@dev` and `pnpm add uikit@dev` are given the same way, along with a CDN URL, `https://cdn.jsdelivr.net/npm/uikit@dev`, for the same tag.

The section says this is for always having the latest development version, even before a release. So the project publishes a moving pre-release on npm, reachable by the same three package managers and by a CDN, and the tag is the only handle a consumer has on it. There is no version number to record, so a project pinning `uikit@dev` has pinned a moving target.

That arrangement is a real choice rather than an omission. It gives contributors a way to test a change before it is released, and it gives a user a way to see unreleased work. The cost is that the README is the only place the tag is named, and nothing in the top level listing points at it.

There is a composer.json in a front-end framework

The top level contains `composer.json`, `dist/`, `build/`, `src/`, `tests/`, `jsconfig.json`, `eslint.config.mjs`, `.prettierrc.json`, `pnpm-workspace.yaml`, `pnpm-lock.yaml`, `AGENTS.md` and `BACKERS.md`.

A Composer manifest in a project whose manifest is a `package.json` and whose primary language is recorded as HTML is the most distinctive single entry in that list. It suggests a PHP packaging path alongside npm, and `dist/` is committed in the repository.

Nothing in the README explains it. There is no section on distribution, no mention of Composer, and no note about who consumes that package or why the framework has a PHP packaging path alongside an npm one. For a reader it is a loose end that changes how you think about the project, because it implies somebody is installing this from a PHP ecosystem.

Two smaller signals in the same list. The build tools in `build/` are referenced without file extensions, `node build/scss`, `node build/build`, `node build/icons`, `node build/less`, `node build/prefix` and `node build/scope`, with only `watch.js` carrying one. And the editor configuration is `jsconfig.json` rather than a TypeScript configuration, which is consistent with a JavaScript project that has no types to declare.

SemVer is claimed and the third component has reached 25

The versioning section is one sentence: UIkit is maintained by using the Semantic Versioning Specification.

The release history makes that worth reading twice. The three most recent tags are v3.25.27 on 2026-10-20, v3.25.28 on 2026-10-26 and v3.25.29 on 2026-11-02. Three releases in two weeks, and the third component of the version is at twenty-nine.

A patch component that reaches twenty-nine is not behaving like a patch level. Under a strict SemVer reading those are all the same version to a consumer who writes `^3.25.0`, so the number is functioning as a build counter rather than as a compatibility boundary. That is a common and harmless pattern, and it is also a mismatch between the stated policy and the observed numbers.

The browser support section has a related problem. The table reduces to a single row reading Latest with a tick in every column, followed by a BrowserStack link and the words Tested With. The column headings, which would name the browsers, do not appear in the text, and no minimum version is given anywhere in the section.

So both compatibility statements are vague in the same way. SemVer is claimed without the numbers backing it, and browser support is asserted without a version anyone can compare against. The last push to the default branch was on 2026-10-30.

Editorial conclusion

uikit fits a team that wants a complete CSS and JavaScript layer dropped into a server-rendered or static site without a build step of its own, and that is happy to take a whole framework rather than assemble components. It does not fit a team that needs to import one component's script through a bundler, because the manifest has no exports map and no module field, or one that expects the README to describe the right-to-left build that the scripts and dependencies implement. Before adopting, check three things: whether you want the prebuilt CSS and JS release or the source files, since three of the six documented install routes are explicitly for source, whether the `dev` dist-tag is acceptable for you given that it moves ahead of any release, and whether your bundler can live with resolution through `main` at `dist/js/uikit.js` and a `sideEffects` list that disables tree-shaking for the stylesheet.

Frequently asked questions

How do I install uikit?

The README lists six routes: download the latest release with pre-built CSS and JS, `npm install uikit`, `yarn add uikit`, `pnpm add uikit`, load it directly from jsDelivr, or clone the repository for all source files including the build scripts. It is developed by YOOtheme and released under the MIT licence.

What is uikit?

UIkit is described as a lightweight and modular front-end framework for developing fast and powerful web interfaces, and it is an open source project developed by YOOtheme under the MIT licence. It is versioned with SemVer and currently sits on a 3.25 line, published on npm as the `uikit` package with `main` at `dist/js/uikit.js` and `style` at `dist/css/uikit.css`.

Does uikit have a pre-release or development version?

Yes. The Developers section says that to always have the latest development version, even before a release, you can use npm, yarn or pnpm with the `dev` tag, giving `npm install uikit@dev`, `yarn add uikit@dev` and `pnpm add uikit@dev`, plus a CDN URL for the same tag. The Developers section is the only place the tag is named.

How do I use right-to-left styles with uikit?

The build has a `compile-rtl` script that runs the Less compile with an `rtl` argument, and `rtlcss` is a development dependency that performs the flip. The README does not mention right-to-left support at all, so the capability exists in the build without being documented.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. uikit/uikit on GitHub
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/uikit-uikit.svg)](https://hysenlabs.com/projects/uikit-uikit)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/uikit-uikit.svg)](https://hysenlabs.com/projects/uikit-uikit)

Was this useful?