HTML, CSS & JavaScript Playground
Write HTML, CSS, and JavaScript side by side and see the result render instantly in a live preview. A built-in console captures console.log output and runtime errors, so you can prototype a layout, test a snippet, or debug a function without leaving your browser. Everything runs locally in a sandboxed frame — your code is never uploaded.
Related Tools
Your code runs in a sandboxed frame in your own browser and is never uploaded. For security the preview cannot make network requests, so external scripts, stylesheets, and fetch calls are blocked.
Frequently Asked Questions
Is my code sent to a server?
No. The playground has no backend endpoint — your HTML, CSS, and JavaScript run entirely inside a sandboxed frame in your own browser. Nothing is uploaded, logged, or stored anywhere except your own browser’s local storage.
Can I load an external library like jQuery or React from a CDN?
No. For security, the preview frame blocks all external network requests — remote scripts, stylesheets, images, and fetch or XHR calls. This is what prevents the playground being used to load or distribute third-party code. If you need a library, paste its source directly into the JavaScript pane.
Does my work save automatically?
Yes. Your three panes are saved to your browser’s local storage as you type and restored when you come back. You can also save multiple named snippets. Clearing your browser data removes them, and nothing is synced between devices.
What happens if my code has an infinite loop?
The playground stops it for you. Loops are given an iteration and time budget before they run, so something like while (true) {} raises an error in the console after a few seconds instead of locking up the page. Auto-run pauses at that point so the same loop is not restarted on your next keystroke — fix the exit condition and press Run again.
Does alert() work in the preview?
No. The preview is a sandboxed frame with modal dialogs disabled, so alert, confirm, and prompt do nothing. Use console.log() instead — its output appears in the console pane below the preview, along with any errors your code throws.
How a Browser Code Playground Works — and How to Get the Most From It
A code playground is the shortest possible distance between an idea and a working example. Instead of creating a project folder, wiring up a build tool, installing dependencies, and starting a dev server, you type into three panes and watch the result appear immediately. That tightening of the feedback loop is not just a convenience — it changes how you learn and how you debug. When the gap between a change and its consequence shrinks to under a second, you start experimenting more freely, testing assumptions you would otherwise have accepted, and building an intuition for how HTML, CSS, and JavaScript actually interact.
The Three-Pane Model and How Your Code Composes
The three panes map directly to the three languages the browser understands natively. The HTML pane defines structure — the elements that exist and how they nest. The CSS pane defines presentation — how those elements look and where they sit. The JavaScript pane defines behaviour — what happens when the user interacts, or when time passes. Keeping them separate mirrors the separation of concerns that well-structured production code follows, and it makes each piece easier to reason about in isolation.
When you press Run, these three inputs are assembled into a single document inside the preview frame. The CSS is injected into a style element, the HTML becomes the body content, and the JavaScript runs last, after the DOM already exists. That ordering matters, and it explains a class of confusing errors: if your script tries to grab an element with document.getElementById before that element has been parsed, you get null. Because the playground always runs your JavaScript after the HTML is in place, that particular trap is avoided here — but the same code pasted into a real page with a script tag in the head would break, which is worth remembering when you move your work out of the playground.
Why the Preview Runs in a Sandboxed Frame
Running arbitrary JavaScript inside a web page is genuinely dangerous if it is done carelessly. Any script running on a page has, by default, access to everything that page can reach: its cookies, its local storage, its DOM, and any authenticated session the visitor has with that site. A naive playground that simply called eval() on your input would give that code the full privileges of the surrounding site — which is exactly the vulnerability class known as cross-site scripting.
This playground avoids that entirely by running your code in an iframe with the sandbox attribute set to allow-scripts and, crucially, without allow-same-origin. That combination gives the frame what the HTML specification calls an opaque origin: a unique origin that matches nothing else. From inside that frame, reading document.cookie throws a security error, localStorage is inaccessible, and any attempt to reach into the parent page fails with a cross-origin exception. Your code gets a complete, fully functional browser environment that is walled off from everything belonging to the surrounding site.
A second layer comes from Content Security Policy, a header that tells the browser which capabilities a document is permitted to use. The preview frame is served with a policy that permits inline scripts and evaluation — necessary, because running your code is the entire point — while forbidding all network access. There is no fetch, no XMLHttpRequest, no WebSocket, no remote script loading, and no remote images. This is why you cannot pull jQuery or React in from a CDN here. It is a deliberate trade: the same restriction that blocks a convenient CDN import also makes it impossible to use this page to exfiltrate data, probe internal networks, or serve someone else's malicious payload from a trusted domain.
Reading the Console Effectively
The console pane captures everything your code reports. console.log is the workhorse, but the variants carry meaning worth using: console.warn for things that are suspicious but survivable, console.error for genuine failures, and console.info for context. Colour-coding in the pane reflects those levels, so a well-instrumented script becomes far easier to scan than one that logs everything at the same level.
Uncaught exceptions appear automatically with their line and column numbers, pointing back at your JavaScript pane. Rejected promises that nobody handled are also surfaced — a category of bug that is easy to miss, because an unhandled rejection often fails silently in ordinary pages. If you are doing anything asynchronous, watch for those messages specifically; they usually mean a missing catch or a forgotten await.
One habit worth adopting: log values, not just markers. console.log("here") tells you that a line executed, but console.log("count:", count) tells you why it behaved the way it did. Objects and arrays are expanded into readable text automatically, including nested structures, so you rarely need to stringify anything by hand.
Debugging Layout in a Live Preview
CSS problems are usually easier to solve by subtraction than by addition. When an element is not where you expect, the instinct is to add more rules — more margins, more positioning, more overrides. A faster approach in a live preview is to temporarily give the misbehaving element a loud outline, such as outline: 2px solid red, and watch where its box actually sits. Because the preview updates as you type, you can add and remove that diagnostic in seconds.
The most common layout confusions come from a small set of causes. Margin collapse means adjacent vertical margins merge into one rather than adding up. A flex container's align-items controls the cross axis, not the main axis, so it flips meaning entirely when you change flex-direction. Percentage heights need a parent with a definite height, which is why height: 100% so often appears to do nothing. And position: absolute resolves against the nearest positioned ancestor, not the page — so adding position: relative to a parent frequently fixes an element that has flown to the wrong corner.
Handling Infinite Loops and Runaway Code
Sooner or later you will write while (true) without an exit condition, or a recursive function that never reaches its base case. It is tempting to assume an iframe protects the page from this, but it generally does not: browsers keep same-site frames — including sandboxed ones — in the same renderer process as the page that embeds them, so a tight synchronous loop inside the preview would ordinarily lock up the entire tab, editors and buttons included.
This playground therefore prevents the freeze rather than trying to recover from it. Before your JavaScript runs, each loop header is given an iteration budget and the run as a whole is given a time budget. If either is exceeded, the loop throws an ordinary error that appears in the console, the page stays responsive, and auto-run switches itself off so your next keystroke does not immediately start the same runaway loop again. The budgets are set high enough that legitimate loops — even ones doing millions of iterations of real work — never reach them.
The practical lesson generalises well beyond the playground: any long-running synchronous work blocks the thread it runs on, and the browser cannot paint or respond to input while it does. In production code the answer is to break the work into chunks, move it into a Web Worker, or make it genuinely asynchronous. If a loop needs a guard to stay usable here, it would have frozen a real page too.
Saving Your Work
Everything you type is saved to your browser's local storage automatically and restored the next time you open the page, so an accidental refresh does not lose your work. You can also save multiple named snippets and switch between them, which is useful for keeping several variations of an idea side by side. Because this storage lives in your browser rather than on a server, it is private by construction — but it also means your snippets do not follow you to another device or browser, and clearing your browsing data will remove them. For anything you want to keep permanently, use the Download button to export a complete, standalone HTML file that opens in any browser.
When to Graduate to a Real Build Setup
A playground is ideal for isolated experiments: testing a CSS technique, checking how an API behaves, reproducing a bug in the smallest possible form, or teaching a concept to someone else. It stops being the right tool once you need multiple files, npm packages, a framework with a compile step such as JSX or TypeScript, or anything that talks to a backend. At that point a local project with a modern bundler gives you module resolution, dependency management, hot reloading, and a path to production.
A good workflow uses both. Prototype the tricky piece in a playground where iteration is fastest, confirm the behaviour in isolation, then port the working snippet into your real project with confidence that the core logic is sound. Reducing a bug to a minimal playground reproduction is also one of the most effective debugging techniques there is — and one of the most useful things you can attach to a bug report, because it lets someone else see the problem in seconds rather than cloning your repository.