Skip to content
anybladesPublic

About

A modern drop-in successor to Pico CSS. Just switch `pico.css` to `blades.css`— and voilà! 🥷✨

Topics

Resources

Code of conduct

Contributing

Stars

387 stars

Watchers

7 watching

Forks

Repository files navigation

blades✨

Minimal CSS Framework for Semantic HTML

Blades CSS is a modern drop‑in successor to Pico CSS.

Just switch pico.css to blades.css— and voilà!

Get started  •  Inspired by Pico ✨

Quick start

There are 4 ways to get started:

A. Install manually

Download CSS archive and link css/blades.css in the <head> of your website.

<link rel="stylesheet" href="css/blades.css" />

B. Usage from CDN

<link rel="stylesheet" href="
  https://cdn.jsdelivr.net/npm/@anyblades/blades@3/css/blades.min.css
"/>

Live example: https://github.com/pallets/website/blob/main/src/pallets/templates/layout.html

Full list of CSS files available on CDN: https://cdn.jsdelivr.net/npm/@anyblades/blades@3/css/

layered/blades.layered.min.css is Blades wrapped in @layer blades { }. See Layered modules.

C. Install with NPM

npm install @anyblades/blades

Then, @import the built css/blades.css into your CSS file:

@import "@anyblades/blades";

Alternatively, import standalone Blades CSS sources only (without underlying Pico CSS base styles):

@import "@anyblades/blades/standalone";

Live example using Tailwind: https://github.com/anyblades/buildawesome-micro-starters/blob/main/tailwind/styles.css


Or import only the parts you need, e.g. per page or per component. They come wrapped in @layer blades, so your unlayered styles win over them:

@import "@anyblades/blades/variables";
@import "@anyblades/blades/layout/document";
@import "@anyblades/blades/content/typography";
@import "@anyblades/blades/components/card";
@import "@anyblades/blades/components/modal";
  • variables and layout/document are the minimum; keep the same order as src/pico/_index.css (variables → layout → content → forms → components → utilities).
  • layout doesn't pad body > header/main/footer. Add layout/landmarks for Pico's behaviour.
  • Some parts build on others, e.g. components/modal expects components/card, and components/group and components/dropdown expect forms/basics and content/button.
  • See Layered modules for the available parts, and for importing them from JavaScript in bundlers and component frameworks (SvelteKit, Next.js, Nuxt, Astro, …).
  • The same parts without the layer are under @anyblades/blades/src/…, e.g. @anyblades/blades/src/components/card, to put them in a layer of your own (@import "@anyblades/blades/src/components/card" layer(ui);) or to run your own build. @anyblades/blades/src on its own is the source of the whole blades.css.

D. Official starters


Starter HTML template

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="color-scheme" content="light dark" />
    <link rel="stylesheet" href="css/blades.css" />
    <title>Hello world!</title>
  </head>
  <body>
    <main class="container">
      <h1>Hello world!</h1>
    </main>
  </body>
</html>

Dynamic templates

Available for Nunjucks, Liquid and Twig ↗


Dark mode without a flash

With the Pico-based builds, Blades follows the OS setting by default, with no JavaScript and no flash (see Dark scheme). To force a theme, set data-theme="light" or "dark" on <html>. On a nested element it works when the element paints its own background, such as <article>; otherwise add background-color: var(--pico-background-color); color: var(--pico-color);.

If you persist the user's choice, e.g. under the localStorage key theme, set the attribute before the first paint with a small inline script in <head>, e.g. in SvelteKit's src/app.html:

<script>
  try {
    const theme = localStorage.getItem("theme");
    if (theme === "light" || theme === "dark") document.documentElement.dataset.theme = theme;
  } catch {}
</script>
  • Setting it later, e.g. in onMount or useEffect, renders the OS theme first and then switches.
  • In a Next.js App Router layout, pass the same code as a template literal, <script dangerouslySetInnerHTML={{ __html: `try { … } catch {}` }} />, and add suppressHydrationWarning to <html>, because the attribute changes before hydration.

Compact sizing (opt-in)

Add <html data-compact> for the whole page, or put the attribute on a single element, e.g. <form data-compact> for one form. Without the attribute nothing changes.

  • Where it ships:
    • included in blades.css
    • also in blades.layered.css
    • with per-part imports, add @anyblades/blades/compact after the other parts
    • with pico.conditional.css, add @anyblades/blades/src/compact after it
  • What changes:
    • smaller control padding and 1.5rem block spacing
    • a 0.5rem radius and a 3px focus ring
    • 500-weight labels and buttons, 600-weight headings
    • a white field background in light mode
    • a 1px card ring instead of the blurred shadow, with no grey card header/footer bands
  • Root font size: on <html>, it also keeps the root font size at 100% instead of growing with the viewport. At 1280px wide, controls are then 38px instead of 62px. On a single element they are about 48px, because everything is sized in rem and the root stays as it is.
  • Field text size: form controls stay at 16px, because below that iOS Safari zooms in on focus.

Documentation

Blades CSS is a lightweight, minimal CSS framework for semantic HTML designed as a modern, drop-in successor to Pico CSS.


Trusted by

Also used by

Featured by

About

A modern drop-in successor to Pico CSS. Just switch `pico.css` to `blades.css`— and voilà! 🥷✨

Topics

Resources

Code of conduct

Contributing

Stars

387 stars

Watchers

7 watching

Forks

Releases

Used by

Contributors

Languages