Files
foldsite/docs/content/styles/index.md
Tanishq Dubey ad81d7f3db
All checks were successful
Datadog Software Composition Analysis / Datadog SBOM Generation and Upload (push) Successful in 52s
Datadog Secrets Scanning / Datadog Static Analyzer (push) Successful in 1m1s
Datadog Static Analysis / Datadog Static Analyzer (push) Successful in 5m50s
docs refactor
2025-10-09 18:21:23 -04:00

771 lines
14 KiB
Markdown

---
version: "1.0"
date: "2025-01-15"
author: "DWS Foldsite Team"
title: "Styles Guide"
description: "Understanding Foldsite's CSS cascade system"
summary: "Learn how CSS styles cascade through your Foldsite project - from base styles to page-specific customizations."
quick_tips:
- "base.css is required and loaded on every page"
- "All matching styles are loaded (unlike templates where first match wins)"
- "Styles cascade down through directory structure like templates"
---
# Styles Guide
Foldsite's style system follows the same hierarchical logic as templates, allowing you to organize CSS in a maintainable, scalable way.
## The Style System
### Key Differences from Templates
| Templates | Styles |
|-----------|--------|
| **First match wins** | **All matches load** |
| One template per page | Multiple stylesheets per page |
| Must have at least one | base.css required |
**Why the difference?**
CSS is designed to cascade and layer. Loading multiple stylesheets allows you to:
- Share base styles
- Add section-specific styles
- Override with page-specific styles
## Required Style: base.css
Every Foldsite project **must have** `styles/base.css`.
This file is **loaded on every page**, providing:
- Typography
- Layout basics
- Color scheme
- Resets/normalizes
### Minimal base.css
```css
/* styles/base.css */
* {
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif;
line-height: 1.6;
color: #333;
max-width: 1200px;
margin: 0 auto;
padding: 2rem;
}
h1, h2, h3, h4, h5, h6 {
margin-top: 1.5em;
margin-bottom: 0.5em;
line-height: 1.2;
}
a {
color: #0066cc;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
img {
max-width: 100%;
height: auto;
}
```
## Style Discovery
Styles follow a **hierarchical discovery pattern** similar to templates.
### For File: `blog/my-post.md`
**All matching styles load (in order):**
1. **Base style** (always)
```
/styles/base.css
```
2. **Type + extension** styles (from root to specific)
```
/styles/__file.md.css
/styles/blog/__file.md.css
```
3. **Type + category** styles
```
/styles/__file.document.css
/styles/blog/__file.document.css
```
4. **Specific file** style
```
/styles/blog/my-post.md.css
```
**All found styles are included!**
### Rendered HTML
```html
<link rel="stylesheet" href="/styles/base.css">
<link rel="stylesheet" href="/styles/__file.md.css">
<link rel="stylesheet" href="/styles/blog/__file.md.css">
```
## Style Naming Patterns
### File Styles
Pattern: `__file.{extension}.css` or `__file.{category}.css`
```
styles/
├── __file.md.css # All markdown files
├── __file.document.css # All document files
├── __file.image.css # Individual images (rare)
└── __file.other.css # Other file types
```
### Folder Styles
Pattern: `__folder.{category}.css`
```
styles/
├── __folder.md.css # Folders with markdown
├── __folder.image.css # Photo galleries
└── __folder.html # Any folder view
```
### Specific Page Styles
Pattern: `{path/to/file}.css`
```
styles/
├── index.md.css # Only homepage
├── about.md.css # Only about page
└── blog/
└── special-post.md.css # One specific post
```
## Directory Structure
### Basic Structure
```
styles/
├── base.css # Required: Base styles
├── __file.md.css # Markdown file styles
└── __folder.image.css # Gallery styles
```
### Advanced Structure
```
styles/
├── base.css # Base
├── __file.md.css # General markdown
├── __folder.image.css # General galleries
├── blog/
│ ├── __file.md.css # Blog posts
│ └── __folder.md.css # Blog index
├── docs/
│ └── __file.md.css # Documentation
├── layouts/
│ ├── document.css # Document layout
│ ├── gallery.css # Gallery layout
│ └── landing.css # Landing pages
└── components/
├── navigation.css # Navigation
├── footer.css # Footer
└── breadcrumbs.css # Breadcrumbs
```
## Cascade & Specificity
### CSS Cascade Order
**Load order matters:**
1. `base.css` - Loaded first
2. General styles (`__file.md.css`)
3. Section styles (`blog/__file.md.css`)
4. Specific styles (`blog/my-post.md.css`)
**Later styles override earlier ones** (standard CSS behavior).
### Example Cascade
**Given page:** `blog/tutorial.md`
**Loaded styles:**
```html
<link rel="stylesheet" href="/styles/base.css">
<link rel="stylesheet" href="/styles/__file.md.css">
<link rel="stylesheet" href="/styles/blog/__file.md.css">
```
**base.css:**
```css
h1 {
color: black; /* Default */
}
```
**__file.md.css:**
```css
h1 {
color: #333; /* Slightly lighter */
}
```
**blog/__file.md.css:**
```css
h1 {
color: #0066cc; /* Blue - wins! */
}
```
**Result:** Blog headings are blue.
## Common Patterns
### Pattern 1: Base + Overrides
Start with comprehensive base, override as needed:
**base.css** - Everything
```css
/* Typography */
body { font-family: sans-serif; }
h1 { font-size: 2.5rem; }
h2 { font-size: 2rem; }
/* Layout */
.container { max-width: 1200px; }
/* Components */
nav { /* navigation styles */ }
footer { /* footer styles */ }
```
**blog/__file.md.css** - Blog-specific
```css
/* Override heading colors for blog */
h1 { color: #0066cc; }
/* Add blog-specific components */
.post-meta { /* metadata styles */ }
```
### Pattern 2: Modular Components
Split styles into reusable modules:
**base.css** - Minimal
```css
@import url('components/typography.css');
@import url('components/layout.css');
@import url('components/navigation.css');
```
**components/typography.css**
```css
body {
font-family: Georgia, serif;
line-height: 1.6;
}
h1 { font-size: 2.5rem; }
/* ... */
```
**components/navigation.css**
```css
nav {
display: flex;
justify-content: space-between;
}
/* ... */
```
### Pattern 3: Layout Variants
Different layouts for different sections:
**layouts/document.css**
```css
.document-layout {
display: grid;
grid-template-columns: 250px 1fr;
gap: 2rem;
}
.docs-sidebar { /* sidebar styles */ }
.docs-content { /* content styles */ }
```
**layouts/gallery.css**
```css
.gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 1rem;
}
.photo-item { /* photo card styles */ }
```
**Include in templates:**
```html
<!-- __file.md.html for docs -->
<link rel="stylesheet" href="/styles/layouts/document.css">
<div class="document-layout">
<!-- content -->
</div>
```
### Pattern 4: Responsive Design
Mobile-first approach:
```css
/* base.css - Mobile first */
body {
padding: 1rem;
}
.container {
display: block;
}
/* Tablet */
@media (min-width: 768px) {
body {
padding: 2rem;
}
.container {
display: grid;
grid-template-columns: 1fr 300px;
}
}
/* Desktop */
@media (min-width: 1200px) {
body {
padding: 3rem;
}
.container {
max-width: 1400px;
margin: 0 auto;
}
}
```
## Practical Examples
### Example 1: Blog Site
```
styles/
├── base.css # Site-wide styles
├── __file.md.css # General markdown
├── __folder.md.css # Folder listings
└── blog/
├── __file.md.css # Blog posts
└── __folder.md.css # Blog index
```
**base.css:**
```css
/* Basic layout and typography */
body {
font-family: Georgia, serif;
line-height: 1.6;
max-width: 800px;
margin: 0 auto;
padding: 2rem;
}
a { color: #0066cc; }
```
**__file.md.css:**
```css
/* Default markdown styles */
article {
margin: 2rem 0;
}
code {
background: #f4f4f4;
padding: 0.2em 0.4em;
border-radius: 3px;
}
pre {
background: #f4f4f4;
padding: 1rem;
overflow-x: auto;
}
```
**blog/__file.md.css:**
```css
/* Blog post specific */
.post-header {
border-bottom: 2px solid #eee;
padding-bottom: 1rem;
margin-bottom: 2rem;
}
.post-meta {
color: #666;
font-size: 0.9rem;
}
.post-tags {
margin-top: 2rem;
}
.tag {
display: inline-block;
padding: 0.25rem 0.75rem;
background: #f0f0f0;
border-radius: 3px;
margin-right: 0.5rem;
font-size: 0.85rem;
}
```
**blog/__folder.md.css:**
```css
/* Blog index */
.post-list {
list-style: none;
padding: 0;
}
.post-item {
margin: 2rem 0;
padding: 1.5rem;
border: 1px solid #eee;
border-radius: 4px;
}
.post-item:hover {
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
```
### Example 2: Photo Gallery
```
styles/
├── base.css
└── galleries/
└── __folder.image.css
```
**galleries/__folder.image.css:**
```css
.photo-gallery {
padding: 2rem;
}
.photo-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 1.5rem;
margin-top: 2rem;
}
.photo-item {
position: relative;
overflow: hidden;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
transition: transform 0.2s, box-shadow 0.2s;
}
.photo-item:hover {
transform: translateY(-4px);
box-shadow: 0 4px 16px rgba(0,0,0,0.15);
}
.photo-item img {
width: 100%;
height: auto;
display: block;
}
.photo-caption {
padding: 0.75rem;
background: white;
font-size: 0.85rem;
color: #666;
}
/* Responsive */
@media (max-width: 768px) {
.photo-grid {
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 1rem;
}
}
```
### Example 3: Documentation Site
```
styles/
├── base.css
├── layouts/
│ └── document.css
└── docs/
└── __file.md.css
```
**layouts/document.css:**
```css
.docs-layout {
display: grid;
grid-template-columns: 250px 1fr;
gap: 3rem;
max-width: 1400px;
margin: 0 auto;
}
.docs-sidebar {
position: sticky;
top: 2rem;
height: calc(100vh - 4rem);
overflow-y: auto;
}
.docs-content {
min-width: 0; /* Prevent grid blowout */
}
@media (max-width: 1024px) {
.docs-layout {
grid-template-columns: 1fr;
}
.docs-sidebar {
position: static;
height: auto;
}
}
```
**docs/__file.md.css:**
```css
.documentation {
max-width: 800px;
}
/* Table of contents */
.doc-toc {
background: #f8f8f8;
padding: 1rem;
border-radius: 4px;
margin: 2rem 0;
}
/* Code blocks */
.documentation pre {
background: #282c34;
color: #abb2bf;
padding: 1.5rem;
border-radius: 6px;
overflow-x: auto;
}
.documentation code {
font-family: 'Monaco', 'Courier New', monospace;
}
/* Callouts */
.note,
.warning,
.tip {
padding: 1rem 1.5rem;
margin: 1.5rem 0;
border-left: 4px solid;
border-radius: 4px;
}
.note {
background: #e3f2fd;
border-color: #2196f3;
}
.warning {
background: #fff3e0;
border-color: #ff9800;
}
.tip {
background: #e8f5e9;
border-color: #4caf50;
}
```
## CSS Variables
Use CSS custom properties for theming:
### base.css with Variables
```css
:root {
/* Colors */
--color-primary: #0066cc;
--color-secondary: #6c757d;
--color-text: #333;
--color-background: #fff;
--color-border: #dee2e6;
/* Typography */
--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif;
--font-serif: Georgia, serif;
--font-mono: 'Monaco', 'Courier New', monospace;
/* Spacing */
--space-xs: 0.5rem;
--space-sm: 1rem;
--space-md: 2rem;
--space-lg: 3rem;
/* Breakpoints (for reference) */
/* Use in @media queries */
}
body {
color: var(--color-text);
background: var(--color-background);
font-family: var(--font-sans);
}
a {
color: var(--color-primary);
}
/* ... */
```
### Dark Mode
```css
/* base.css */
@media (prefers-color-scheme: dark) {
:root {
--color-text: #e4e4e4;
--color-background: #1a1a1a;
--color-border: #333;
}
}
/* Or toggle with class */
body.dark-mode {
--color-text: #e4e4e4;
--color-background: #1a1a1a;
--color-border: #333;
}
```
## Performance Tips
### 1. Minimize File Size
```css
/* Remove unnecessary spaces/newlines in production */
/* Use a CSS minifier */
```
### 2. Avoid @import
```css
/* Slow - additional HTTP request */
@import url('components/typography.css');
/* Better - combine files or use build tool */
/* Or let browser load multiple <link> tags in parallel */
```
### 3. Optimize Selectors
```css
/* Fast */
.class-name { }
#id-name { }
/* Slower */
div > ul > li > a { }
[data-attribute="value"] { }
/* Use classes for styling */
```
### 4. Use Will-Change Sparingly
```css
/* Only for elements that will actually animate */
.photo-item {
transition: transform 0.2s;
}
.photo-item:hover {
transform: translateY(-4px);
will-change: transform; /* Hint to browser */
}
```
## Debugging Styles
### Browser DevTools
1. **Inspect element** - Right-click → Inspect
2. **Check computed styles** - See which rules apply
3. **See cascade** - Understand override order
4. **Live edit** - Test changes instantly
### Debug Checklist
**Styles not loading:**
- [ ] File exists in `styles/` directory
- [ ] Filename matches expected pattern
- [ ] No syntax errors in CSS
- [ ] Browser cache cleared
**Styles not applying:**
- [ ] Check CSS specificity
- [ ] Check cascade order
- [ ] Look for typos in selectors
- [ ] Verify HTML classes match CSS
**Wrong styles applying:**
- [ ] Check for conflicting rules
- [ ] Verify file loading order
- [ ] Look for !important (avoid if possible)
## Next Steps
- **[Templates Guide](../templates/)** - Templates use these styles
- **[Template Discovery](../templates/template-discovery.md)** - How styles are discovered
- **[Recipes](../recipes/)** - Complete examples with CSS
Master the style system to create beautiful, maintainable Foldsites!