npm package: @soyleninjs/postcss-flow
Description: PostCSS plugin for creating fluid and responsive CSS values with granular breakpoint control using the flow() function
Author: Lenin
Latest version: 1.0.0

<div align="center">

# PostCSS Flow

**A PostCSS plugin for creating fluid and responsive CSS values with granular breakpoint control**

[![npm version](https://img.shields.io/npm/v/@soyleninjs/postcss-flow.svg)](https://www.npmjs.com/package/@soyleninjs/postcss-flow)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
[![PostCSS](https://img.shields.io/badge/PostCSS-8+-red.svg)](https://postcss.org/)

[Features](#-features) • [Installation](#-installation) • [Usage](#-usage) • [Examples](#-examples) • [Contributing](#-contributing)

</div>

---

## What is PostCSS Flow?

PostCSS Flow is a powerful plugin that simplifies responsive design by transforming a simple `flow()` function into fluid CSS values with automatic media queries. Write responsive styles in a single line instead of managing multiple breakpoints manually.

### Before (Traditional CSS)
```css
.heading {
  font-size: clamp(20px, calc(20px + (30 - 20) * ((100vw - 834px) / 606)), 30px);
}
@media (width <= 834px) {
  .heading {
    font-size: clamp(10px, calc(10px + (20 - 10) * ((100vw - 360px) / 474)), 20px);
  }
}
```

### After (With PostCSS Flow)
```css
.heading {
  font-size: flow(10-360, 20-834, 30-1440);
}
```

---

## Features

- **Fluid Values**: Automatically generates `clamp()` functions with linear interpolation
- **Fixed Values**: Define fixed breakpoints with the `-0` suffix
- **Desktop First**: Exclusive desktop-first approach with automatic breakpoint sorting
- **Auto-Sorting**: Breakpoints are automatically ordered from largest to smallest viewport
- **Auto Media Queries**: Generates necessary media queries using `width <=`
- **Simple Syntax**: One line instead of multiple declarations and media queries
- **Zero Dependencies**: Lightweight and efficient

---

## Installation

Install via npm:

```bash
npm install @soyleninjs/postcss-flow --save-dev
```

Or using yarn:

```bash
yarn add @soyleninjs/postcss-flow --dev
```

Or using pnpm:

```bash
pnpm add @soyleninjs/postcss-flow --save-dev
```

---

## Usage

### 1. Add to PostCSS Config

Add the plugin to your PostCSS configuration:

**postcss.config.js** (Array syntax)
```js
module.exports = {
  plugins: [
    require('@soyleninjs/postcss-flow'),
    // other plugins...
  ]
}
```

**postcss.config.js** (Object syntax)
```js
module.exports = {
  plugins: {
    '@soyleninjs/postcss-flow': {},
    // other plugins...
  }
}
```

### 2. Use in Your CSS

```css
.element {
  property: flow(value1-viewport1, value2-viewport2, value3-viewport3);
}
```

### 3. Recommended: Combine with postcss-sort-media-queries

For optimal results, we recommend using PostCSS Flow together with [postcss-sort-media-queries](https://www.npmjs.com/package/postcss-sort-media-queries). This plugin will organize and merge all generated media queries, resulting in cleaner and more optimized CSS output.

**Installation:**
```bash
npm install postcss-sort-media-queries --save-dev
```

**Configuration:**
```js
module.exports = {
  plugins: [
    require('@soyleninjs/postcss-flow'),
    require('postcss-sort-media-queries')({
      sort: 'desktop-first' // Matches PostCSS Flow's approach
    }),
    // other plugins...
  ]
}
```

**Note:** While not required, this combination significantly improves your final CSS structure by consolidating media queries and reducing duplication.

---

## Syntax

### Basic Syntax

```
flow(value-viewport[, value-viewport-isFluid]*)
```

### Parameters

Each breakpoint is defined with the format:

| Format | Description |
|--------|-------------|
| `value-viewport` | Creates a fluid value between breakpoints |
| `value-viewport-0` | Creates a fixed (non-fluid) value at that breakpoint |

**Parameter details:**
- **value**: Numeric value (unitless, automatically converted to px)
- **viewport**: Viewport width in pixels
- **isFluid** (optional): Omit or use any value except `0` for fluid. Use `0` for fixed.

### Desktop First Approach

The plugin works exclusively with a **Desktop First** approach, starting from the largest viewport and going down to smaller ones. Breakpoints are automatically sorted to ensure this behavior.

**Important:** The order you write breakpoints doesn't matter - they're automatically sorted from largest to smallest viewport!

---

## Examples

### Example 1: Basic Fluid Values

Transform a single line into fluid typography:

**Input:**
```css
.heading {
  font-size: flow(10-360, 20-834, 30-1440);
}
```

**Output:**
```css
.heading {
  font-size: clamp(20px, calc(20px + (30 - 20) * ((100vw - 834px) / 606)), 30px);
}
@media (width <= 834px) {
  .heading {
    font-size: clamp(10px, calc(10px + (20 - 10) * ((100vw - 360px) / 474)), 20px);
  }
}
```

**What happens:**
- From 1440px and up: Fluid scaling from 20px to 30px
- At 834px and below: Fluid scaling from 10px to 20px

---

### Example 2: Combining Fluid and Fixed Values

Mix fluid and fixed breakpoints for precise control. Using `-0` makes a breakpoint **fixed (non-fluid)** from that viewport down to the next breakpoint:

**Input:**
```css
.container {
  padding: flow(10-360, 20-834-0, 30-1440);
}
```

**Output:**
```css
.container {
  padding: clamp(20px, calc(20px + (30 - 20) * ((100vw - 834px) / 606)), 30px);
}
@media (width <= 360px) {
  .container {
    padding: 10px;
  }
}
```

**What happens:**
- From 1440px down to 834px: Fluid scaling from 30px to 20px
- At 834px (marked with `-0`): The value becomes fixed at 20px
- From 834px down to 360px: Stays fixed at 20px (no fluid interpolation)
- At 360px and below: Fixed 10px

The `-0` suffix prevents fluid interpolation **from that breakpoint downwards**, creating a fixed value zone.

---

### Example 3: Automatic Breakpoint Sorting

Don't worry about the order - write breakpoints in any order you want:

**Input:**
```css
.text {
  font-size: flow(20-834, 10-360, 30-1440);
}
```

**Output:**
```css
.text {
  font-size: clamp(20px, calc(20px + (30 - 20) * ((100vw - 834px) / 606)), 30px);
}
@media (width <= 834px) {
  .text {
    font-size: clamp(10px, calc(10px + (20 - 10) * ((100vw - 360px) / 474)), 20px);
  }
}
```

The plugin automatically sorts: `30-1440` → `20-834` → `10-360`

---

### Example 4: Fluid Margins

**Input:**
```css
.section {
  margin-bottom: flow(20-375, 40-768, 80-1920);
}
```

**Output:**
```css
.section {
  margin-bottom: clamp(40px, calc(40px + (80 - 40) * ((100vw - 768px) / 1152)), 80px);
}
@media (width <= 768px) {
  .section {
    margin-bottom: clamp(20px, calc(20px + (40 - 20) * ((100vw - 375px) / 393)), 40px);
  }
}
```

---

### Example 5: Multiple Properties

Use `flow()` on any CSS property that accepts pixel values:

**Input:**
```css
.card {
  padding: flow(16-360, 24-768, 32-1440);
  gap: flow(8-360, 16-768, 24-1440);
  border-radius: flow(4-360, 8-768, 12-1440);
}
```

Each property gets its own fluid calculations and media queries!

---

## Use Cases

Perfect for:

- **Fluid Typography**: Scale font sizes smoothly across devices
- **Responsive Spacing**: Padding, margins, and gaps that adapt naturally
- **Adaptive Layouts**: Grid gaps, container widths, and more
- **Design Systems**: Maintain consistent scaling across breakpoints
- **Performance**: Uses native CSS `clamp()` for optimal rendering

---

## Browser Compatibility

- **PostCSS**: 8.0.0 or higher
- **Browsers**: All modern browsers with `clamp()` support
  - Chrome 79+
  - Firefox 75+
  - Safari 13.1+
  - Edge 79+

For older browser support, consider using a CSS `clamp()` polyfill.

---

## How It Works

1. **Parse**: The plugin detects `flow()` functions in your CSS
2. **Sort**: Breakpoints are automatically sorted from largest to smallest viewport
3. **Calculate**: Linear interpolation formulas are generated for fluid values
4. **Generate**: CSS `clamp()` functions and media queries are created
5. **Output**: Clean, production-ready CSS

---

## Contributing

Contributions are welcome! Here's how you can help:

### Reporting Issues

Found a bug or have a feature request?

1. Check existing [issues](https://github.com/soyleninjs/postcss-flow/issues)
2. Create a new issue with:
   - Clear description
   - Steps to reproduce (for bugs)
   - Expected vs actual behavior
   - Code examples

### Pull Requests

1. Fork the repository
2. Create a feature branch: `git checkout -b feature/amazing-feature`
3. Make your changes
4. Test thoroughly
5. Commit: `git commit -m 'Add amazing feature'`
6. Push: `git push origin feature/amazing-feature`
7. Open a Pull Request

---

## FAQ

**Q: Can I use rem or em units?**
A: Currently, the plugin works with px values only. Unit conversion may be added in future versions.

**Q: Does it work with CSS variables?**
A: The `flow()` function requires numeric values. CSS variables are not supported within the function.

**Q: Can I use negative values?**
A: Yes! Negative values work perfectly for margins and transforms.

**Q: Is there a maximum number of breakpoints?**
A: No hard limit, but 3-4 breakpoints is recommended for maintainability.

---

## License

MIT License - see [LICENSE](LICENSE) file for details.

---

## Author

**Lenin**
- GitHub: [@soyleninjs](https://github.com/soyleninjs)

---

## Acknowledgments

Inspired by the need for simpler responsive design workflows and the power of modern CSS functions.

If this plugin helps you, consider giving it a star on [GitHub](https://github.com/soyleninjs/postcss-flow)!

---

<div align="center">

**Made with by [@soyleninjs](https://github.com/soyleninjs)**

[Report Bug](https://github.com/soyleninjs/postcss-flow/issues) • [Request Feature](https://github.com/soyleninjs/postcss-flow/issues)

</div>