Usage

Work without package manager or dependencies 🙂!

There are 3 ways to get started with pico.css:

Install manually

Download Pico and link /css/pico.min.css in the <head> of your website.

<link rel="stylesheet" href="css/pico.min.css">

Install from CDN

Alternatively, you can use the unpkg CDN to link pico.css

<link rel="stylesheet" href="https://unpkg.com/@picocss/[email protected]/css/pico.min.css">

Install with NPM

npm install @picocss/pico

Starter HTML template:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, viewport-fit=cover">
    <link rel="stylesheet" href="css/pico.min.css">
    <title>Hello, world!</title>
  </head>
  <body>
    <main class="container">
      <h1>Hello, world!</h1>
    </main>
  </body>
</html>

Themes

Pico is shipped with 2 consistents themes: Light & Dark.

The Light theme is used by default. The Dark theme is automatically enabled if user has dark mode enabled prefers-color-scheme: dark

Themes can be forced on document level <html data-theme="light"> or on any HTML element <article data-theme="dark">

Light theme

<article data-theme="light">
  ...
</article>

Dark theme

<article data-theme="dark">
  ...
</article>

Customization

You can customize themes with SCSS or you can simply edit the CSS variables.

Example: pick a color!

Custom theme

There are 2 ways to customize your version of Pico.css:

Importing SASS

It is recommended to customize Pico by importing SASS source files in your project. This way you can keep Pico up to date without conflicts since Pico code and your custom code are separated.

Compile the SASS file to CSS to get a custom version of Pico.

/* Custom  version */

// Override default variables
$primary-500: ...;
$primary-600: ...;
$primary-700: ...;

// Import full Pico source code
@import "path/pico";

Alternatively, you can create a custom theme and import it in your project with the components you need.

/* Custom  version */

// Custom theme
@import "path/themes/custom";

// Import needed components
@import "path/layout/document";
@import "path/layout/sectioning";
...

This allows to create a lighter version with only the components that are useful to you. Example here: scss/pico.slim.scss.

Overriding CSS variables

All Pico's styles and colors are set with CSS custom properties (variables). Just override the CSS variables to customize your version of Pico.

/* Light scheme (Default) */
/* Can be forced with data-theme="light" */
[data-theme="light"],
:root:not([data-theme="dark"]) {
  --primary:              ...;
  --primary-hover:        ...;
  --primary-focus:        ...;
  --primary-inverse:      ...;
}

/* Dark scheme (Auto) */
/* Automatically enabled if user has Dark mode enabled */
@media only screen and (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --primary:            ...;
    --primary-hover:      ...;
    --primary-focus:      ...;
    --primary-inverse:    ...;
  }
}

/* Dark scheme (Forced) */
/* Enabled if forced with data-theme="dark" */
[data-theme="dark"] {
  --primary:              ...;
  --primary-hover:        ...;
  --primary-focus:        ...;
  --primary-inverse:      ...;
}

/* (Common styles) */
:root {
  --primary-border:       var(--primary);
  --primary-hover-border: var(--primary-hover);
  --input-hover-border:   var(--primary);
  --input-focus:          var(--primary-focus);
  --input-inverse:        var(--primary-inverse);
}

You can find all the CSS variables used in the default theme here: css/default.css

Class-less version

For wild HTML purists!

Pico provide a .classless version (Example).

In this version, <header>, <main> and <footer> act as containers to define a centered or a fluid viewport.

Usage:

Use the default .classless version if you need centered viewports:

<link rel="stylesheet" href="css/pico.classless.min.css">

Or use the .fluid.classless version if you need a fluid container:

<link rel="stylesheet" href="css/pico.fluid.classless.min.css">

Containers

.container enable a centered viewport.
.container-fluid enable a 100% layout.

<body>
  <main class="container"></main>
</body>

Pico use the same breakpoints and viewports sizes as Bootstrap.

Device Extra small Small Medium Large Extra large
Breakpoint <576px ≥576px ≥768px ≥992px ≥1200px
Viewport None (auto) 540px 720px 960px 1140px

<header>, <main> and <footer> as direct childs of <body> provide a responsive vertical padding

<section> provide a responsive margin-bottom to separate your sections.

Grids

.grid enable a minimal grid system with auto-layout columns.

1
2
3
4
<div class="grid">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
</div>

Columns intentionally collapses below large devices (992px)

To go further, discover how to merge Pico with the Bootstrap grid system.

 More about grids

As Pico focus on native HTML elements, we kept this grid system very minimalist.

A full grid system in flexbox, with all the ordering, offsetting and breakpoints utilities can be heavier than the total size of the Pico library. Not really in the Pico spirit.

If you need a quick way to prototyping or build a complex layouts, you can look about Flexbox grid layouts. For example: Bootstrap Grid System only or Flexbox Grid.

If you need a light and custom grid, you can look about CSS Grid Generators. For example: CSS Grid Generator, Layoutit! or Griddy.

Alternatively you can Learn about CSS Grid.

Horizontal scroller

<figure> act as a container to make any content scrollable horizontally.

Useful to have responsives <table>

# Heading Heading Heading Heading Heading Heading Heading Heading Heading
1 Cell Cell Cell Cell Cell Cell Cell Cell Cell
2 Cell Cell Cell Cell Cell Cell Cell Cell Cell
3 Cell Cell Cell Cell Cell Cell Cell Cell Cell
<figure>
  <table>
    ...
  </table>
</figure>

Typography

All typographic elements are responsives, allowing text to scale gracefully across devices and viewport sizes.

Device Extra small Small Medium Large Extra large
Base font 16px 17px 18px 19px 20px
h1 32px 34px 36px 38px 40px
h2 28px 29px 31.5px 33.25px 35px
h3 24px 25.5px 27px 28.5px 30px
h4 20px 21.25px 22.5px 23.75px 25px
h5 18px 19.125px 20.25px 21.375px 22.5px
h6 16px 17px 18px 19px 20px

Headings:

Heading 1

Heading 2

Heading 3

Heading 4

Heading 5
Heading 6
<h1>Heading 1</h1>
<h2>Heading 2</h2>
<h3>Heading 3</h3>
<h4>Heading 4</h4>
<h5>Heading 5</h5>
<h6>Heading 6</h6>

Inside a <hgroup> all margin-bottom are collapsed and the :last-child is styled.

Heading 2

Subtitle for heading 2

<hgroup>
  <h2>Heading 2</h2>
  <h3>Subtitle for heading 2</h3>
<hgroup>

Inline text elements:

Abbr. abbr

Bold strong b

Italic i em cite

Deleted del

Inserted ins

Ctrl + S kbd

Highlighted mark

Strikethrough s

Small small

Text Sub sub

Text Sup sup

Underline u

Links come with .secondary and .contrast styles.

Primary
Secondary
Contrast
<a href="#">Primary</a>
<a href="#" class="secondary">Secondary</a>
<a href="#" class="contrast">Contrast</a>

Blockquote:

"Maecenas vehicula metus tellus, vitae congue turpis hendrerit non. Nam at dui sit amet ipsum cursus ornare."
- Phasellus eget lacinia
<blockquote>
  "Maecenas vehicula metus tellus, vitae congue turpis hendrerit non. Nam at dui sit amet ipsum cursus ornare."
  <footer>
    <cite>- Phasellus eget lacinia</cite>
  </footer>
</blockquote>

Buttons

The essential button in pure HTML, without .classes for the default style.

<button>Button</button>
<input type="submit">

Buttons are width: 100%; by default. Use <a role="button"> if you need an inline element.

Link Link
<a href="#" role="button">Link</a>
<a href="#" role="button">Link</a>

Buttons come with .secondary and .contrast styles.

Secondary Contrast
<a href="#" role="button" class="secondary">Secondary</a>
<a href="#" role="button" class="contrast">Contrast</a>

And a classic .outline variant.

Primary Secondary Contrast
<a href="#" role="button" class="outline">Primary</a>
<a href="#" role="button" class="secondary outline">Secondary</a>
<a href="#" role="button" class="contrast outline">Contrast</a>

Forms

All form elements in pure semantic HTML and fully responsives, allowing forms to scale gracefully across devices and viewport sizes.

Input are width: 100%; by default. You can use .grid inside a form.

All natives form elements are fully customized and themables with CSS variables.

We'll never share your email with anyone else.
<form>

  <!-- Grid -->
  <div class="grid">

    <!-- Markup example 1: input is inside label -->
    <label for="firstname">
      First name
      <input type="text" id="firstname" name="firstname" placeholder="First name" required>
    </label>

    <label for="lastname">
      Last name
      <input type="text" id="lastname" name="lastname" placeholder="Last name" required>
    </label>

  </div>

  <!-- Markup example 2: input is after label -->
  <label for="email">Email address</label>
  <input type="email" id="email" name="email" placeholder="Email address" required>
  <small>We'll never share your email with anyone else.</small>

  <!-- Button -->
  <button type="submit">Submit</button>

</form>

Disabled and validation states:

<input type="text" placeholder="Valid" aria-invalid="false">
<input type="text" placeholder="Invalid" aria-invalid="true">
<input type="text" placeholder="Disabled" disabled>
<input type="text" value="Readonly" readonly>

<fieldset> are unstyled and act as a container for radios and checkboxes providing a consistent margin-bottom for the set.

role="switch" on a type="checkbox" enable a custom switch.

Gender
<!-- Select -->
<label for="country">Country</label>
<select id="country">
  <option selected>Choose...</option>
  <option>...</option>
</select>

<!-- Radios -->
<fieldset>
  <legend>Gender</legend>
  <label for="male">
    <input type="radio" id="male" name="gender" value="male" checked>
    Male
  </label>
  <label for="female">
    <input type="radio" id="female" name="gender" value="female">
    Female
  </label>
  <label for="other">
    <input type="radio" id="other" name="gender" value="other">
    Other
  </label>
</fieldset>

<!-- Checkbox -->
<fieldset>
  <label for="terms">
    <input type="checkbox" id="terms" name="terms">
    I agree to the Terms and Conditions
  </label>
</fieldset>

<!-- Switch -->
<fieldset>
  <label for="switch">
    <input type="checkbox" id="switch" name="switch" role="switch">
    Publish on my profile
  </label>
</fieldset>

You can change a checkbox to indeterminate state by setting the indeterminate property to true

<script>
  document.getElementById('indeterminate-checkbox').indeterminate = true;
</script>

Others input types:

<!-- File browser -->
<label for="file">File browser
  <input type="file" id="file" name="file">
</label>

<!-- Range slider -->
<label for="range">Range slider
  <input type="range" min="0" max="100" value="50" id="range" name="range">
</label>

<!-- Date -->
<label for="date">Date
  <input type="date" id="date" name="date">
</label>

<!-- Time -->
<label for="time">Time
  <input type="time" id="time" name="time">
</label>

<!-- Color -->
<label for="color">Color
  <input type="color" id="color" name="color" value="#0eaaaa">
</label>

Tables

Default styles for tables without .classes

# Heading Heading Heading Heading Heading
1 Cell Cell Cell Cell Cell
2 Cell Cell Cell Cell Cell
3 Cell Cell Cell Cell Cell
<table>
  <thead>
    <tr>
      <th scope="col">#</th>
      <th scope="col">Heading</th>
      <th scope="col">Heading</th>
      <th scope="col">Heading</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">1</th>
      <td>Cell</td>
      <td>Cell</td>
      <td>Cell</td>
    </tr>
  </tbody>
</table>

role="grid" enable striped rows.

# Heading Heading Heading Heading Heading
1 Cell Cell Cell Cell Cell
2 Cell Cell Cell Cell Cell
3 Cell Cell Cell Cell Cell
<table role="grid">
  ...
</table>

Accordions

Toggle sections of content in pure HTML, without JavaScript.

Collapsible elements 1

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque urna diam, tincidunt nec porta sed, auctor id velit. Etiam venenatis nisl ut orci consequat, vitae tempus quam commodo. Nulla non mauris ipsum. Aliquam eu posuere orci. Nulla convallis lectus rutrum quam hendrerit, in facilisis elit sollicitudin. Mauris pulvinar pulvinar mi, dictum tristique elit auctor quis. Maecenas ac ipsum ultrices, porta turpis sit amet, congue turpis.

Collapsible elements 2
  • Vestibulum id elit quis massa interdum sodales.
  • Nunc quis eros vel odio pretium tincidunt nec quis neque.
  • Quisque sed eros non eros ornare elementum.
  • Cras sed libero aliquet, porta dolor quis, dapibus ipsum.
<details>
  <summary>Collapsible elements 1</summary>
  <p>...</p>
</details>

<details open>
  <summary>Collapsible elements 2</summary>
  <ul>
    <li>...</li>
    <li>...</li>
  </ul>
</details>

Cards

A flexible container with graceful spacings across devices and viewport sizes.

I'm a card!
<article>I'm a card!</article>

You can use <header> and footer <footer> inside <article>

Body
Footer
<article>
  Body
  <footer>Footer</footer>
</article>

Progress

Progress bar element in pure HTML, without JavaScript.

<progress value="25" max="100"></progress>

You can change a progress bar to indeterminate state by setting the indeterminate property to true

<script>
  document.getElementById('indeterminate-progress').indeterminate = true;
</script>

Tooltips

Enable tooltips everywhere in pure HTML, without JavaScript.

Tooltip on a link

Tooltip on inline element

<p>Tooltip on a <a href="#" data-tooltip="Tooltip">link</a></p>
<p>Tooltip on <em data-tooltip="Tooltip">inline element</em></p>
<p><button data-tooltip="Tooltip">Tooltip on a button</button></p>

We love .classes

As a starting point, Pico chose to be as neutral and semantic as possible using very few .classes

But off course, .classes are not a bad practice at all.

Feel free to use modifiers.

<button class="warning">Action</button>

Just try to keep your HTML clean and semantic to keep the Pico spirit.

<button class="button-red margin-large padding-medium">Action</button>