folderweb/docs/02-tutorial/02-styling.md
Ruben 76697e4656 Add getting started documentation
Add tutorial on adding content

Add tutorial on styling

Add tutorial on templates

Add configuration reference

Add metadata reference

Add template variables reference

Add internationalization reference

Add plugin system documentation

Add creating templates documentation

Add index page
2025-11-27 23:01:02 +01:00

8.1 KiB

Styling Your Site

FolderWeb embraces modern CSS—no preprocessors, no build steps, just the good stuff browsers support today. Let's make your site look exactly how you want.

Where Styles Live

FolderWeb has a simple style hierarchy:

custom/
├── styles/
│   ├── base.css           # Your main stylesheet
│   └── custom-theme.css   # Additional stylesheets (optional)
└── content/
    └── my-page/
        └── styles.css     # Page-specific styles (optional)

Loading order:

  1. custom/styles/base.css — Your main styles (always loaded)
  2. Page-specific styles.css — If it exists in the content directory

Editing the Main Stylesheet

Start by editing custom/styles/base.css. This is where your site-wide styles live.

Default structure:

/* CSS Variables (Design Tokens) */
:root {
  --color-primary: oklch(60% 0.15 250);
  --color-text: oklch(20% 0 0);
  --color-bg: oklch(98% 0 0);
  --font-base: system-ui, -apple-system, sans-serif;
  --font-mono: 'SF Mono', Monaco, monospace;
  --spacing-unit: 1rem;
}

/* Base Typography */
body {
  font-family: var(--font-base);
  color: var(--color-text);
  background: var(--color-bg);
  line-height: 1.6;
}

/* More styles... */

Edit these values to match your brand. No build step, no compilation—just save and refresh.

Modern CSS Features

FolderWeb encourages using modern CSS features. Here's what you should know:

CSS Variables (Custom Properties)

Define once, use everywhere:

:root {
  --color-accent: oklch(65% 0.2 150);
  --radius-sm: 0.25rem;
  --shadow: 0 2px 8px oklch(0% 0 0 / 0.1);
}

.button {
  background: var(--color-accent);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
}

OKLCH Colors

Use modern color spaces for better color manipulation:

/* Traditional RGB/HSL */
--old: rgb(100, 150, 200);
--old-hsl: hsl(210, 50%, 60%);

/* Modern OKLCH (better perceptual uniformity) */
--new: oklch(65% 0.1 250);

Format: oklch(lightness chroma hue / alpha)

  • Lightness: 0% (black) to 100% (white)
  • Chroma: 0 (gray) to ~0.4 (vivid)
  • Hue: 0-360 degrees (color wheel)

CSS Nesting

Nest related styles without preprocessors:

.card {
  padding: 1rem;
  border-radius: 0.5rem;

  & h2 {
    margin-top: 0;
  }

  & p {
    color: var(--color-text-muted);
  }

  &:hover {
    box-shadow: var(--shadow-lg);
  }
}

Fluid Typography with clamp()

Responsive sizing without media queries:

h1 {
  /* Min 2rem, ideal 5vw, max 4rem */
  font-size: clamp(2rem, 5vw, 4rem);
}

p {
  /* Min 1rem, ideal 1.125rem, max 1.25rem */
  font-size: clamp(1rem, 1.125rem, 1.25rem);
}

Logical Properties

Use logical properties for better internationalization:

/* Old way (assumes left-to-right) */
.old {
  margin-left: 1rem;
  padding-right: 2rem;
}

/* New way (respects text direction) */
.new {
  margin-inline-start: 1rem;
  padding-inline-end: 2rem;
}

Common logical properties:

  • margin-inline-start / margin-inline-end (left/right in LTR)
  • margin-block-start / margin-block-end (top/bottom)
  • padding-inline / padding-block
  • inline-size (width)
  • block-size (height)

Grid Layout

Use CSS Grid for layout (not flexbox for everything):

.page-layout {
  display: grid;
  grid-template-columns: 1fr min(65ch, 100%) 1fr;
  gap: 2rem;

  & > * {
    grid-column: 2;
  }

  & > .full-width {
    grid-column: 1 / -1;
  }
}

Classless CSS Philosophy

FolderWeb defaults to classless CSS—styling HTML elements directly instead of adding classes everywhere.

Good (classless):

<article>
  <h1>Page Title</h1>
  <p>Content here.</p>
</article>
article {
  max-width: 65ch;
  margin: 0 auto;

  & h1 {
    font-size: 2.5rem;
    margin-bottom: 1rem;
  }

  & p {
    line-height: 1.7;
  }
}

Less good (class-heavy):

<article class="article-container">
  <h1 class="article-title">Page Title</h1>
  <p class="article-text">Content here.</p>
</article>

When to use classes:

  • Component variants (.button-primary, .button-secondary)
  • JavaScript hooks (.js-toggle)
  • Utility overrides (.visually-hidden)

Page-Specific Styles

Add styles.css to a content directory for page-specific styling:

content/portfolio/
├── index.md
└── styles.css

styles.css:

/* Scoped to this page only */
.portfolio-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 2rem;
}

FolderWeb automatically loads and includes page-specific styles with cache-busting:

<link rel="stylesheet" href="/portfolio/styles.css?v=abc123def">

Dark Mode

Add dark mode with CSS variables and prefers-color-scheme:

:root {
  --color-bg: oklch(98% 0 0);
  --color-text: oklch(20% 0 0);
}

@media (prefers-color-scheme: dark) {
  :root {
    --color-bg: oklch(15% 0 0);
    --color-text: oklch(95% 0 0);
  }
}

All colors using the variables automatically adapt.

Responsive Design

Use fluid layouts and relative units:

/* Bad: fixed breakpoints */
@media (min-width: 768px) {
  .container {
    width: 750px;
  }
}

/* Good: fluid and flexible */
.container {
  width: min(90%, 1200px);
  padding: clamp(1rem, 3vw, 3rem);
}

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  gap: clamp(1rem, 3vw, 2rem);
}

Use media queries sparingly:

  • Layout changes (sidebar position)
  • Font size adjustments
  • Complex interactions

Prefer fluid CSS:

  • Spacing (clamp())
  • Typography (clamp())
  • Grids (auto-fit, minmax())

Cache Busting

FolderWeb automatically versions CSS files with MD5 hashes:

<link rel="stylesheet" href="/custom/styles/base.css?v=a1b2c3d4">

When you edit your CSS, the hash changes and browsers fetch the new version. No manual cache clearing needed.

Practical Examples

Simple Blog Theme

:root {
  --color-accent: oklch(55% 0.15 220);
  --color-text: oklch(25% 0 0);
  --color-bg: oklch(99% 0 0);
  --max-width: 65ch;
}

body {
  font-family: Georgia, serif;
  color: var(--color-text);
  background: var(--color-bg);
  padding: 2rem 1rem;
}

article {
  max-width: var(--max-width);
  margin: 0 auto;

  & h1 {
    font-size: clamp(2rem, 5vw, 3rem);
    color: var(--color-accent);
  }

  & p {
    line-height: 1.8;
    margin-bottom: 1.5rem;
  }
}

Portfolio Grid

.project-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  gap: 2rem;
  padding: 2rem 0;
}

.project-card {
  border-radius: 0.5rem;
  overflow: hidden;
  box-shadow: 0 2px 8px oklch(0% 0 0 / 0.1);
  transition: transform 0.2s;

  &:hover {
    transform: translateY(-4px);
    box-shadow: 0 4px 16px oklch(0% 0 0 / 0.15);
  }

  & img {
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
  }

  & h3 {
    padding: 1rem;
    margin: 0;
  }
}

Documentation Site

:root {
  --sidebar-width: 250px;
}

.docs-layout {
  display: grid;
  grid-template-columns: var(--sidebar-width) 1fr;
  gap: 3rem;
  max-width: 1400px;
  margin: 0 auto;

  @media (max-width: 900px) {
    grid-template-columns: 1fr;
  }
}

.sidebar nav {
  position: sticky;
  top: 2rem;

  & ul {
    list-style: none;
    padding: 0;
  }

  & a {
    display: block;
    padding: 0.5rem 1rem;
    text-decoration: none;
    border-radius: 0.25rem;

    &:hover {
      background: var(--color-bg-hover);
    }
  }
}

Tips

  • Start simple: Edit colors and fonts first, then tackle layout
  • Use the inspector: Browser dev tools show computed values and help debug
  • Test in different browsers: Modern CSS has excellent support, but always verify
  • Keep it readable: Future you will thank present you for clear, organized styles

What's Next?

Now that you can style your site, learn how to:

Or explore the Reference for detailed documentation on all available template variables and hooks.