# Puppertino 2.0.0 > The complete Puppertino documentation in one file. Each page starts with a top-level heading and its source URL. An index of every class in each stylesheet closes the file. # Getting started Source: https://puppertino.com/docs/getting-started/ Install Puppertino and bring Apple's design language to the web in a few minutes. Puppertino is a CSS framework that brings macOS and iOS aesthetics to the web. It follows Apple's Human Interface Guidelines, ships zero JavaScript dependencies, and works without a build step. Puppertino provides the macOS 27 color system, the materials specification, and a complete typography scale. The v1 classes remain available so projects can upgrade without rewrites. ## Install via CDN The fastest way to use Puppertino is through jsDelivr. Add the full CSS to the `` of your HTML. ```html ``` Building for one platform only? Two smaller bundles ship alongside the full one. ```html ``` All three include the foundations (colors, typography, materials, layout, shadows, dark mode). The desktop bundle adds the macOS component set; the mobile bundle adds buttons, forms, modals, actions, and tabs. Need only specific components? Import them individually to keep the bundle small. ```html ``` ## Install via npm Install Puppertino as a dependency in your project. ```bash npm install @codedgar/puppertino@2.0.0 ``` Then import the full framework or individual components. ```javascript // Full framework import '@codedgar/puppertino' // Individual components import '@codedgar/puppertino/buttons' import '@codedgar/puppertino/colors' import '@codedgar/puppertino/typography' import '@codedgar/puppertino/materials' import '@codedgar/puppertino/dark-mode' ``` You can also use plain CSS imports if your stack supports them. ```css @import '@codedgar/puppertino'; /* Or pick what you need */ @import '@codedgar/puppertino/colors'; @import '@codedgar/puppertino/materials'; ``` ## JavaScript modules A few components ship with optional vanilla JavaScript: modals, tabs, actions, segmented controls, and the dark mode manager. Import only the ones you use. ```javascript import '@codedgar/puppertino/js/modals.js' import '@codedgar/puppertino/js/tabs.js' import '@codedgar/puppertino/js/darkmode_manager.js' ``` ## Your first page Here is the smallest possible Puppertino setup. It pulls in the full framework, applies the typography scale to the body, and enables automatic dark mode. ```html My Puppertino app

Hello from Puppertino

A CSS framework for Apple-style interfaces.

``` The `p-type` class opts the page into the macOS 27 typography scale. The `p-auto-dark-mode` class flips colors to dark mode when the user's system preference is dark. ## Dark mode Puppertino supports dark mode in two ways. **Automatic** uses the system preference. **Manual** lets you toggle it from a button. ```html ``` For the manual approach, the dark mode manager script handles the toggle, persistence, and tab synchronization. ```html ``` ## The foundations Three foundations follow Apple's macOS 27 specification. - **Colors.** Thirteen system accents, six text hierarchy levels, five fill tiers, and semantic background tokens. All with light and dark mode variants. - **Typography.** The full Apple text style scale, from Large Title to Caption 2. Nine font weights and optical letter spacing baked in. - **Materials.** Five thickness levels for blur and translucency, plus elevation tokens for shadows. Built with `prefers-reduced-transparency` and `@supports` fallbacks. The v1 `color_palette.css`, `layout.css`, and `shadows.css` files are still included for backwards compatibility. Projects upgrading from v1 do not need to change anything to keep working. ## Migrating from version 1 If you are upgrading an existing Puppertino v1 project, your code will continue to work. The v2 tokens live alongside the v1 classes. When you are ready to adopt the v2 system, update your imports to point at the v2 files. ```javascript // v1 import '@codedgar/puppertino/colors' // color_palette.css import '@codedgar/puppertino/layout' // layout.css import '@codedgar/puppertino/shadows' // shadows.css // v2 (the v2 files include everything from v1) import '@codedgar/puppertino/colors' // colors.css (v2 + v1) import '@codedgar/puppertino/typography' // typography.css (v2 + v1) import '@codedgar/puppertino/materials' // materials.css (v2 + v1) ``` Note that `@codedgar/puppertino/colors` points at `colors.css`, which includes both the macOS 27 system tokens *and* the v1 classes. Same for materials. Both systems are available from the same import. ## Browser support Puppertino targets modern evergreen browsers: Safari, Chrome, Firefox, and Edge. Materials use `backdrop-filter` with a `@supports` fallback for older browsers. Color tokens use CSS custom properties. ## Where to go next - **Foundations** explain how the design system works. Start with [Colors](https://puppertino.com/docs/colors/), [Typography](https://puppertino.com/docs/typography/), and [Materials](https://puppertino.com/docs/materials/). - **Mobile components** cover touch-optimized elements like buttons, forms, modals, and tabs. - **Desktop components** cover pointer-driven elements with hover states and macOS interaction patterns. If you find a bug or want to request a component, open an issue on [the GitHub repo](https://github.com/codedgar/Puppertino/issues). --- # Materials Source: https://puppertino.com/docs/materials/ Materials are surfaces that blur the content behind them. Five thickness levels, full dark mode support, and accessibility built in. A material is a surface that blurs and tints the content behind it. Apple uses materials for navigation bars, sheets, popovers, and any element that should feel like it sits on top of the rest of the interface without hiding it completely. Puppertino ships five thickness levels that match Apple's macOS 27 specification. Each level adapts to light and dark mode, respects reduced transparency, and falls back gracefully when the browser does not support `backdrop-filter`. ## Thickness levels Five materials, ordered from most see-through to most opaque. Pick the one that matches the importance of the surface. Thinner materials work for light decorative chrome; thicker materials work for surfaces that hold critical content. - Ultra Thin: `.p-material-ultrathin`, opacity 0.36 / 0.10 - Thin: `.p-material-thin`, opacity 0.48 / 0.20 - Medium: `.p-material-medium`, opacity 0.60 / 0.29 - Thick: `.p-material-thick`, opacity 0.72 / 0.40 - Ultra Thick: `.p-material-ultrathick`, opacity 0.88 / 0.50 The two opacity values are light mode and dark mode respectively. Light materials are `#F6F6F6` at each opacity, except Ultra Thick, which is a slightly darker `#ECECEC` at 88%. Dark materials are black. Note that dark mode materials are more transparent than light mode materials, in line with the Liquid Glass direction: materials should let more of the background through. ## Choosing a thickness Match the material to the size of the surface and the content it carries. | Material | Use it for | |---|---| | Ultra Thin | Floating decorative chrome that should barely separate from the background | | Thin | Tab bars and toolbars that need slight separation | | Medium | Cards, popovers, and tooltips | | Thick | Sheets, modals, and dialogs | | Ultra Thick | Surfaces that hold critical content over a busy background | ## How to use materials Apply a material class to any element. The class handles the blur, the saturation, and the background fill in one step. ```html
Sheet content
``` The `p-material` class on its own applies the blur and saturation without setting a background color. Combine it with a custom background when you need full control. ```html
Custom tinted material
``` ## Chrome Chrome is the material for bars that sit on a window edge: title bars, toolbars, and the band at the top of a scroll view. It is nearly opaque and barely blurred, so content that scrolls under it fades. A single hairline separates it from the content. | Token | Light | Dark | |---|---|---| | `--p-material-chrome` | `rgba(255,255,255,0.85)` | `rgba(31,31,31,0.55)` | | `--p-material-chrome-separator` | `rgba(0,0,0,0.05)` | `rgba(255,255,255,0.10)` | | `--p-material-chrome-separator-width` | `0.67px` | `0.67px` | | `--p-material-chrome-blur` | `3px` | `3px` | The `.p-material-chrome` class sets the fill and blur. Draw the separator yourself on the edge that meets the content, so a top bar and a bottom bar can share the class. ```html
Title
``` ### Touch chrome iOS bars use a different dark chrome. It darkens the content with black, and its hairline is black. Light mode is the same as macOS. Use `.p-material-chrome-touch` for touch nav bars, toolbars, and scroll edges. | Token | Light | Dark | |---|---|---| | `--p-material-chrome-touch` | `rgba(255,255,255,0.85)` | `rgba(0,0,0,0.55)` | | `--p-material-chrome-touch-separator` | `rgba(0,0,0,0.05)` | `rgba(0,0,0,0.10)` | ## Glass components Three preset glass surfaces sized for common UI elements. ```html
Card
Window or sheet
``` | Class | Light | Dark | Shadow | |---|---|---|---| | `.p-glass-sm` | `rgba(242,242,242,0.55)` | `rgba(153,153,153,0.17)` | `--p-shadow-glass-control` | | `.p-glass-md` | `rgba(245,245,245,0.72)` | `rgba(26,26,26,0.96)` | `--p-shadow-alert` | | `.p-glass-lg` | `rgba(245,245,245,0.72)` | `rgba(26,26,26,0.96)` | `--p-shadow-alert` | Small glass stays readable over light and dark content. In dark mode it is nearly clear, while medium and large glass are close to opaque. On iOS, glass cards (sheets, alerts, popovers) cast `--p-shadow-overlay`, which sits 8px below the card. macOS cards use `--p-shadow-alert`, 18px below. Every preset carries the glass edge, `--p-glass-edge`, and a sensible border radius (24px for small, 14px for medium, 10px for large) so the surface looks finished without extra styling. ### The glass edge The edge is what makes glass read as a separate pane, even on a white page. It is a list of box shadows. | Part | Light | Dark | |---|---|---| | Keyline, 0.5px outside the shape | Black at 12%, thicker at the sides | Black at 80%, thicker at the sides | | Rim, 1px inside the top and bottom | White at 70% | White at 20% | | Glow inside the top and bottom | A soft white band, stronger along the bottom | The same, fainter | The sides get the keyline only. Use the token on your own glass surfaces. ```css .my-panel { background: var(--p-glass-md); backdrop-filter: saturate(180%) blur(30px); box-shadow: var(--p-glass-edge), var(--p-shadow-alert); } ``` With increased contrast on, the keyline becomes a solid 1px line at 45%. ## Liquid Glass Liquid Glass is the material Apple introduced across its platforms in 2025. It bends the content behind it the way a real lens does. The web has no native version, so there are two ways to approximate it: faux Liquid Glass and real-time Liquid Glass. Puppertino ships both. Switch knobs and slider thumbs get the faux lens below, and bars, buttons, and panels get [Puppertino Glass](#puppertino-glass), which refracts the real page. ```html ``` Press and hold a switch, then drag across it. The knob lifts into glass, and the track bends through it. Drag a slider and its thumb lifts into clear glass that shows the track through it. Release and the glass settles back into a solid knob. ### Faux Liquid Glass Faux Liquid Glass never looks at the page behind it. A switch knob always sits on its own track, and a slider thumb always sits on its fill. Because the content under the lens is known, the lens can redraw that content inside itself, and nobody can tell it is a copy. It comes in two looks. Every switch and slider uses the liquid lens by default: the track is cut out under the glass and redrawn inside it. A switch magnifies and bends its copy. A slider shows it at its real size and in focus, with the fill color wrapped around the rim. Add `data-p-lens="clear"` to a switch's label or a slider input for the flatter macOS 27 and iOS 27 look instead: a nearly transparent body, a hairline rim, and a soft shadow below, with the track showing through unmagnified. The rest of this section describes the liquid lens. The liquid lens is three layers stacked inside the control. | Layer | What it does | |---|---| | Baseline | The track itself. On a switch, a capsule is cut out of it wherever the lens sits, so the page shows through the glass rather than the flat track. The cut is a CSS mask that grows with the lens. | | Displacement | A copy of the track inside the lens, scaled up 1.65x and run through an SVG goo filter. The filter blurs the copy, then crushes its alpha (`16a − 10`) so the edges re-harden. The track color fuses into a rim at the glass edge, which reads as refraction. | | Knockout and glass | The resting knob fades out as the lens lifts, and a stack of 11 shadows draws the glass: white specular edges, a dark inner shade for curvature, and a soft cast shadow. An SVG filter splits red and blue a fraction of a pixel apart for faint chromatic aberration. | Every value scales with the lens. The reference is a 50px lens with a 2px goo blur and a 0.8px color split; a 24px touch knob gets half of each. The SVG filter values are absolute, so the script builds a set per lens height rather than letting the rim blur away at small sizes. One number drives all of it. `--p-lens-lift` runs from 0, a plain knob, to 1, fully lifted glass. The scale, the blur that sharpens the lens as it lifts, the cover fade, and the rim all read from it, so they can never fall out of step. It moves over 350ms on a spring sampled from a lightly damped oscillator, with a 3% overshoot as it lands. Browsers without `linear()` easing get `cubic-bezier(0.32, 1.2, 0.36, 1)`. Because nothing samples the backdrop, faux Liquid Glass works in Safari, Chrome, and Firefox alike. Consider it for small controls whose surroundings you control. The original implementation of this effect is by [Jhey Tompkins](https://jhey.dev). Puppertino adapts it to real form controls: the switch stays a native checkbox, so forms, labels, and keyboard toggling keep working. ### How to use it Load the script once. It adds the lens to every `.p-switch` on the page and to every `.p-slider` while it is dragged. The markup does not change. ```html ``` Switches added after the page loads need one call. ```js PuppertinoLiquidGlass.enhance(container); ``` Without the script, switches keep their CSS lens morph and sliders keep a solid thumb. Nothing breaks. ### Real-time Liquid Glass Real-time Liquid Glass refracts whatever is actually behind the element: text, photos, video, other controls. It is what Apple renders on toolbars, tab bars, and sheets. Every web version bends the page with a displacement map. What differs is where the map gets applied, and that decides which browsers keep the effect. | Approach | How it works | Support | |---|---|---| | `backdrop-filter: url(#filter)` | An SVG `feDisplacementMap` bends the page behind the element. No extra code and no copies of the content. | Chromium only. Safari and Firefox drop the declaration and the refraction disappears. | | A plain `filter` on content the component owns | The same primitive, applied to a layer the component itself renders, like a copy of a track fill. The page behind is untouched. | Every modern engine. | | Capture the DOM, refract it in WebGL | A library snapshots the page (snapDOM, or html2canvas), uploads it as a texture, and a shader does the refraction, chromatic aberration, and specular highlights. | Every WebGL browser, including Safari and Firefox. | The second row is what the faux lens uses, because a control always knows what sits under it. Aave documented it in [Building Glass for the Web](https://aave.com/design/building-glass-for-the-web), and their switch and slider work the way Puppertino's do: the glass refracts a copy of the track fill rather than the page. Their write-up is also the best list of Safari's quirks, including filter output being cached by filter ID and live `