Skip to content

ExpressiveCSS

Browse documentation

Layout templates

Preview and copy complete app layouts with navigation, panes, and responsive grids.

View as Markdown

Choose a layout

Choose a structure, preview it, and copy the complete HTML into your project. These templates use ExpressiveCSS navigation, panes, and grid classes.

Compact app

One content column with a bottom navigation bar. Use it for a small app or a focused mobile screen.

Navigation rail

A collapsed rail beside your content from 600px. Compact windows use the bottom navigation bar.

Expanded rail

An expanded rail for destinations with longer labels. Below 840px, the bottom navigation bar takes over.

List-detail

A selectable list beside its detail from 840px. Narrow windows show one pane, with a Back action and keyboard focus recovery.

Dashboard

A navigation rail with a responsive card grid and activity list. Cards stack as the content area narrows.

Copy and run

To run a template:

  1. Download it as index.html.
  2. Put the framework's complete dist/ directory beside it, including fonts.
  3. Open the HTML file.

From a built repository checkout:

mkdir my-site
cp docs/public/layout-rail.html my-site/index.html
cp -R dist my-site/dist

For an npm installation, copy the package's built assets:

cp -R node_modules/@expressivecss/expressive/dist my-site/dist

Replace the sample content and documentation destinations with your application's URLs. Every template follows your system theme. Change theme="auto" to light or dark for a fixed scheme.

Compact app

One content column with a bottom navigation bar. Use it for a small app or a focused mobile screen.

Copy complete HTML
<!doctype html>
<html lang="en" theme="auto">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Compact app | My project</title>
  <!-- Copy this file as index.html beside the framework's complete dist directory. -->
  <link rel="stylesheet" href="dist/css/expressive.min.css">
  <style>
    body { margin: 0; }
    .app-shell { display: grid; grid-template-columns: minmax(0, 1fr); min-height: 100dvh; }
    .app-content { display: flex; flex-direction: column; min-width: 0; min-height: 100dvh; }
    main { flex: 1; min-width: 0; }
    .app-navigation { position: sticky; bottom: 0; }
  </style>
</head>
<body>
  <div class="app-shell">
    <div class="app-content">
      <header>
        <div class="bar">
          <h2>My project</h2>
          <a class="button text" href="https://www.expressivecss.com/">Docs</a>
        </div>
      </header>
      <main id="main" class="container py-4" style="max-width: 600px" tabindex="-1">
        <h1>Overview</h1>
        <p class="flow-text">A place for your project's content.</p>
        <article class="outlined mb-4">
          <h2>Welcome back</h2>
          <p>Replace this content with your own. The layout uses ExpressiveCSS components and spacing helpers.</p>
          <div class="actions">
            <a class="button filled" href="https://www.expressivecss.com/">Start building</a>
          </div>
        </article>
        <h2>Next steps</h2>
        <ul class="list">
          <li><a href="https://www.expressivecss.com/themes.html"><div>Choose your theme<p>Use the system scheme or choose light or dark.</p></div></a></li>
          <li><a href="https://www.expressivecss.com/grid.html"><div>Arrange your content<p>Use the responsive grid for your page sections.</p></div></a></li>
          <li><a href="https://www.expressivecss.com/auto-init.html"><div>Add interactions<p>AutoInit starts the components in your markup.</p></div></a></li>
        </ul>
      </main>
      <!-- Replace these documentation destinations with your application's URLs. -->
      <footer class="app-navigation">
        <nav class="navigation-bar" aria-label="Primary navigation">
          <a href="#main" aria-current="page"><span class="material-symbols" aria-hidden="true">home</span>Overview</a>
          <a href="https://www.expressivecss.com/buttons.html"><span class="material-symbols" aria-hidden="true">widgets</span>Components</a>
          <a href="https://www.expressivecss.com/"><span class="material-symbols" aria-hidden="true">help</span>Setup</a>
        </nav>
      </footer>
    </div>
  </div>
  <script src="dist/js/expressive.min.js"></script>
  <script>
    document.addEventListener('DOMContentLoaded', () => {
      Expressive.AutoInit();
    });
  </script>
</body>
</html>

Navigation rail

A collapsed rail beside your content from 600px. Compact windows use the bottom navigation bar.

Copy complete HTML
<!doctype html>
<html lang="en" theme="auto">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Navigation rail app | My project</title>
  <!-- Copy this file as index.html beside the framework's complete dist directory. -->
  <link rel="stylesheet" href="dist/css/expressive.min.css">
  <style>
    body { margin: 0; }
    .app-shell { display: grid; grid-template-columns: minmax(0, 1fr); min-height: 100dvh; }
    .app-content { display: flex; flex-direction: column; min-width: 0; min-height: 100dvh; }
    main { flex: 1; min-width: 0; }
    .app-navigation { position: sticky; bottom: 0; }
    .navigation-rail { position: sticky; top: 0; height: 100dvh; align-self: start; overflow-y: auto; }
    @media (width >= 600px) { .app-shell { grid-template-columns: auto minmax(0, 1fr); } }
  </style>
</head>
<body>
  <div class="app-shell">
    <nav class="navigation-rail hide-on-compact-only" aria-label="Primary navigation">
      <button type="button" aria-label="Toggle navigation"><span class="material-symbols" aria-hidden="true">menu</span></button>
      <a href="#main" aria-current="page"><span class="material-symbols" aria-hidden="true">home</span>Overview</a>
      <a href="https://www.expressivecss.com/buttons.html"><span class="material-symbols" aria-hidden="true">widgets</span>Components</a>
      <a href="https://www.expressivecss.com/"><span class="material-symbols" aria-hidden="true">help</span>Setup</a>
    </nav>
    <div class="app-content">
      <header>
        <div class="bar">
          <h2>My project</h2>
          <a class="button text" href="https://www.expressivecss.com/">Docs</a>
        </div>
      </header>
      <main id="main" class="container py-4" tabindex="-1">
        <h1>Overview</h1>
        <p class="flow-text">A place for your project's content.</p>
        <article class="outlined mb-4">
          <h2>Welcome back</h2>
          <p>Replace this content with your own. The layout uses ExpressiveCSS components and spacing helpers.</p>
          <div class="actions">
            <a class="button filled" href="https://www.expressivecss.com/">Start building</a>
          </div>
        </article>
        <h2>Next steps</h2>
        <ul class="list">
          <li><a href="https://www.expressivecss.com/themes.html"><div>Choose your theme<p>Use the system scheme or choose light or dark.</p></div></a></li>
          <li><a href="https://www.expressivecss.com/grid.html"><div>Arrange your content<p>Use the responsive grid for your page sections.</p></div></a></li>
          <li><a href="https://www.expressivecss.com/auto-init.html"><div>Add interactions<p>AutoInit starts the components in your markup.</p></div></a></li>
        </ul>
      </main>
      <!-- Replace these documentation destinations with your application's URLs. -->
      <footer class="app-navigation hide-on-med-and-up">
        <nav class="navigation-bar" aria-label="Compact navigation">
          <a href="#main" aria-current="page"><span class="material-symbols" aria-hidden="true">home</span>Overview</a>
          <a href="https://www.expressivecss.com/buttons.html"><span class="material-symbols" aria-hidden="true">widgets</span>Components</a>
          <a href="https://www.expressivecss.com/"><span class="material-symbols" aria-hidden="true">help</span>Setup</a>
        </nav>
      </footer>
    </div>
  </div>
  <script src="dist/js/expressive.min.js"></script>
  <script>
    document.addEventListener('DOMContentLoaded', () => {
      Expressive.AutoInit();
    });
  </script>
</body>
</html>

Expanded rail

An expanded rail for destinations with longer labels. Below 840px, the bottom navigation bar takes over.

Copy complete HTML
<!doctype html>
<html lang="en" theme="auto">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Expanded rail app | My project</title>
  <!-- Copy this file as index.html beside the framework's complete dist directory. -->
  <link rel="stylesheet" href="dist/css/expressive.min.css">
  <style>
    body { margin: 0; }
    .app-shell { display: grid; grid-template-columns: minmax(0, 1fr); min-height: 100dvh; }
    .app-content { display: flex; flex-direction: column; min-width: 0; min-height: 100dvh; }
    main { flex: 1; min-width: 0; }
    .app-navigation { position: sticky; bottom: 0; }
    .navigation-rail { position: sticky; top: 0; height: 100dvh; align-self: start; overflow-y: auto; }
    @media (width >= 840px) { .app-shell { grid-template-columns: auto minmax(0, 1fr); } }
  </style>
</head>
<body>
  <div class="app-shell">
    <nav class="navigation-rail expanded hide-on-med-and-down" aria-label="Primary navigation">
      <button type="button" aria-label="Toggle navigation"><span class="material-symbols" aria-hidden="true">menu</span></button>
      <a href="#main" aria-current="page"><span class="material-symbols" aria-hidden="true">home</span>Overview</a>
      <a href="https://www.expressivecss.com/buttons.html"><span class="material-symbols" aria-hidden="true">widgets</span>Components</a>
      <a href="https://www.expressivecss.com/"><span class="material-symbols" aria-hidden="true">help</span>Setup</a>
    </nav>
    <div class="app-content">
      <header>
        <div class="bar">
          <h2>My project</h2>
          <a class="button text" href="https://www.expressivecss.com/">Docs</a>
        </div>
      </header>
      <main id="main" class="container py-4" tabindex="-1">
        <h1>Overview</h1>
        <p class="flow-text">A place for your project's content.</p>
        <article class="outlined mb-4">
          <h2>Welcome back</h2>
          <p>Replace this content with your own. The layout uses ExpressiveCSS components and spacing helpers.</p>
          <div class="actions">
            <a class="button filled" href="https://www.expressivecss.com/">Start building</a>
          </div>
        </article>
        <h2>Next steps</h2>
        <ul class="list">
          <li><a href="https://www.expressivecss.com/themes.html"><div>Choose your theme<p>Use the system scheme or choose light or dark.</p></div></a></li>
          <li><a href="https://www.expressivecss.com/grid.html"><div>Arrange your content<p>Use the responsive grid for your page sections.</p></div></a></li>
          <li><a href="https://www.expressivecss.com/auto-init.html"><div>Add interactions<p>AutoInit starts the components in your markup.</p></div></a></li>
        </ul>
      </main>
      <!-- Replace these documentation destinations with your application's URLs. -->
      <footer class="app-navigation hide-on-expanded-and-up">
        <nav class="navigation-bar" aria-label="Compact navigation">
          <a href="#main" aria-current="page"><span class="material-symbols" aria-hidden="true">home</span>Overview</a>
          <a href="https://www.expressivecss.com/buttons.html"><span class="material-symbols" aria-hidden="true">widgets</span>Components</a>
          <a href="https://www.expressivecss.com/"><span class="material-symbols" aria-hidden="true">help</span>Setup</a>
        </nav>
      </footer>
    </div>
  </div>
  <script src="dist/js/expressive.min.js"></script>
  <script>
    document.addEventListener('DOMContentLoaded', () => {
      Expressive.AutoInit();
    });
  </script>
</body>
</html>

List-detail

A selectable list beside its detail from 840px. Narrow windows show one pane, with a Back action and keyboard focus recovery.

Copy complete HTML
<!doctype html>
<html lang="en" theme="auto">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>List-detail | My project</title>
  <!-- Copy this file as index.html beside the framework's complete dist directory. -->
  <link rel="stylesheet" href="dist/css/expressive.min.css">
  <style>
    body { display: flex; flex-direction: column; height: 100dvh; margin: 0; }
    .workspace { flex: 1; min-height: 0; container-type: inline-size; }
  </style>
</head>
<body>
  <header>
    <div class="bar">
      <h2>My project</h2>
      <a class="button text" href="https://www.expressivecss.com/">Docs</a>
    </div>
  </header>
  <main id="main" class="workspace">
    <div class="list-detail">
      <section id="items" class="list-pane active" aria-labelledby="items-title">
        <header><h1 id="items-title">Reading list</h1></header>
        <ul class="list">
          <li><a href="#detail" aria-current="true" data-title="Plan your next project" data-body="Write down the task your users need to complete. Choose a layout that gives that task enough space."><div>Plan your next project<p>Start with the user's task.</p></div></a></li>
          <li><a href="#detail" data-title="Choose your components" data-body="Use lists for indexes and cards for distinct items. Give every control an accessible name and a real action."><div>Choose your components<p>Use the framework's documented markup.</p></div></a></li>
          <li><a href="#detail" data-title="Test the compact view" data-body="Resize the window below 840px. Select an item to show its detail, then use Back to return to the list."><div>Test the compact view<p>Keep navigation and content reachable.</p></div></a></li>
        </ul>
      </section>
      <section id="detail" class="detail-pane" aria-labelledby="detail-title">
        <header>
          <button id="back" type="button" class="hide-on-expanded-and-up" aria-label="Back to reading list">
            <span class="material-symbols" aria-hidden="true">arrow_back</span>
          </button>
          <h2 id="detail-title" tabindex="-1">Plan your next project</h2>
        </header>
        <div><p id="detail-body">Write down the task your users need to complete. Choose a layout that gives that task enough space.</p></div>
      </section>
    </div>
  </main>
  <script src="dist/js/expressive.min.js"></script>
  <script>
    document.addEventListener('DOMContentLoaded', () => {
      Expressive.AutoInit();
      // Panes are CSS layouts. The application owns selection and focus.
      const items = document.getElementById('items');
      const detail = document.getElementById('detail');
      const title = document.getElementById('detail-title');
      items.addEventListener('click', (event) => {
        const link = event.target.closest('a[data-title]');
        if (!link) return;
        event.preventDefault();
        items.querySelector('[aria-current]')?.removeAttribute('aria-current');
        link.setAttribute('aria-current', 'true');
        title.textContent = link.dataset.title;
        document.getElementById('detail-body').textContent = link.dataset.body;
        items.classList.remove('active');
        detail.classList.add('active');
        title.focus();
      });
      document.getElementById('back').addEventListener('click', () => {
        detail.classList.remove('active');
        items.classList.add('active');
        items.querySelector('[aria-current]').focus();
      });
    });
  </script>
</body>
</html>

Dashboard

A navigation rail with a responsive card grid and activity list. Cards stack as the content area narrows.

Copy complete HTML
<!doctype html>
<html lang="en" theme="auto">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Dashboard | My project</title>
  <!-- Copy this file as index.html beside the framework's complete dist directory. -->
  <link rel="stylesheet" href="dist/css/expressive.min.css">
  <style>
    body { margin: 0; }
    .app-shell { display: grid; grid-template-columns: minmax(0, 1fr); min-height: 100dvh; }
    .app-content { display: flex; flex-direction: column; min-width: 0; min-height: 100dvh; }
    main { flex: 1; min-width: 0; }
    .app-navigation { position: sticky; bottom: 0; }
    .navigation-rail { position: sticky; top: 0; height: 100dvh; align-self: start; overflow-y: auto; }
    @media (width >= 600px) { .app-shell { grid-template-columns: auto minmax(0, 1fr); } }
  </style>
</head>
<body>
  <div class="app-shell">
    <nav class="navigation-rail hide-on-compact-only" aria-label="Primary navigation">
      <button type="button" aria-label="Toggle navigation"><span class="material-symbols" aria-hidden="true">menu</span></button>
      <a href="#main" aria-current="page"><span class="material-symbols" aria-hidden="true">home</span>Overview</a>
      <a href="https://www.expressivecss.com/buttons.html"><span class="material-symbols" aria-hidden="true">widgets</span>Components</a>
      <a href="https://www.expressivecss.com/"><span class="material-symbols" aria-hidden="true">help</span>Setup</a>
    </nav>
    <div class="app-content">
      <header>
        <div class="bar">
          <h2>My project</h2>
          <a class="button text" href="https://www.expressivecss.com/">Docs</a>
        </div>
      </header>
      <main id="main" class="container py-4" tabindex="-1">
        <h1>Project overview</h1>
        <p class="flow-text">Sample data. Replace these values with your project's metrics.</p>
        <div class="row mb-4">
          <div class="s12 m6 l4"><article class="filled"><h2>Active projects</h2><p class="headline-large">12</p><p>Projects currently in progress.</p></article></div>
          <div class="s12 m6 l4"><article class="filled"><h2>Completed tasks</h2><p class="headline-large">48</p><p>Tasks completed this month.</p></article></div>
          <div class="s12 m6 l4"><article class="filled"><h2>Team members</h2><p class="headline-large">8</p><p>People working on the project.</p></article></div>
        </div>
        <div class="row">
          <div class="s12 l8">
            <h2>Recent activity</h2>
            <ul class="list">
              <li><div>Project created<p>Your workspace is ready for content.</p></div></li>
              <li><div>Layout selected<p>Cards stack as the window narrows.</p></div></li>
              <li><div>Theme configured<p>The system scheme controls light and dark mode.</p></div></li>
            </ul>
          </div>
          <div class="s12 l4">
            <article class="outlined">
              <h2>Build your next screen</h2>
              <p>Choose components for the task your users need to complete.</p>
              <div class="actions"><a class="button filled" href="https://www.expressivecss.com/">Browse components</a></div>
            </article>
          </div>
        </div>
      </main>
      <!-- Replace these documentation destinations with your application's URLs. -->
      <footer class="app-navigation hide-on-med-and-up">
        <nav class="navigation-bar" aria-label="Compact navigation">
          <a href="#main" aria-current="page"><span class="material-symbols" aria-hidden="true">home</span>Overview</a>
          <a href="https://www.expressivecss.com/buttons.html"><span class="material-symbols" aria-hidden="true">widgets</span>Components</a>
          <a href="https://www.expressivecss.com/"><span class="material-symbols" aria-hidden="true">help</span>Setup</a>
        </nav>
      </footer>
    </div>
  </div>
  <script src="dist/js/expressive.min.js"></script>
  <script>
    document.addEventListener('DOMContentLoaded', () => {
      Expressive.AutoInit();
    });
  </script>
</body>
</html>

No matching pages

  • Source color

    The seed every generated ramp derives from. Pick one and browse the docs — the whole theme follows. Error does not: it is a fixed hue.

    Default source: Mist Iris.

    ExpressiveCSS presets: Lagoon, Harbor, Breeze, Cobalt, Iris.

    Bold

    Soft

    Mist

    Glow