433 lines
8.1 KiB
Markdown
433 lines
8.1 KiB
Markdown
|
|
# 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
|
||
|
|
/* 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:
|
||
|
|
|
||
|
|
```css
|
||
|
|
: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:
|
||
|
|
|
||
|
|
```css
|
||
|
|
/* 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:
|
||
|
|
|
||
|
|
```css
|
||
|
|
.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:
|
||
|
|
|
||
|
|
```css
|
||
|
|
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:
|
||
|
|
|
||
|
|
```css
|
||
|
|
/* 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):
|
||
|
|
|
||
|
|
```css
|
||
|
|
.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):**
|
||
|
|
```html
|
||
|
|
<article>
|
||
|
|
<h1>Page Title</h1>
|
||
|
|
<p>Content here.</p>
|
||
|
|
</article>
|
||
|
|
```
|
||
|
|
|
||
|
|
```css
|
||
|
|
article {
|
||
|
|
max-width: 65ch;
|
||
|
|
margin: 0 auto;
|
||
|
|
|
||
|
|
& h1 {
|
||
|
|
font-size: 2.5rem;
|
||
|
|
margin-bottom: 1rem;
|
||
|
|
}
|
||
|
|
|
||
|
|
& p {
|
||
|
|
line-height: 1.7;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Less good (class-heavy):**
|
||
|
|
```html
|
||
|
|
<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:**
|
||
|
|
```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:
|
||
|
|
|
||
|
|
```html
|
||
|
|
<link rel="stylesheet" href="/portfolio/styles.css?v=abc123def">
|
||
|
|
```
|
||
|
|
|
||
|
|
## Dark Mode
|
||
|
|
|
||
|
|
Add dark mode with CSS variables and `prefers-color-scheme`:
|
||
|
|
|
||
|
|
```css
|
||
|
|
: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:
|
||
|
|
|
||
|
|
```css
|
||
|
|
/* 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:
|
||
|
|
|
||
|
|
```html
|
||
|
|
<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
|
||
|
|
|
||
|
|
```css
|
||
|
|
: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
|
||
|
|
|
||
|
|
```css
|
||
|
|
.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
|
||
|
|
|
||
|
|
```css
|
||
|
|
: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:
|
||
|
|
- **[Create custom templates](#)** — Control HTML structure and layout
|
||
|
|
- **[Add multilingual support](#)** — Style for different languages and text directions
|
||
|
|
|
||
|
|
Or explore the [Reference](#) for detailed documentation on all available template variables and hooks.
|