1const e=[{title:"Warum ich Breakpoint Preview gebaut habe",description:"Kurze Geschichte über Tab-Wechsel beim responsiven Bauen und ein CLI, das alle Viewports gleichzeitig zeigt.",date:"2026-05-05",tags:["dx","tooling","open-source"],published:!0,readTime:"4 min read",category:"Frontend",image:"breakpoint-preview.png",lang:"de",translatedSlug:"why-breakpoint-preview",content:`<script> 2 import ViewportGrid from '$lib/blog/markdown/ViewportGrid.svelte'; 3<\/script> 4 5Irgendwann saà ich da mit zwei Monitoren, vier Browser-Fenstern und der vagen Hoffnung, dass die Mobile-Variante schon irgendwie passen würde. Daneben DevTools im Responsive-Mode, einmal kurz auf 375 stellen, dann zurück auf Desktop, dann nochmal auf 768, dann gemerkt, dass ich im falschen Tab bin. So baut man keine responsiven Sites. So baut man Tab-Wechsel. 6 7Das Nervige daran ist nicht die Zeit pro Wechsel. Es ist die Reibung im Kopf. Jedes Mal wenn ich von Desktop auf Mobile springe, verliere ich den Faden, was ich gerade vergleichen wollte. Daraus ist \`breakpoint-preview\` geworden. 8 9## Was es macht 10 11Ein CLI, das deine laufende Seite gleichzeitig in mehreren Viewport-Breiten nebeneinander rendert. Default sind 375, 768, 1024 und 1440. Eine URL eingeben, alle vier reagieren. Hot Reload läuft durch wie gewohnt, weil das Tool einen kleinen Proxy vor dein Dev-Server hängt und die WebSocket-Verbindungen einfach durchreicht. 12 13<ViewportGrid caption="Vier Viewports gleichzeitig, eine URL, ein Browser-Tab." /> 14 15Jedes Viewport hat eine eigene URL-Bar, du kannst also einen einzelnen Frame auf eine andere Route schicken, um eine spezifische Mobile-View zu prüfen, während Desktop auf der Ãbersicht bleibt. Scroll-Sync ist optional, einzelne Viewports lassen sich ausblenden und der State bleibt über Reloads erhalten. 16 17## Wie ich es nutze 18 19Beim Bauen lasse ich es im zweiten Fenster offen, während die DevTools im Haupt-Tab Desktop bleiben. Sobald ich an einer Card oder einem Layout arbeite, sehe ich beim Speichern direkt, ob Tablet bricht oder Mobile zu eng wird, ohne aktiv hinzugucken. 20 21Bei Bug-Reports von Designer:innen oder Kund:innen ("kannst du das mal in Mobile checken") spare ich mir das Hin-und-her zwischen den GröÃen. Ich öffne das Tool, scrolle einmal durch, sehe alle vier Breakpoints in einem Blick. 22 23Für AI-Agents liegt eine \`SKILL.md\` im Repo, sodass Claude Code oder Codex das Tool selbst starten und durch Viewports navigieren können, wenn sie an responsivem Code arbeiten. Funktioniert mit jedem Framework, das einen Dev-Server hat: Vite, Next, SvelteKit, Astro, Remix, plain HTML. Letzter Schritt vor dem Push: einmal \`npx breakpoint-preview http://localhost:5173\`, durchscrollen, fertig. 24 25## Wie es funktioniert 26 27Unter der Haube ein lokaler Proxy, der alle Requests an deinen Dev-Server forwarded. Das macht alle Viewports same-origin, was Scroll-Sync und Per-Viewport-URLs erst möglich macht. WebSocket-Verbindungen für HMR werden transparent durchgereicht. Keine Extension, keine Config-Datei, keine Dependencies auÃer Node selbst. Mit \`--app\` Flag öffnet es als Standalone-Window ohne Browser-Chrome, dann fühlt es sich an wie eine eigene App. 28 29## Was hängenbleibt 30 31Was mir nach dem Bauen geblieben ist, ist nicht das Tool selbst, sondern wie viel Tab-Switching ich vorher als normalen Teil der Arbeit hingenommen hatte. Sobald die vier Frames nebeneinander stehen, fällt einem auf, wie oft man eigentlich in den Mobile-View springt, ohne es zu merken. Seitdem teste ich responsiv beiläufig statt am Ende, und das ändert mehr am Endergebnis als jede einzelne Mobile-Korrektur. 32 33- Repo: [github.com/enisbu/breakpoint-preview](https://github.com/enisbu/breakpoint-preview) 34- npm: [npmjs.com/package/breakpoint-preview](https://www.npmjs.com/package/breakpoint-preview)`,_meta:{filePath:"warum-breakpoint-preview/+page.svx",fileName:"+page.svx",directory:"warum-breakpoint-preview",extension:"svx",path:"warum-breakpoint-preview/+page"},slug:"warum-breakpoint-preview"},{title:"Warum ich tw-easing-gradients gebaut habe",description:"Kurze Geschichte über sichtbares Banding in CSS-Gradienten und wie ich es mit einem Tailwind-Plugin losgeworden bin.",date:"2026-05-05",tags:["css","tailwind","open-source"],published:!0,readTime:"4 min read",category:"Frontend",image:"tw-easing-gradients.png",lang:"de",translatedSlug:"why-tw-easing-gradients",content:`<script> 35 import GradientCompare from '$lib/blog/markdown/GradientCompare.svelte'; 36 import EasingGallery from '$lib/blog/markdown/EasingGallery.svelte'; 37 import MiniPlayground from '$lib/blog/markdown/MiniPlayground.svelte'; 38 import PlaygroundCard from '$lib/blog/markdown/PlaygroundCard.svelte'; 39 import UseCaseStrip from '$lib/blog/markdown/UseCaseStrip.svelte'; 40<\/script> 41 42Ich saà an einer Card mit Image-Overlay. Schwarzes Gradient von unten nach oben, fade to transparent, damit der Titel lesbar bleibt. Auf einem 27"-Display sah das aus wie ein billiges Stockfoto aus 2009. Drei sichtbare Streifen, harte Kanten dazwischen. Erst dachte ich, mein Display sei kaputt. Dann: Browser-Bug. Beides falsch. 43 44Das Banding kommt aus dem CSS selbst. Ich hatte es jahrelang ignoriert, weil ich meistens auf hellen Hintergründen mit kräftigen Farben arbeite, wo es kaum auffällt. Sobald aber \`to-transparent\` ins Spiel kommt oder dunkle Töne nahe Schwarz, sieht man es überall. Daraus ist \`tw-easing-gradients\` geworden. 45 46## Das Problem 47 48Ein simples \`bg-linear-to-t from-black to-transparent\` sieht harmlos aus. Auf einem ordentlichen Display erscheint in der Mitte ein grau-stichiger Streifen, dazu harte Ãbergänge oben und unten. Das ist die klassische "gray dead zone". Lineare Interpolation zwischen Schwarz und transparentem Schwarz mischt sich auf eine Art, die das Auge als Unsauberkeit liest. 49 50<GradientCompare leftLabel="bg-linear-to-t" rightLabel="bg-ease-to-t" /> 51 52Andreas Larsen hat das 2017 in seinem [Easing-Gradients-Artikel](https://larsenwork.com/easing-gradients) sauber beschrieben und damals ein PostCSS-Plugin dafür gebaut. Es gibt sogar einen [W3C-Vorschlag](https://github.com/w3c/csswg-drafts/issues/1332) für native Unterstützung, der seit Jahren in der Schwebe hängt. Bis es soweit ist, muss man sich selbst behelfen. 53 54## Drop-in Replacement 55 56Mein Plugin macht aus einer Klasse eine andere. Mehr nicht. 57 58\`\`\`html 59<div class="bg-linear-to-t from-black to-transparent"></div> 60<div class="bg-ease-to-t from-black to-transparent"></div> 61\`\`\` 62 63Gleiche \`from-*\` und \`to-*\` Color Stops, gleiche Direction-Suffixe (\`to-t\`, \`to-r\`, \`to-tl\`, alle acht). Vier Easing-Varianten: \`bg-ease-\`, \`bg-ease-in-\`, \`bg-ease-out-\`, \`bg-ease-in-out-\`. Zero Runtime, kein JavaScript im Browser. 64
65<EasingGallery caption="Linear vs. drei Easing-Varianten, gleicher from-foreground Overlay." /> 66 67## Wo es sich lohnt 68 69Der häufigste Fall: Text auf einem Bild lesbar halten. Beim linearen Gradient bleibt der schwarze Block solid und blendet nicht ins Bild ein. Mit Easing fadet derselbe Overlay natürlich aus, der Titel bleibt lesbar, das Bild wirkt nicht abgeschnitten. 70 71<UseCaseStrip title="Quiet Mornings" eyebrow="Image-Overlay" /> 72 73Andere Stellen, an denen ich es einsetze: Top- und Bottom-Fades an scrollenden Containern, Color-zu-Color-Backgrounds in Cards (kein matschiger grauer Mittelteil), und Custom-Bezier-Kurven über die Bracket-Syntax wie \`bg-ease-to-r-[0.22,1,0.36,1]\` für Brand-Curves. 74 75Welches Easing am besten passt, kann man schwer beschreiben. Hier kannst du live durchklicken: 76 77<MiniPlayground /> 78 79## Probier es im Playground 80 81Lässt sich besser im Browser drehen als im Blog beschreiben. Direction, Easing und Custom-Bezier live anpassen, mit Color-Pickern auf beiden Seiten und einem Compare-Slider gegen das normale Tailwind-Linear. 82 83<PlaygroundCard 84 href="https://tw-easing-gradients.enisdev.com/playground" 85 title="Live Playground" 86 description="Color-Picker, Direction, Custom-Bezier-Editor und Compare-Slider in einer Seite." 87/> 88 89## Was hängenbleibt 90 91Was mir nach dem Bauen geblieben ist, ist weniger das Plugin selbst und mehr die Erkenntnis, dass ich jahrelang über diese Streifen drübergeguckt habe wie über schlechtes Wetter. Seitdem sehe ich Banding überall: in Hero-Sections, auf Stockfotos, in Spotify-Album-Covers. Lässt sich nicht mehr abstellen, beste und gleichzeitig schlechteste Nebenwirkung des Projekts. 92 93- Repo: [github.com/enisbu/tw-easing-gradients](https://github.com/enisbu/tw-easing-gradients) 94- Doku und Playground: [tw-easing-gradients.enisdev.com](https://tw-easing-gradients.enisdev.com)`,_meta:{filePath:"warum-tw-easing-gradients/+page.svx",fileName:"+page.svx",directory:"warum-tw-easing-gradients",extension:"svx",path:"warum-tw-easing-gradients/+page"},slug:"warum-tw-easing-gradients"},{title:"Why I built Breakpoint Preview",description:"A short story about tab switching while building responsive sites and a CLI that shows every viewport at once.",date:"2026-05-05",tags:["dx","tooling","open-source"],published:!0,readTime:"4 min read",category:"Frontend",image:"breakpoint-preview.png",lang:"en",translatedSlug:"warum-breakpoint-preview",content:`<script> 95 import ViewportGrid from '$lib/blog/markdown/ViewportGrid.svelte'; 96<\/script> 97 98At some point I was sitting there with two monitors, four browser windows, and a vague hope that the mobile variant would somehow line up. DevTools in responsive mode on the side, switch to 375 quick, back to desktop, then 768, then realize I was on the wrong tab. That's not how you build responsive sites. That's how you build tab switches. 99 100The annoying part isn't the time per switch. It's the friction in your head. Every time I jump from desktop to mobile, I lose the thread of what I was actually trying to compare. That's how \`breakpoint-preview\` came about. 101 102## What it does 103 104A CLI that renders your running site at several viewport widths next to each other at the same time. Defaults are 375, 768, 1024, and 1440. Type a URL, all four react. Hot reload keeps working as usual, because the tool drops a small proxy in front of your dev server and passes the WebSocket connections through. 105 106<ViewportGrid caption="Four viewports at once, one URL, one browser tab." /> 107 108Each viewport has its own URL bar, so you can point a single frame at a different route to check a specific mobile view while desktop stays on the overview. Scroll sync is optional, viewports can be hidden individually, and state persists across reloads. 109 110## How I use it 111 112While building, I keep it open in a second window while DevTools stay on desktop in the main tab. As soon as I touch a card or a layout, I can see on save whether tablet breaks or mobile gets too tight, without actively looking. 113 114For bug reports from designers or clients ("can you check this on mobile") I skip the back and forth between sizes. I open the tool, scroll through once, see all four breakpoints in a single glance. 115 116For AI agents there's a \`SKILL.md\` in the repo so Claude Code or
116Codex can launch the tool themselves and navigate viewports when they're working on responsive code. Works with any framework that has a dev server: Vite, Next, SvelteKit, Astro, Remix, plain HTML. Last step before pushing: \`npx breakpoint-preview http://localhost:5173\`, scroll once, done. 117 118## How it works 119 120Under the hood it's a local proxy that forwards all requests to your dev server. That makes all viewports same-origin, which is what enables scroll sync and per-viewport URLs in the first place. WebSocket connections for HMR are passed through transparently. No extension, no config file, no dependencies besides Node itself. With the \`--app\` flag it opens as a standalone window without browser chrome, which makes it feel like its own app. 121 122## What stuck with me 123 124What stayed with me after building this isn't the tool itself, it's how much tab switching I had quietly accepted as a normal part of the job. Once the four frames sit next to each other, you notice how often you used to jump into mobile view without thinking about it. I now test responsive in passing instead of at the end, and that changes the final result more than any single mobile fix. 125 126- Repo: [github.com/enisbu/breakpoint-preview](https://github.com/enisbu/breakpoint-preview) 127- npm: [npmjs.com/package/breakpoint-preview](https://www.npmjs.com/package/breakpoint-preview)`,_meta:{filePath:"why-breakpoint-preview/+page.svx",fileName:"+page.svx",directory:"why-breakpoint-preview",extension:"svx",path:"why-breakpoint-preview/+page"},slug:"why-breakpoint-preview"},{title:"Why I built tw-easing-gradients",description:"A short story about visible banding in CSS gradients, and how I got rid of it with a Tailwind plugin.",date:"2026-05-05",tags:["css","tailwind","open-source"],published:!0,readTime:"4 min read",category:"Frontend",image:"tw-easing-gradients.png",lang:"en",translatedSlug:"warum-tw-easing-gradients",content:`<script> 128 import GradientCompare from '$lib/blog/markdown/GradientCompare.svelte'; 129 import EasingGallery from '$lib/blog/markdown/EasingGallery.svelte'; 130 import MiniPlayground from '$lib/blog/markdown/MiniPlayground.svelte'; 131 import PlaygroundCard from '$lib/blog/markdown/PlaygroundCard.svelte'; 132 import UseCaseStrip from '$lib/blog/markdown/UseCaseStrip.svelte'; 133<\/script> 134 135I was working on a card with an image overlay. Black gradient from bottom to top, fading to transparent so the title stays readable. On a 27" display, the result looked like a cheap stock photo from 2009. Three visible stripes, hard edges between them. My first thought: broken display. My second: browser bug. Both wrong. 136 137The banding comes from the CSS itself. I had been ignoring it for years because I mostly work on bright backgrounds with bold colors, where it barely shows up. The moment \`to-transparent\` enters the picture, or dark tones near black, you see it everywhere. That's how \`tw-easing-gradients\` came about. 138 139## The problem 140 141A plain \`bg-linear-to-t from-black to-transparent\` looks harmless. On a decent display you get a grayish stripe in the middle and hard edges at the top and bottom. Classic "gray dead zone". Linear interpolation between black and transparent black mixes in a way the eye reads as messy. 142 143<GradientCompare leftLabel="bg-linear-to-t" rightLabel="bg-ease-to-t" /> 144 145Andreas Larsen described this back in 2017 in his [easing gradients article](https://larsenwork.com/easing-gradients) and built a PostCSS plugin for it at the time. There's even a [W3C proposal](https://github.com/w3c/csswg-drafts/issues/1332) for native support that has been hanging in limbo for years. Until that lands, you have to work around it. 146 147## Drop-in replacement 148 149The plugin turns one class into another. That's it. 150 151\`\`\`html 152<div class="bg-linear-to-t from-black to-transparent"></div> 153<div class="bg-ease-to-t from-black to-transparent"></div> 154\`\`\` 155 156Same \`from-*\` and \`to-*\` color stops, same direction suffixes (\`to-t\`, \`to-r\`, \`to-tl\`, all eight). Four easing variants: \`bg-ease-\`, \`bg-ease-in-\`, \`bg-ease-out-\`, \`bg-ease-in-out-\`. Zero runtime, no JavaScript in the browser. 157 158<EasingGallery caption="Linear vs. three easing variants, same from-foreground overlay." /> 159 160## Where it earns its keep 161 162The most common case: keeping text readable on top of an image. With a plain linear gradient the black block stays solid and doesn't blend into the image. With easing the same overlay fades naturally, the title stays legible and the image doesn't look chopped off. 163 164<UseCaseStrip title="Quiet Mornings" eyebrow="Image overlay" /> 165
166Other places I use it: top and bottom fades on scrolling containers, color-to-color card backgrounds without a muddy middle, and custom bezier curves through the bracket syntax like \`bg-ease-to-r-[0.22,1,0.36,1]\` for brand curves. 167 168Which easing fits best is hard to put in words. Click through it live: 169 170<MiniPlayground /> 171 172## Try it in the playground 173 174Easier to play with in the browser than to describe in a blog. Tweak direction, easing, and custom bezier live, with color pickers on both sides and a compare slider against plain Tailwind linear. 175 176<PlaygroundCard 177 href="https://tw-easing-gradients.enisdev.com/playground" 178 title="Live playground" 179 description="Color pickers, direction, custom bezier editor, and a compare slider in one page." 180/> 181 182## What stuck with me 183 184What stayed with me after building this isn't the plugin itself, it's the realization that I had been looking past those stripes for years like bad weather. I see banding everywhere now: hero sections, stock photos, Spotify album covers. Can't unsee it, best and worst side effect of the whole project. 185 186- Repo: [github.com/enisbu/tw-easing-gradients](https://github.com/enisbu/tw-easing-gradients) 187- Docs and playground: [tw-easing-gradients.enisdev.com](https://tw-easing-gradients.enisdev.com)`,_meta:{filePath:"why-tw-easing-gradients/+page.svx",fileName:"+page.svx",directory:"why-tw-easing-gradients",extension:"svx",path:"why-tw-easing-gradients/+page"},slug:"why-tw-easing-gradients"}];export{e as a};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.