@import "https://unpkg.com/open-props";
.card { border-radius: var(--radius-2); padding: var(--size-fluid-3); box-shadow: var(--shadow-2); &:hover { box-shadow: var(--shadow-3); } @media (--motionOK) { animation: var(--animation-fade-in); } }
18 props +normalize.css
10 props
8 props +normalize.css
10 props
16 props
+2 imports
Example loads only the animations and easings for a springy scale-in animation
Light + dark HTML5 minimal styles
It'snon-prescriptive.
File sizes and links to source:
The following sizes are for the minified files and afterBrotli compression.
@import "https://unpkg.com/open-props";
.just-for-gap { display: grid; gap: var(--size-4); }
blockquote { --_accent-1: var(--lime-5); --_accent-2: var(--lime-4); --_bg: var(--surface-2); --_ink: var(--text-1); color: var(--_ink); border-color: var(--_accent-2); background-color: var(--_bg); justify-self: flex-start; }
.gradient-swatch { border-radius: var(--radius-2); aspect-ratio: var(--ratio-landscape); }
pre > code { box-shadow: var(--shadow-6); font-family: var(--font-mono); font-size: var(--font-size-2); }
.yellow-badge { padding-inline: var(--size-1); border-width: var(--border-size-1); border-color: var(--yellow-6); color: var(--yellow-2); border-radius: var(--radius-round); @nest [data-theme="light"] & { border-color: var(--orange-2); color: var(--orange-6); } }
.block-wrap { display: flex; flex-wrap: wrap; flex-basis: var(--size-content-2); gap: var(--size-5) var(--size-8); align-items: flex-start; }
.demo-gallery figure { border-radius: var(--radius-3); box-shadow: var(--shadow-4); }
.op-icon-p { stroke: var(--indigo-2); @nest a:hover & { stroke: var(--indigo-1); } @nest [data-theme="light"] & { stroke: var(--indigo-9); @nest a:hover & { stroke: var(--indigo-8); } } }
.checkmark-list { align-self: flex-start; display: grid; gap: var(--size-2); font-size: var(--font-size-fluid-1); font-weight: var(--font-weight-2); padding-inline-start: 0; }
These props come in many flavors:CSS,PostCSS,JSON, orJavascript. Get em from aCDN orNPM. Try it in browser withPreact,Vite,Vanilla Extract,Lit,Qwik, you name it, it's in thishelpful Stackblitz collection
Need help?
Ask a question onDiscord
No installation required.
/* the props */ @import "https://unpkg.com/open-props"; /* optional imports that use the props */ @import "https://unpkg.com/open-props/normalize.min.css"; @import "https://unpkg.com/open-props/buttons.min.css"; /* just dark or light themes */ @import "https://unpkg.com/open-props/normalize.dark.min.css"; @import "https://unpkg.com/open-props/buttons.dark.min.css"; @import "https://unpkg.com/open-props/normalize.light.min.css"; @import "https://unpkg.com/open-props/buttons.light.min.css"; /* individual imports */ @import "https://unpkg.com/open-props/indigo.min.css"; @import "https://unpkg.com/open-props/indigo-hsl.min.css"; @import "https://unpkg.com/open-props/easings.min.css"; @import "https://unpkg.com/open-props/animations.min.css"; @import "https://unpkg.com/open-props/sizes.min.css"; @import "https://unpkg.com/open-props/gradients.min.css"; /* see PropPacks for the full list */
<!-- the props --> <link rel="stylesheet" href="https://unpkg.com/open-props"/> <!-- optional imports that use the props --> <link rel="stylesheet" href="https://unpkg.com/open-props/normalize.min.css"/> <link rel="stylesheet" href="https://unpkg.com/open-props/buttons.min.css"/> <!-- individual imports --> <link rel="stylesheet" href="https://unpkg.com/open-props/indigo.min.css"/> <link rel="stylesheet" href="https://unpkg.com/open-props/indigo-hsl.min.css"/> <link rel="stylesheet" href="https://unpkg.com/open-props/easings.min.css"/> <link rel="stylesheet" href="https://unpkg.com/open-props/animations.min.css"/> <link rel="stylesheet" href="https://unpkg.com/open-props/sizes.min.css"/> <link rel="stylesheet" href="https://unpkg.com/open-props/gradients.min.css"/> <!-- see PropPacks for the full list -->
// the props import 'https://unpkg.com/open-props'; // optional imports that use the props import 'https://unpkg.com/open-props/normalize.min.css'; import 'https://unpkg.com/open-props/buttons.min.css'; // just go dark themed or light themed import 'https://unpkg.com/open-props/normalize.dark.min.css'; import 'https://unpkg.com/open-props/buttons.dark.min.css'; import 'https://unpkg.com/open-props/normalize.light.min.css'; import 'https://unpkg.com/open-props/buttons.light.min.css'; // individual imports import 'https://unpkg.com/open-props/indigo.min.css'; import 'https://unpkg.com/open-props/indigo-hsl.min.css'; import 'https://unpkg.com/open-props/easings.min.css'; import 'https://unpkg.com/open-props/animations.min.css'; import 'https://unpkg.com/open-props/sizes.min.css'; import 'https://unpkg.com/open-props/gradients.min.css'; // see PropPacks for the full list
/* the props */ @import "https://unpkg.com/open-props/src/index.css"; /* optional imports that use the props */ @import "https://unpkg.com/open-props/src/extra/normalize.css"; @import "https://unpkg.com/open-props/src/extra/buttons.css"; /* individual imports */ @import "https://unpkg.com/open-props/src/indigo.min.css"; @import "https://unpkg.com/open-props/src/indigo-hsl.min.css"; @import "https://unpkg.com/open-props/src/easings.min.css"; @import "https://unpkg.com/open-props/src/animations.min.css"; @import "https://unpkg.com/open-props/src/sizes.min.css"; @import "https://unpkg.com/open-props/src/gradients.min.css"; /* see PropPacks for the full list */
Not all props can be represented as a design token.
Community createdsetup instructions.
https://unpkg.com/open-props/open-props.figma-tokens.json https://unpkg.com/open-props/open-props.figma-tokens.sync.json
import "open-props/style-dictionary-tokens" // or import "open-props/open-props.style-dictionary-tokens.json"
https://unpkg.com/open-props/open-props.style-dictionary-tokens.json
/* the props */ @import "open-props/shadow/style"; @import "open-props/open-props.shadow.min.css"; /* individual imports */ @import "open-props/shadow/indigo"; @import "open-props/shadow/indigo-hsl"; @import "open-props/shadow/easings"; @import "open-props/shadow/animations"; @import "open-props/shadow/sizes"; @import "open-props/shadow/gradients"; /* see PropPacks for the full list */
These props are scoped to:host for use in shadow DOM.
/* the props */ @import "https://unpkg.com/open-props/open-props.shadow.min.css"; /* individual imports */ @import "https://unpkg.com/open-props/indigo.shadow.min.css"; @import "https://unpkg.com/open-props/indigo.shadow-hsl.min.css"; @import "https://unpkg.com/open-props/easings.shadow.min.css"; @import "https://unpkg.com/open-props/animations.shadow.min.css"; @import "https://unpkg.com/open-props/sizes.shadow.min.css"; @import "https://unpkg.com/open-props/gradients.shadow.min.css"; /* see PropPacks for the full list */
npm install open-props
/* the props */ @import "open-props/style"; /* optional imports that use the props */ @import "open-props/normalize"; @import "open-props/buttons"; /* just light or dark themes */ @import "open-props/normalize/dark"; @import "open-props/buttons/dark"; @import "open-props/normalize/light"; @import "open-props/buttons/light"; /* individual imports */ @import "open-props/indigo"; @import "open-props/easings"; @import "open-props/animations"; @import "open-props/sizes"; @import "open-props/gradients"; /* see PropPacks for the full list */
/* the props */ @import "open-props/open-props.min.css"; /* optional imports that use the props */ @import "open-props/normalize.min.css"; @import "open-props/buttons.min.css"; /* individual imports */ @import "open-props/indigo.min.css"; @import "open-props/easings.min.css"; @import "open-props/animations.min.css"; @import "open-props/sizes.min.css"; @import "open-props/gradients.min.css"; /* see PropPacks for the full list */
/* the props */ @import "open-props/postcss/style"; /* optional imports that use the props */ @import "open-props/postcss/normalize"; @import "open-props/postcss/buttons"; /* individual imports */ @import "open-props/postcss/indigo"; @import "open-props/postcss/easings"; @import "open-props/postcss/animations"; @import "open-props/postcss/sizes"; @import "open-props/postcss/gradients"; /* see PropPacks for the full list */
/* the props */ @import "open-props/postcss/index.css"; /* optional imports that use the props */ @import "open-props/postcss/extra/normalize.css"; @import "open-props/postcss/extra/buttons.css"; /* individual imports */ @import "open-props/postcss/indigo.min.css"; @import "open-props/postcss/easings.min.css"; @import "open-props/postcss/animations.min.css"; @import "open-props/postcss/sizes.min.css"; @import "open-props/postcss/gradients.min.css"; /* see PropPacks for the full list */
// index.js loading JS object import OpenProps from 'open-props'; // module import OpenProps from 'open-props/src'; // unbundled ES module import Colors from 'open-props/src/colors'; // object notation access is special to OpenProps console.info(OpenProps.size1); console.info(OpenProps['--size-1']); console.info(Colors['--indigo-5']);
// import just 1 color set object import {Indigo} from 'open-props/src/colors'; // import shadows without prop deps import {StaticShadows} from 'open-props/src/shadows'; // import the gradients import Gradients from 'open-props/src/gradients'; // see PropPacks for the full list
/* 3 ways to import */ import 'open-props/tokens' import 'open-props/json' import 'open-props/design-tokens'
Only ship the props you use.Learn more.
npm install postcss-jit-props
Stop importing Open Props in your CSS (if you were).
This plugin adds them to your stylesheet as you use them 🙂
// postcss.config.js const postcssJitProps = require('postcss-jit-props'); const OpenProps = require('open-props'); module.exports = { plugins: [ postcssJitProps(OpenProps), ] }
// postcss.config.js const postcssJitProps = require('postcss-jit-props'); const path = require('path'); module.exports = { plugins: [ postcssJitProps({ files: [ path.resolve(__dirname, 'node_modules/open-props/open-props.min.css'), ] }), ] }
git clone https://github.com/argyleink/open-props.git
// build src files npm run gen:shadowdom // src files with `:host` instead of `html` npm run gen:nowhere // src files without `:where()` npm run gen:prefixed // each prop prefixed with `op`, like `--op-font-size-1` // full custom! pass args with node to the props.js script node props.js 'ns' true ':root' 'my' ⇣ // arg1: default '', is a custom namespace, props will be --ns-gray-1 // arg2: default false, indicates wrapping in :where() or not // arg3: default '', set a custom selector like :scope, .my-class, etc // arg4: default '', set a file prefix, files will be my.props.easing.css, etc
npm run gen:op // runs through `src/` js files and creates the PostCSS files in `src/` npm run gen:shadowdom // runs through `src/` js files and creates the PostCSS files in `src/` npm run build // does both gen:op and gen:shadowdom npm run bundle // creates all the various minified bundles of props npm run lib:js // builds the JS modules for NPM
node_modules
folder where open-props is installed.vscode/settings.json
file. Take a look at an illustration below // .vscode/settings.json file { "cssvar.files": [ "./node_modules/open-props/open-props.min.css", // if you have an alternative path to where your styles are located // you can add it in this array of files "assets/styles/variables.css" ], // Do not ignore node_modules css files, which is ignored by default "cssvar.ignore": [], // add support for autocomplete in JS or JS like files "cssvar.extensions": [ "css", "postcss", "jsx", "tsx" ] }
// .sublime-completions file { "scope": "./node_modules/open-props/open-props.min.css", "completions": [ // here you'll add the classes you want autocomplete for. ] }
// .sublime-completions file { "scope": "path/to/your/variables", }
"auto-complete-selector": "source, text"
Open Props includesOpen Color, an open-source color scheme optimized for UI development, and its extension,Colar.
Open the color picker in your browser dev tools, set the swatches to the page's custom properties, and enjoy picking from the set!
--gray-{0-12} --stone-{0-12} --red-{0-12} --pink-{0-12} --purple-{0-12} --violet-{0-12} --indigo-{0-12} --blue-{0-12} --cyan-{0-12} --teal-{0-12} --green-{0-12} --lime-{0-12} --yellow-{0-12} --orange-{0-12} --choco-{0-12} --brown-{0-12} --sand-{0-12} --camo-{0-12} --jungle-{0-12}
button.blue { color: var(--blue-6); background-color: var(--blue-0); border: 1px solid var(--blue-1); text-shadow: 0 1px 0 var(--blue-2); &:hover { background-color: var(--blue-1); } }
html { --text-1: var(--gray-9); --text-2: var(--gray-7); @media (--OSdark) { --text-1: var(--gray-1); --text-2: var(--gray-2); } }
/* additional import required */ /* @import "open-props/gray-hsl"; */ @import "open-props/colors-hsl"; .backdrop { background-color: hsl(var(--gray-9-hsl) / 30%); }
Various brand colors.
Not part of the main bundle. Must be individually imported.
@import "open-props/brand-colors";.facebook-logo { fill: var(--brand-facebook);}
Low numbers are light and high numbers are dark. See how the Open Propsnormalize.css implementslight anddark modes.
See it live:auto, light, dark, dim and purple themes demonstrated with Open Props!
html { --brand-light: var(--orange-6); --text-1-light: var(--gray-8); --text-2-light: var(--gray-7); --surface-1-light: var(--gray-0); --surface-2-light: var(--gray-1); --surface-3-light: var(--gray-2); --surface-4-light: var(--gray-3); }
html { --brand-dark: var(--orange-3); --text-1-dark: var(--gray-3); --text-2-dark: var(--gray-5); --surface-1-dark: var(--gray-12); --surface-2-dark: var(--gray-11); --surface-3-dark: var(--gray-10); --surface-4-dark: var(--gray-9); }
html { --brand-dim: var(--orange-4); --text-1-dim: var(--gray-3); --text-2-dim: var(--gray-4); --surface-1-dim: var(--gray-8); --surface-2-dim: var(--gray-7); --surface-3-dim: var(--gray-6); --surface-4-dim: var(--gray-5); }
html { --brand-purple: var(--purple-5); --text-1-purple: var(--purple-9); --text-2-purple: var(--purple-7); --surface-1-purple: var(--purple-0); --surface-2-purple: var(--purple-1); --surface-3-purple: var(--purple-2); --surface-4-purple: var(--purple-3); }
It's not ideal for components to reference individual light or dark theme colors. Instead, you should prefer to use these individual variables to build a set of theme-agnostic aliases. This allows you to reference a custom property without worrying about its underlying value, which will dynamically adapt to the current context's theme.
:root { --brand: var(--brand-light); --text-1: var(--text-1-light); --text-2: var(--text-2-light); --surface-1: var(--surface-1-light); --surface-2: var(--surface-2-light); --surface-3: var(--surface-3-light); --surface-4: var(--surface-4-light); }
@media (prefers-color-scheme: dark) { :root { --brand: var(--brand-dark); --text-1: var(--text-1-dark); --text-2: var(--text-2-dark); --surface-1: var(--surface-1-dark); --surface-2: var(--surface-2-dark); --surface-3: var(--surface-3-dark); --surface-4: var(--surface-4-dark); } }
@media (prefers-contrast: less) { :root { --brand: var(--brand-dim); --text-1: var(--text-1-dim); --text-2: var(--text-2-dim); --surface-1: var(--surface-1-dim); --surface-2: var(--surface-2-dim); --surface-3: var(--surface-3-dim); --surface-4: var(--surface-4-dim); } }
[color-scheme="purple"] { --brand: var(--brand-purple); --text-1: var(--text-1-purple); --text-2: var(--text-2-purple); --surface-1: var(--surface-1-purple); --surface-2: var(--surface-2-purple); --surface-3: var(--surface-3-purple); --surface-4: var(--surface-4-purple); }
Your app is now free to use adaptive custom properties! Now, your team only needs to remember a single naming convention rather than wrestling with individual theming variables. Here are a few examples of how the above color theme system could be used.
html { background-color: var(--surface-1); color: var(--text-1); accent-color: var(--link); }
.surface-1 { background-color: var(--surface-1); color: var(--text-2); } .surface-2 { background-color: var(--surface-2); color: var(--text-2); } .surface-3 { background-color: var(--surface-3); color: var(--text-1); } .surface-4 { background-color: var(--surface-4); color: var(--text-1); }
h1,h2,h3,h4,p,dt { color: var(--text-1); } h5,h6,small,dd { color: var(--text-2); }
@import "https://unpkg.com/open-props/theme.light.switch.min.css"; @import "https://unpkg.com/open-props/theme.dark.switch.min.css";
The Open Propsnormalize.css has light and dark built in, but it only changes with the media query / operating system. If you want users to be able to change this, you'll needOpen Props switch imports. These have the same theme values from normalize, but scoped to selectors.
Light Selectors:.light
|.light-theme
|data-theme="light"
Dark Selectors:.dark
|.dark-theme
|data-theme="dark"
This allows you to apply a light or dark theme to the page or a portion of the page using the selectors imported.
See it in action:here
When you need to control the appearance of a specific section, use any of the selectors from the switch imports, like.dark
or.light
, and apply them to HTML elements.
Try ithere
@import "https://unpkg.com/open-props/theme.light.switch.min.css"; @import "https://unpkg.com/open-props/theme.dark.switch.min.css"; /* classes toggle the adaptive props */ .dark, .light { color: var(--text-1); background: var(--surface-1); }
Open Props includes 30 handcrafted gradients. Linear gradient direction can be changed with a custom property mixin.
Don't miss the noise props inspired bygrainy-gradients.
--gradient-{1-30}
header { background-image: var(--gradient-5); @media (--OSdark) { background-image: var(--gradient-15); } }
.gradient-text { background: var(--gradient-1); -webkit-background-clip: text; -webkit-text-fill-color: transparent; }
--noise-{1-5} --noise-filter-{1-5}
.noise-noise-noise { /* stack grain with a gradient */ background-image: var(--gradient-3), var(--noise-3); /* force colors and noise to collide */ filter: var(--noise-filter-3); /* fit noise image to element */ background-size: cover; }
Variable and static font sizes, smart line heights,modern font stacks, and other familiar typography variables, all ready to go.
--font-size-{00-8} --font-size-fluid-{0-3} --font-weight-{1-9} --font-letterspacing-{0-7} --font-lineheight-{00-5}
.hero { line-height: var(--font-lineheight-1); font-size: var(--font-size-fluid-3); font-weight: var(--font-weight-9); font-family: var(--font-sans); }
These rad font-families fromDan Klammer'smodern font stacks provide great typefaces that are entirely local. With these font stacks you won't have to worry about slowing down your page load or layout shift from external fonts!
--font-system-ui: system-ui, sans-serif; --font-transitional: Charter, Bitstream Charter, Sitka Text, Cambria, serif; --font-old-style: Iowan Old Style, Palatino Linotype, URW Palladio L, P052, serif; --font-humanist: Seravek, Gill Sans Nova, Ubuntu, Calibri, DejaVu Sans, source-sans-pro, sans-serif; --font-geometric-humanist: Avenir, Montserrat, Corbel, URW Gothic, source-sans-pro, sans-serif; --font-classical-humanist: Optima, Candara, Noto Sans, source-sans-pro, sans-serif; --font-neo-grotesque: Inter, Roboto, Helvetica Neue, Arial Nova, Nimbus Sans, Arial, sans-serif; --font-monospace-slab-serif: Nimbus Mono PS, Courier New, monospace; --font-monospace-code: Dank Mono, Operator Mono, Inconsolata, Fira Mono, ui-monospace, SF Mono,Monaco, Droid Sans Mono, Source Code Pro, Cascadia Code,Menlo, Consolas, DejaVu Sans Mono, monospace; --font-industrial: Bahnschrift, DIN Alternate, Franklin Gothic Medium, Nimbus Sans Narrow, sans-serif-condensed, sans-serif; --font-rounded-sans: ui-rounded, Hiragino Maru Gothic ProN, Quicksand, Comfortaa, Manjari, Arial Rounded MT, Arial Rounded MT Bold, Calibri, source-sans-pro, sans-serif; --font-slab-serif: Rockwell, Rockwell Nova, Roboto Slab, DejaVu Serif, Sitka Small, serif; --font-antique: Superclarendon, Bookman Old Style, URW Bookman, URW Bookman L, Georgia Pro, Georgia, serif; --font-didone: Didot, Bodoni MT, Noto Serif Display, URW Palladio L, P052, Sylfaen, serif; --font-handwritten: Segoe Print, Bradley Hand, Chilanka, TSCu_Comic, casual, cursive;
Unlike the other props, which are identical to their modern font stack counterparts,--font-monospace-code
is modified in open-props.
--font-system-ui
--font-transitional
--font-old-style
--font-humanist
--font-geometric-humanist
--font-classical-humanist
--font-neo-grotesque
--font-monospace-slab-serif
--font-monospace-code
--font-industrial
--font-rounded-sans
--font-slab-serif
--font-antique
--font-didone
--font-handwritten
--font-weight-1: 100; --font-weight-2: 200; --font-weight-3: 300; --font-weight-4: 400; --font-weight-5: 500; --font-weight-6: 600; --font-weight-7: 700; --font-weight-8: 800; --font-weight-9: 900;
--font-letterspacing-0: -.05em; --font-letterspacing-1: .025em; --font-letterspacing-2: .050em; --font-letterspacing-3: .075em; --font-letterspacing-4: .150em; --font-letterspacing-5: .500em; --font-letterspacing-6: .750em; --font-letterspacing-7: 1em;
--font-lineheight-00: .95; --font-lineheight-0: 1.1; --font-lineheight-1: 1.25; --font-lineheight-2: 1.375; --font-lineheight-3: 1.5; --font-lineheight-4: 1.75; --font-lineheight-5: 2;
--font-size-00: .5rem; --font-size-0: .75rem; --font-size-1: 1rem; --font-size-2: 1.1rem; --font-size-3: 1.25rem; --font-size-4: 1.5rem; --font-size-5: 2rem; --font-size-6: 2.5rem; --font-size-7: 3rem; --font-size-8: 3.5rem;
var(--font-size-00)
Almost before you knew it, we'd touched ground.var(--font-size-0)
Almost before you knew it, we'd touched ground.var(--font-size-1)
Almost before you knew it, we'd touched ground.var(--font-size-2)
Almost before you knew it, we'd touched ground.var(--font-size-3)
Almost before you knew it, we'd touched ground.var(--font-size-4)
Almost before you knew it, we'd touched ground.var(--font-size-5)
Almost before you knew it, we'd touched ground.var(--font-size-6)
Almost before you knew it, we'd touched ground.var(--font-size-7)
Almost before you knew it, we'd touched ground.var(--font-size-8)
Almost before you knew it, we'd touched ground. --font-size-fluid-0: clamp(.75rem, 2vw, 1rem); --font-size-fluid-1: clamp(1rem, 4vw, 1.5rem); --font-size-fluid-2: clamp(1.5rem, 6vw, 2.5rem); --font-size-fluid-3: clamp(2rem, 9vw, 3.5rem);
var(--font-size-fluid-0)
Almost before you knew it, we'd touched ground.var(--font-size-fluid-1)
Almost before you knew it, we'd touched ground.var(--font-size-fluid-2)
Almost before you knew it, we'd touched ground.var(--font-size-fluid-3)
Almost before you knew it, we'd touched ground.Premadekeyframe effects allow you to orchestrate your own animations. Plus, a few nice attention-grabbers and indeterminate state animations.
--animation-fade-{in,out} --animation-fade-{in,out}-bloom --animation-shake-{x,y,z} --animation-slide-out-{up,down,left,right} --animation-slide-in-{up,down,left,right} --animation-spin --animation-ping --animation-blink --animation-float --animation-bounce --animation-pulse
.loaded { animation: var(--animation-fade-in) forwards; } .actionsheet { animation: var(--animation-slide-out-down) forwards; &.open { animation: var(--animation-slide-in-up) forwards; } } .alert { animation: var(--animation-blink); }
.slide-fade { animation: var(--animation-fade-out) forwards, var(--animation-slide-out-down); animation-timing-function: var(--ease-elastic-in-out-3); animation-duration: 1s; }
.shake-in { animation: var(--animation-shake-y), var(--animation-fade-in), var(--animation-slide-in-left); }
.push-out { animation: var(--animation-scale-down), var(--animation-fade-out); animation-timing-function: var(--ease-elastic-in-out-4); }
Sizes use relative units by default withrem
but static,px
-based units are also available.0
s are unsafe but common negative values, while 1-N are safe.
--size-{000-15} --size-px-{000-15} --size-fluid-{1-10} --size-content-{1-3} --size-header-{1-3} --size-relative-{000-15}
--size-000: -.5rem; --size-00: -.25rem; --size-1: .25rem; --size-2: .5rem; --size-3: 1rem; --size-4: 1.25rem; --size-5: 1.5rem; --size-6: 1.75rem; --size-7: 2rem; --size-8: 3rem; --size-9: 4rem; --size-10: 5rem; --size-11: 7.5rem; --size-12: 10rem; --size-13: 15rem; --size-14: 20rem; --size-15: 30rem;
--size-px-000: -8px; --size-px-00: -4px; --size-px-1: 4px; --size-px-2: 8px; --size-px-3: 16px; --size-px-4: 20px; --size-px-5: 24px; --size-px-6: 28px; --size-px-7: 32px; --size-px-8: 48px; --size-px-9: 64px; --size-px-10: 80px; --size-px-11: 120px; --size-px-12: 160px; --size-px-13: 240px; --size-px-14: 320px; --size-px-15: 480px;
article { display: grid; gap: var(--size-3); } li { padding-inline-start: var(--size-2); } .icon { inline-size: var(--size-5); block-size: var(--size-5); }
--size-fluid-1: clamp(.5rem, 1vw, 1rem); --size-fluid-2: clamp(1rem, 2vw, 1.5rem); --size-fluid-3: clamp(1.5rem, 3vw, 2rem); --size-fluid-4: clamp(2rem, 4vw, 3rem); --size-fluid-5: clamp(4rem, 5vw, 5rem); --size-fluid-6: clamp(5rem, 7vw, 7.5rem); --size-fluid-7: clamp(7.5rem, 10vw, 10rem); --size-fluid-8: clamp(10rem, 20vw, 15rem); --size-fluid-9: clamp(15rem, 30vw, 20rem); --size-fluid-10: clamp(20rem, 40vw, 30rem);
body { padding: var(--size-fluid-3); } hr { margin-block: var(--size-fluid-5); }
--size-content-1: 20ch; --size-content-2: 45ch; --size-content-3: 60ch;
p { max-inline-size: var(--size-content-3); } aside { max-inline-size: var(--size-content-2); }
Carrot cake gummi bears sweet caramels cotton candy topping.
Carrot cake gummi bears sweet caramels cotton candy topping. Jelly candy apple pie gingerbread tootsie roll chupa chups.
Carrot cake gummi bears sweet caramels cotton candy topping. Jelly candy apple pie gingerbread tootsie roll chupa chups. Gummi bears lollipop apple pie pudding tart cake jelly. Soufflé lollipop jelly-o chocolate bar icing bonbon.
--size-header-1: 20ch; --size-header-2: 25ch; --size-header-3: 35ch;
h1 { max-inline-size: var(--size-header-2); } small { max-inline-size: var(--size-header-1); }
--size-relative-000: -.5ch; --size-relative-00: -.25ch; --size-relative-1: .25ch; --size-relative-2: .5ch; --size-relative-3: 1ch; --size-relative-4: 1.25ch; --size-relative-5: 1.5ch; --size-relative-6: 1.75ch; --size-relative-7: 2ch; --size-relative-8: 3ch; --size-relative-9: 4ch; --size-relative-10: 5ch; --size-relative-11: 7.5ch; --size-relative-12: 10ch; --size-relative-13: 15ch; --size-relative-14: 20ch; --size-relative-15: 30ch;
Sizes, corner radii, a circle helper,conditional radii, radii that produce ahand-drawn border, and some blobs.
--border-size-{1-5} --radius-{1-6} --radius-round --radius-drawn-{1-6} --radius-blob-{1-5} --radius-conditional-{1-6}
.card { /* no radius when fullscreen */ border-radius: var(--radius-conditional-3); border: var(--border-size-1) solid var(--gray-1); } .circle { inline-size: var(--size-5); aspect-ratio: var(--ratio-square); border-radius: var(--radius-round); } .drawn { inline-size: var(--size-14); border: var(--brown-12) var(--border-size-4) solid; border-radius: var(--radius-drawn-1); }
Currently one step ahead ofthe CSS spec, Open Props offers named media queries with the@custom-media
syntax. Available only withthis PostCSS plugin, for now 😈
Media query widths also available as custom properties. Use likevar(--size-sm)
240px
360px
480px
768px
1024px
1440px
1920px
--portrait --landscape --{xxs,xs,sm,md,lg,xl,xxl}-only --{xxs,xs,sm,md,lg,xl,xxl}-n-above --{xxs,xs,sm,md,lg,xl,xxl}-n-below --{xxs,xs,sm,md,lg}-phone
@custom-media --portrait (orientation: portrait); @custom-media --landscape (orientation: landscape); @custom-media --md-only (480px <= width < 768px); @custom-media --md-n-above (width >= 768px); @custom-media --md-n-below (width < 768px); @custom-media --md-phone (--md-only) and (--portrait); @custom-media --xxl-only (1440px <= width < 1920px); @custom-media --xxl-n-above (width >= 1920px); @custom-media --xxl-n-below (width < 1920px);
@custom-media --touch (hover: none) and (pointer: coarse); @custom-media --stylus (hover: none) and (pointer: fine); @custom-media --pointer (hover) and (pointer: coarse); @custom-media --mouse (hover) and (pointer: fine); @custom-media --HDcolor (dynamic-range: high) or (color-gamut: p3);
@custom-media --OSdark (prefers-color-scheme: dark); @custom-media --OSlight (prefers-color-scheme: light); @custom-media --motionOK (prefers-reduced-motion: no-preference); @custom-media --motionNotOK (prefers-reduced-motion: reduce); @custom-media --invertedColors (inverted-colors: inverted); @custom-media --forcedColors (forced-colors: active);
@custom-media --highContrast (prefers-contrast: more); @custom-media --lowContrast (prefers-contrast: less); @custom-media --opacityOK (prefers-reduced-transparency: no-preference); @custom-media --opacityNotOK (prefers-reduced-transparency: reduce); @custom-media --useDataOK (prefers-reduced-data: no-preference); @custom-media --useDataNotOK (prefers-reduced-data: reduce);
html { background: white; color: var(--gray-8); } @media (--OSdark) { html { background: var(--gray-9); color: var(--gray-1); } }
transform: translateX(100%); @media (--motionOK) { transition: transform .5s var(--ease-3); }
Rad edges and corner-cuts ready to go. A huge shout out toTemani Afif andtheir amazing mask work. Be sure to check out theirCSS Generators too; customize the size and distribution of these masks. Try onCodepen.
Not part of the main bundle. Must be individually imported.
@import "open-props/masks/edges"; @import "open-props/masks/corner-cuts"; .box-with-corner-cuts { -webkit-mask: var(--mask-corner-cut-angles-2); } .box-with-zig-zag-on-bottom { -webkit-mask: var(--mask-edge-zig-zag-bottom); }
/* NPM */ @import "open-props/masks/edges"; @import "open-props/src/props.masks.edges.css"; @import "open-props/masks.edges.min.css"; /* CDN */ @import "https://unpkg.com/open-props/masks.edges.min.css";
--mask-edge-scoop-{top,right,bottom,left,vertical,horizontal} .mask-usage { -webkit-mask: var(--mask-edge-scoop-top); }
--mask-edge-scalloped-{edges,top,right,bottom,left,vertical,horizontal} .mask-usage { -webkit-mask: var(--mask-edge-scalloped-edges); }
--mask-edge-drip-{top,right,bottom,left,vertical,horizontal} .mask-usage { -webkit-mask: var(--mask-edge-drip-bottom); }
--mask-edge-zig-zag-{top,right,bottom,left,vertical,horizontal} .mask-usage { -webkit-mask: var(--mask-edge-zig-zag-bottom); }
/* NPM */ @import "open-props/masks/corner-cuts"; @import "open-props/src/props.masks.corner-cuts.css"; @import "open-props/masks.corner-cuts.min.css"; /* CDN */ @import "https://unpkg.com/open-props/masks.corner-cuts.min.css";
--mask-corner-cut-squares-{1,2,3} .mask-usage { -webkit-mask: var(--mask-corner-cut-squares-2); }