Pico CSS: What Happens When You Delete Your Design System

BudgetFlow uses Pico CSS for the basic page styles. It gives forms, tables, and headings sensible defaults while letting us write ordinary HTML.

We still write CSS for our own components and page layouts. Pico covers the common elements, so those styles can stay focused on what the app needs.

Starting with HTML Elements

Pico styles native elements directly. A <button> gets button styles, and a <table> gets table styles. You can add classes for variants, but basic markup does not require them.

A button shows the difference clearly.

Bootstrap vs. Pico: A Button

Bootstrap:

<button class="btn btn-primary btn-lg">Save Budget</button>

Pico:

<button>Save Budget</button>

Pico styles the element itself. For a secondary or outline button, you can add class="secondary" or class="outline". The difference becomes more useful across a whole form.

Form controls, headings, and tables receive the same treatment. Most pages look coherent before we add any page-specific styles.

Useful Defaults

Pico covers controls such as <input>, <select>, and <textarea>, along with focus and disabled states. It also supports dark mode through prefers-color-scheme.

The <article> element works as a simple card. BudgetFlow's wealth comparison page puts several articles inside Pico's .grid to display its figures.

For these elements, the markup stays close to plain HTML. That makes templates easier to scan when revisiting them months later.

What You Override

BudgetFlow defines a few application colours in CSS custom properties:

:root {
	--primary-color: rgb(0, 103, 163);
	--secondary-color: #6c757d;
	--success-color: #28a745;
	--danger-color: #dc3545;
	--warning-color: #ffc107;
	--info-color: #17a2b8;
}

These variables also give the web components a shared set of colours.

Pico increases its base font size at wider breakpoints. We keep it at 100% because the app has dense tables and forms:

@media (min-width: 576px)  { :root { --pico-font-size: 100% } }
@media (min-width: 768px)  { :root { --pico-font-size: 100% } }
@media (min-width: 1024px) { :root { --pico-font-size: 100% } }
@media (min-width: 1280px) { :root { --pico-font-size: 100% } }

That override sits beside the rest of the page styles.

Pico and Shadow DOM

BudgetFlow also has web components such as ui-button and ui-modal. Pico's element styles generally do not apply inside their shadow roots, so the components define their own internal styles.

Pico handles the page's native elements. The components handle their own buttons, drawers, and modals. Both can use inherited CSS custom properties for shared colours.

When a page needs to style part of a component, it can use an exposed ::part():

.blog-article-container::part(container) {
	max-width: 800px;
}

The syntax highlighter needs a couple of overrides where Pico's styles affect code blocks:

background-color: unset; /* Remove pico.css background color */
color: unset; /* Remove pico.css text color */

Those declarations reset the affected colours for highlighted code.

What Pico Doesn't Give You

Pico has a small .grid helper, but it does not provide a full layout utility system. We write CSS when a page needs a specific arrangement.

It also does not provide the app's interactive components. BudgetFlow uses web components for modals and other reusable elements, htmx for server requests, and its hx-live extension for local state.

Pico itself is CSS, so it does not manage interactions. That division has been easy to work with here.

A project that needs many custom component variants will still have to build them. Pico helps most when native HTML makes up a large part of the interface.

Why We Chose It

Pico gave the forms and content pages a useful starting point with little markup. We could add custom styles where the defaults did not fit.

The result is visible throughout BudgetFlow: tables and forms use Pico's defaults, while custom components keep their own styles.

Where It Fits

Pico is a good fit when you want to start with native HTML and add styles as the interface takes shape. It leaves room for detailed component styling without making every template depend on framework classes.

If your pages are mostly forms, tables, and readable content, try styling the HTML first. You can see fairly quickly which parts need custom CSS.

Start Your Financial Journey Today

Take control of your financial future with visual planning and dynamic budgeting. Sign up now and start managing your budget with confidence!