KNACSS styles native HTML elements instead of shipping a component library
Styles CSS sur-vitaminés pour éléments HTML natifs
At a glance
- What is it?
- KNACSS is a CSS layer for the native elements of an HTML page, buttons, inputs, selects, tables, dialogs, with no dependency on a CSS framework and theming done through custom properties. The styleguide that documents it is itself built with Handlebars templates and Vite, and the code samples in it are highlighted through the CSS Custom Highlight API rather than a traditional highlighter.
- Who is it for?
- Adopt KNACSS if you want modern styling on semantic HTML without adopting a component library, and if you are willing to override the CSS custom properties rather than to pass props to widgets. Do not adopt it if you need a large catalogue of prebuilt interactive components, since the scope here is styling the elements the browser already gives you.
- Can I use it commercially?
- Yes. WTFPL 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 8 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
A stylesheet for elements the browser already ships
KNACSS is described in the repository listing as a stylesheet for native HTML elements, and the README calls it a library of native HTML components that are styled, accessible and customisable. The word native is doing the work in that sentence.
The feature list starts with the essentials. All the essential HTML elements, button, input, textarea, select, checkbox, radio, range, switch, details, dialog, table and list, with modern and accessible styles. There is no wrapper component, no virtual DOM element and no template for you to learn. The HTML you write is the HTML the browser understands, and the CSS makes it look deliberate.
That approach has a practical consequence worth naming. Because the markup stays native, the accessibility story is largely inherited from the platform rather than built on top of it, and the README says to keep the native semantics, with labels, required attributes and aria attributes where they apply, and states that the styles do not obstruct keyboard navigation.
The styling approach is modern vanilla CSS. Custom properties, nesting, Grid and Flexbox, modern media queries, and no dependency on a CSS framework. The performance and accessibility bullet is specific about the means: light code, low CSS specificity, minimal JavaScript, and complete keyboard navigation.
There is an eco-design bullet as well, with optimised assets, efficient rendering and compatibility with sober approaches, which is the French way of saying the project tries to ship less.
Theming is a set of custom properties, and the README shows the shape
Personalisation is described as complete: adapt colours, spacing, radii and typography through CSS variables, without touching the HTML.
The README shows what those variables look like, and the naming convention is the interesting part because it encodes a scale rather than one off values:
:root {
/* Couleurs */
--color-primary-500: #2563eb;
--color-gray-900: #0f172a;
/* Typo et rythmes */
--text-m: 1rem;
--leading-28: 1.75rem;
/* Rayons et espacements */
--radius-8: 8px;
--spacing-16: 1rem;
}The tokens are named by role and step: a primary colour at the 500 step, a grey at 900, a text size at the m step, a line height at 28, a radius at 8 and a spacing value at 16. The trailing number is a scale step, not a pixel count, which is the difference between a token set you can scale and a list of hard coded sizes.
Overriding them in :root or in a wrapper is the whole customisation story, and the README's own note in the usage section repeats it: modify your tokens through your own CSS variables, with no dependency on a CSS framework.
Two ways of using the project are offered. The first is to copy and paste the HTML from the styleguide, choose a component, click the show code button and copy the block, then include the project stylesheet. With Vite that means importing assets/app.css in your JavaScript entry point, and in a static setup it means using the generated CSS in public/css/ or in the build directory in your HTML pages.
Most components work without JavaScript, and the rest is opt in
The usage notes are short and set expectations clearly.
Most components work without JavaScript. Some offer optional JavaScript, with dialog and a textarea with a counter given as examples, and the README refers you to the component folder to enable it if you need it.
That is a meaningful design position for a component library, and it changes what you inherit. A dialog, for instance, is a native element with native behaviour, and the project only adds a progressive enhancement on top when you ask for it. The same pattern holds for a textarea counter. You are not adopting a JavaScript widget runtime, and you are not losing the platform behaviour you would have had with no library at all.
The styleguide itself is described as an interactive layout rendered through templates at build time. The directories are templates/ for Handlebars, templates/partials/ for the header, sidebar and footer, templates/context.json for page metadata, and assets/data/components.json for the list of components in the navigation.
The demo injection stays on the client side, through assets/js/router.js and an import.meta.glob over the natives HTML files, which is the standard Vite glob import pattern for pulling in every native component example at build time.
The package.json shows the toolchain behind it: Vite with a Handlebars plugin, PostCSS with custom media, ESLint, Prettier and a stack of stylelint configurations, including the property sort order rules for SMACSS conventions, which tells you the project holds its CSS to a specific ordering standard.
Syntax highlighting runs through the browser, not a highlighter library
The styleguide highlights its own code samples with the CSS Custom Highlight API and a web component called syntax-highlight-element, and the README is explicit that this is the mechanism.
The configuration story is the interesting part, and it is a workaround for a real constraint. The element uses a top level await, so to avoid a build error the project is configured to target ES2022 on both the esbuild and the build side, with esbuild.target, optimizeDeps.esbuildOptions.target and build.target all set to es2022 in vite.config.js.
The component is imported globally from assets/main.js, along with its prettylights theme stylesheet, and the theme applies its colours through the ::highlight() pseudo element, which you can change or replace with your own.
The markup is a web component with a language attribute, and the README notes that an initial text node is present, a space, to guarantee that the API creates its Ranges on the firstChild. The code block stays an ARIA region with an aria-label, and the component exposes a code role through ElementInternals.
When a reader clicks the show code button, the component's HTML is serialised, formatted and injected, with the textContent set to the formatted HTML and an update call when available to trigger the highlighting again. If the web component is not available, there is a fallback: the code is inserted into a code element with the language-html class.
For the styleguide's own conventions, the language attribute takes html, css or js, and the formatter compacts some elements onto one line when their content is simple text.
The releases stopped in 2022 while the commits carried on
The maintenance record is the one thing here that needs care, because the two signals disagree.
The release list shows v8.2 on 2022-01-19, v8.1 on 2022-01-05 and v8.0.4 on 2021-04-26. Those are the most recent tagged versions, and they are more than four years old. Meanwhile the last push was on 2026-10-15 and the repository is not archived, so work on the code has clearly continued.
That means there is a gap between what the version numbers describe and what is in the repository today. If you are evaluating it now, you are looking at a tree whose last named release predates most of its own history. The changelog.md at the root and the git history are the places to look for what actually changed.
There is a related oddity in the packaging. The package.json is marked private, its version field is 0.0.0, and the dependencies are minimal, with syntax-highlight-element at 1.2.0 or newer as the single runtime dependency. So the npm package is not the distribution channel here. The project is distributed as a stylesheet and a styleguide site, and the repository is the source of truth for both.
The licence is the WTFPL, and the LICENSE file sits at the root alongside a CNAME file, a sitemap.xml and a robots.txt, which is the shape of a project published as a website rather than as a package. The WTFPL is one of the most permissive licences available, and it applies to a stylesheet, so the licensing question is rarely the obstacle here. The obstacle, when there is one, is the version gap above and whether the modern CSS features it relies on are acceptable for the browsers you have to support.
Where a component library is the better answer
The scope boundary is the honest comparison point. KNACSS styles what the browser already provides, which means it does not ship a calendar, a combobox with typeahead, a rich text editor or a data grid. If your product needs those, a component library is the different approach, not a better one.
The difference in approach is where the behaviour lives. A component library gives you a widget with its own state, its own keyboard handling and its own accessibility implementation, and you drive it through props. KNACSS gives you a native element with the platform's behaviour, and you drive it through attributes, so you get the browser's own accessibility and behaviour for free and you accept that you cannot restyle its internals.
That trade is worth it when the design is yours to define and the elements involved are ordinary. It is not worth it when a native element is inadequate for the task, because at that point you are writing the widget yourself anyway, and you have added a stylesheet layer on top of it.
The second limit is the specificity question. The README claims low CSS specificity as a feature, and that is what lets a user override a component without fighting the cascade. The cost is that the visual result depends on the order and the shape of the token set, and a project that needs a design that departs from the default tokens will find itself overriding more than it expected.
The third is browser support, and it is the one to check first. Custom properties, CSS nesting, Grid and Flexbox are all baseline in current browsers, but the README is explicit that the project uses modern CSS with no framework fallback, so an older browser is not a partial degradation case, it is an unstyled page. That is a perfectly good position for a project that controls its audience, and a poor one for a public library.
For a comparison point on the other side, the framework approach gives you a consistent component vocabulary across a large team and a documentation story that is not a styleguide page. KNACSS gives you less to learn and fewer bytes, at the price of doing more yourself when you need something the platform does not offer.
Editorial conclusion
Adopt KNACSS if you want modern styling on semantic HTML without adopting a component library, and if you are willing to override the CSS custom properties rather than to pass props to widgets. Do not adopt it if you need a large catalogue of prebuilt interactive components, since the scope here is styling the elements the browser already gives you. Verify first which browsers you need to support, because the modern CSS features the project relies on, custom properties, nesting and grid, set the floor, and check whether the theme you want can be expressed with the documented variables rather than by rewriting selectors.
Frequently asked questions
What is KNACSS and what does it style?
KNACSS is a CSS library of native HTML components that are styled, accessible and customisable. It covers the essential HTML elements such as button, input, textarea, select, checkbox, radio, range, switch, details, dialog, table and list, using modern vanilla CSS with custom properties, nesting, Grid and Flexbox, and no dependency on a CSS framework.
How do I customise the look of KNACSS components?
By overriding the CSS custom properties, either in :root or in a wrapper, without touching the HTML. The tokens are named by role and scale step, for example --color-primary-500, --color-gray-900, --text-m, --leading-28, --radius-8 and --spacing-16, so a theme can be re-scaled rather than just recoloured.
Do KNACSS components need JavaScript?
Most of them do not. Some offer optional JavaScript, with the dialog and a textarea counter given as examples, and the README refers you to the component folder to enable it. The project also states that you should keep the native semantics, with labels, required attributes and aria attributes where needed, and that the styles do not obstruct keyboard navigation.
How is the KNACSS styleguide built?
It is a modular layout rendered through Handlebars templates at build time, with templates/ for the templates, templates/partials/ for the header, sidebar and footer, templates/context.json for page metadata and assets/data/components.json for the navigation list. The demo injection stays on the client side through assets/js/router.js and an import.meta.glob over the natives HTML files, and the build runs on Vite with a Handlebars plugin.
What licence is KNACSS under and how current is it?
The repository listing records the licence as WTFPL, with the LICENSE file at the repository root, and the package.json marks the npm package as private. The last tagged releases are v8.2 from 2022-01-19 and v8.1 from 2022-01-05, while the last push was on 2026-10-15 and the repository is not archived.
Official sources
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.
[](https://hysenlabs.com/projects/alsacreations-knacss)Was this useful?