{"id":21606290,"url":"https://github.com/zaydek/duomo","last_synced_at":"2026-01-05T04:04:02.234Z","repository":{"id":55077320,"uuid":"304644518","full_name":"zaydek/duomo","owner":"zaydek","description":"CSS component for implementing layout","archived":false,"fork":false,"pushed_at":"2021-09-28T01:25:18.000Z","size":1876,"stargazers_count":20,"open_issues_count":10,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-18T14:50:07.745Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"SCSS","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zaydek.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-10-16T14:04:21.000Z","updated_at":"2023-08-25T04:49:42.000Z","dependencies_parsed_at":"2022-08-14T11:20:29.415Z","dependency_job_id":null,"html_url":"https://github.com/zaydek/duomo","commit_stats":null,"previous_names":[],"tags_count":65,"template":false,"template_full_name":null,"purl":"pkg:github/zaydek/duomo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zaydek%2Fduomo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zaydek%2Fduomo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zaydek%2Fduomo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zaydek%2Fduomo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zaydek","download_url":"https://codeload.github.com/zaydek/duomo/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zaydek%2Fduomo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28213442,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2026-01-05T02:00:06.358Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-24T20:20:30.028Z","updated_at":"2026-01-05T04:04:02.195Z","avatar_url":"https://github.com/zaydek.png","language":"SCSS","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Introducing Duomo\n\nWhat is Duomo? Duomo is a CSS component that makes implementing layout fun!\n\nDuomo is based on the philosophy that layout and design implementation are separate concerns, and that design should be able to be layered subsequent to layout.\n\nIn practice, Duomo is a small collection of utility classes and Sass mixins and functions. Note that Duomo utilities are not strict utility classes in the sense that every class maps to one and only one property / value combination. Instead, Duomo is designed around some higher-order patterns such as `flex-row` instead of `flex flex-row` or `position top-all` instead of `position top-0 right-auto bottom-auto left-auto`.\n\n**Duomo is not for everyone or every project.** Duomo only solves for layout, and needs to be layered with CSS, Sass, etc. in order to be effective. Think of a Duomo as a CSS component, not a CSS library.\n\n## Get Started\n\nIf you need breakpoints, use either one of the following links:\n\n```html\n\u003clink rel=\"stylesheet\" href=\"https://unpkg.com/duomo/dist/duomo.css\" /\u003e\n\u003clink rel=\"stylesheet\" href=\"https://unpkg.com/duomo/dist/duomo.min.css\" /\u003e\n```\n\nIf you don't need breakpoints, use either one of the following links:\n\n```html\n\u003clink rel=\"stylesheet\" href=\"https://unpkg.com/duomo/duomo/dist/duomo-root-only.css\" /\u003e\n\u003clink rel=\"stylesheet\" href=\"https://unpkg.com/duomo/duomo/dist/duomo-root-only.min.css\" /\u003e\n```\n\nIf you only need the CSS reset / base, use either one of the following links:\n\n```html\n\u003clink rel=\"stylesheet\" href=\"https://unpkg.com/duomo/duomo/dist/reset.css\" /\u003e\n\u003clink rel=\"stylesheet\" href=\"https://unpkg.com/duomo/duomo/dist/reset.min.css\" /\u003e\n```\n\nIf you need sourcemaps, simply concatenate `.map` to the filename. For example, [`duomo.css.map`](https://unpkg.com/duomo/dist/duomo.css.map).\n\n## Build Sizes\n\nTo see the exact kB size for every artifact, open [`dist/stats.txt`](/dist/stats.txt). Here's an idea of what you can expect:\n\n```\n// This is the non-minified version\ndist/duomo.css\n+-----------------+\n| text   |  202kB |\n| gzip   |   26kB |\n| brotli |    9kB |\n+-----------------+\n\n// This is the minified version\ndist/duomo.min.css\n+-----------------+\n| text   |  142kB |\n| gzip   |   20kB |\n| brotli |    8kB |\n+-----------------+\n```\n\nDuomo is only acceptable in production when compressed. Also note that Duomo can and should be cached for a long time if not forever if you hash the filename or concatenate the release version. This means that users should only ever need to download Duomo infrequently and is `\u003c10kB` because of compression.\n\n## Supported Properties\n\nDuomo exports utility classes for the following CSS properties:\n\n- [`position`](/#position)\n- [`margin`](/#margin)\n- [`padding`](/#padding)\n- [`flexbox`](/#flexbox)\n- [`aspect-ratio`](/#aspect-ratio) (polyfill using `padding-bottom`)\n- [`width`](/#width)\n- [`height`](/#height)\n- [`border-width`](/#border-width)\n- [`overflow`](/#overflow)\n- [`z-index`](/#z-index)\n\n## API\n\nThe API uses a regex-like pattern to describe all class name combinations.\n\nThis means one class name:\n\n```\nclass-name\n```\n\nThis means one class name, `class-foo` or `class-bar`:\n\n```\nclass-(\n  | foo\n  | bar\n)\n```\n\nThis means the second class name is optional:\n\n```\nclass-name | optional-class-name\n```\n\nThis means the second class name is required:\n\n```\nclass-name \u0026 required-class-name\n```\n\nThis means the second class name is optional and one of `foo` or `bar`:\n\n```\nclass-name | (\n  | foo\n  | bar\n)\n```\n\nThis means the second class name is required and one of `foo` or `bar`:\n\n```\nclass-name \u0026 (\n  | version-a\n  | version-b\n)\n```\n\nIt may seem confusing at first, but because there are many class names, describing them this way should make it easy to reference which class name combinations are supported.\n\n### `position`\n\n```\nrelative\n\n(\n  | relative\n  | absolute\n  | fixed\n  | sticky\n) \u0026 (\n  | all\n  | top-all\n  | top-right-all\n  | right-all\n  | bottom-right-all\n  | bottom-all\n  | bottom-left-all\n  | left-all\n  | top-left-all\n)\n```\n\nFor example:\n\n- `relative`\n- `absolute all`\n\n### `margin`\n\n```\nm-(\n  | \u003cpx\u003e\n  | auto\n)\n\nm(\n  | x\n  | y\n  | t\n  | r\n  | b\n  | l\n)-(\n  | \u003cpx\u003e\n  | auto\n)\n```\n\nFor example:\n\n- `m-16`\n- `m-auto`\n- `mx-16`\n- `mx-auto`\n\n### `padding`\n\n```\np-\u003cpx\u003e\n\np(\n  | x\n  | y\n  | t\n  | r\n  | b\n  | l\n)-\u003cpx\u003e\n```\n\nFor example:\n\n- `p-16`\n- `px-16`\n\n### `flexbox`\n\n```\njustify-self-(\n  | stretch\n  | start\n  | center\n  | end\n  | baseline\n)\n\nalign-self-(\n  | stretch\n  | start\n  | center\n  | end\n  | baseline\n)\n\nflex-(\n  | row\n  | col\n) | justify-(\n  | stretch\n  | start\n  | center\n  | end\n  | baseline\n) | align-(\n  | stretch\n  | start\n  | center\n  | end\n  | baseline\n) | m-gap-\u003cpx\u003e\n\nflex-grow\n```\n\nFor example:\n\n- `self-justify-center`\n- `self-justify-center self-align-center`\n- `flex flex-row justify-center`\n- `flex flex-row justify-center align-center`\n- `flex flex-row justify-center align-center m-gap-16`\n- `flex-grow`\n\n### `display`\n\n```\nhide | show\n\nhide \u0026 flex-(\n  | row\n  | col\n) \u0026 \u003cbreakpoint\u003e:show\n\nshow \u0026 flex-(\n  | row\n  | col\n) \u0026 \u003cbreakpoint\u003e:hide\n```\n\nFor example:\n\n- `hide md:show`\n- `show md:hide`\n- `hide md:show flex-row`\n- `show md:hide flex-row`\n\n### `aspect-ratio`\n\n```\naspect \u0026 aspect-w-\u003cinteger\u003e \u0026 aspect-h-\u003cinteger\u003e\n\naspect-revert\n```\n\nFor example:\n\n- `aspect aspect-w-16 aspect-h-9`\n- `aspect-revert`\n\n### `width`\n\n```\nw-(\n  | \u003cpx\u003e\n  | full\n  | screen\n  | sm\n  | md\n  | lg\n  | xl\n)\n```\n\nFor example:\n\n- `w-16`\n- `w-full`\n- `w-screen`\n- `w-sm`\n- `w-md`\n- `w-lg`\n- `w-xl`\n\n### `height`\n\n```\nh-(\n  | \u003cpx\u003e\n  | full\n  | screen\n)\n\nmin-h-(\n  | 0\n  | full\n  | screen\n)\n```\n\nFor example:\n\n- `h-16`\n- `h-full`\n- `h-screen`\n- `min-h-0`\n- `min-h-full`\n- `min-h-screen`\n\n### `border-width`\n\n```\nborder-\u003cpx\u003e\n\nborder-(\n  | x\n  | y\n  | top\n  | right\n  | bottom\n  | left\n)-\u003cpx\u003e\n```\n\n### `overflow`\n\nFor example:\n\n- `border-4`\n- `border-x-4`\n\n```\noverflow-(\n  | scroll\n  | hidden\n)\n\noverflow-(\n  | x\n  | y\n)-(\n  | scroll\n  | hidden\n)\n```\n\nFor example:\n\n- `overflow-scroll`\n- `overflow-x-scroll`\n\n### `z-index`\n\n```\nz-\u003cinteger\u003e\n```\n\nFor example:\n\n- `z-10`\n\n## Meta Classes\n\nYou may notice that classes such as `hide` and `show` don't map 1:1 with CSS. This is intentional as Duomo is not strictly a utility CSS library. Duomo uses a combination of selector logic and CSS variables where necessary to achieve higher-level APIs that are intuitive and easy to reason about.\n\nThe `m-gap` (short for `margin-gap`), `flex-grow`, `hide`, `show`, and `aspect-ratio` classes are examples of APIs that use selector logic and or CSS variables.\n\n## Ranges\n\nFor classes that use `\u003cpx\u003e` values, Duomo uses a standard range (a range is simply a list of integers) that changes its increment at `20`, `40`, `80`, `160`, and `320`.\n\nHere's the standard range, which can be user-configured:\n\n```scss\n$-duomo-configuration: (\n  // ...\n  range: (\n      0, // Increment by 2\n      1,\n      2,\n      4,\n      6,\n      8,\n     10,\n     12,\n     14,\n     16,\n     18,\n     20, // Increment by 4\n     24,\n     28,\n     32,\n     36,\n     40, // Increment by 8\n     48,\n     56,\n     64,\n     72,\n     80, // Increment by 16\n     96,\n    112,\n    128,\n    144,\n    160, // Increment by 32\n    192,\n    224,\n    256,\n    288,\n    320, // Increment by 64\n    384,\n    448,\n    512,\n    576,\n    640,\n  ),\n  // ...\n);\n```\n\nDifferent properties implement different bounds, which are simply upper and lower limits on the standard range.\n\nHere's the range bounds, which can be user-configured:\n\n```scss\n$-duomo-configuration: (\n  // ...\n  margin-bounds: (\n    -128,\n    128,\n  ),\n  margin-gap-bounds: (\n    0,\n    128,\n  ),\n  padding-bounds: (\n    0,\n    128,\n  ),\n  width-bounds: (\n    0,\n    640,\n  ),\n  height-bounds: (\n    0,\n    640,\n  ),\n  border-width-bounds: (\n    0,\n    8,\n  ),\n  // ...\n);\n```\n\nThis means `margin` supports values inclusively between `-128` and `128`, whereas `border-width` supports values inclusively between `0` and `8`.\n\n## Configuration\n\nWhile Duomo can be configured, Duomo is designed to not rely on configuration. Think of Duomo as a set of immutable classes. Configuring Duomo means the immutability of those classes cannot be guaranteed, therefore only do so when you know what you are doing.\n\nA common use-case for configuration would be disabling some breakpoints or all breakpoints (this is how [`scripts/duomo-root-only.scss`](/scripts/duomo-root-only.scss) works). Another common use-case would be tweaking breakpoint values.\n\nHere's how to disable breakpoints:\n\n```scss\n@use \"../duomo\";\n\n@include duomo.configure(\n  (\n    breakpoints: (),\n  ),\n);\n```\n\nAnd Here's how to tweak breakpoints:\n\n```scss\n@use \"../duomo\";\n\n@include duomo.configure(\n  (\n    breakpoints: (\n      sm: 512px,\n    ),\n  ),\n);\n```\n\nNote that you only need to provide key-value pairs for values you want to change. For example, if you want to tweak the `sm` breakpoint, only provide a key-value pair for `sm`. Under the hood, Duomo uses [ordered deep map merging](/duomo/utils/map.scss).\n\n## Sass Mixins\n\nDuomo exports a few mixins to help you configure Duomo and or generate your own `duomo.css` file.\n\n```scss\n// This is how you import Duomo in Sass-land\n@use \"duomo\";\n\n// Optionally configure Duomo by providing key-value pairs you want to override\nduomo.configure(\n  breakpoints: (\n    // Tweak `sm` to `512px`\n    sm: 512px,\n  ),\n);\n\n// The CSS reset / base Tailwind CSS uses\nduomo.reset;\n\n// Generate Duomo classes\nduomo.classes;\n```\n\n## Sass Functions\n\nDuomo exports a few functions to help you layer your design implementation.\n\n```scss\n@use \"duomo\" as *;\n\n// `duomo` is an accessor for configured key-value pairs\n\n@debug duomo(nrange);\n// -\u003e (-640, -576, ...)\n\n@debug duomo(range);\n// -\u003e (0, 1, ...)\n\n@debug duomo(margin-bounds);\n// -\u003e (-128, 128)\n\n@debug duomo(margin-gap-bounds);\n// -\u003e (0, 128)\n\n@debug duomo(padding-bounds);\n// -\u003e (0, 128)\n\n@debug duomo(width-bounds);\n// -\u003e (0, 640)\n\n@debug duomo(height-bounds);\n// -\u003e (0, 640)\n\n@debug duomo(border-width-bounds);\n// -\u003e (0, 8)\n\n@debug duomo(breakpoints);\n// -\u003e (sm: 640px, md: 768px, lg: 1024px, xl: 1280px)\n```\n\nFurthermore, Duomo implements Tailwind CSS's design tokens:\n\n```scss\n@use \"duomo\" as *;\n\n// `tailwind` is an accessor for configured key-value pairs\n\n// https://tailwindcss.com/docs/font-family\n@debug tailwind(\u003cfont\u003e);\n\n// https://tailwindcss.com/docs/customizing-colors\n@debug tailwind(\u003ccolor\u003e-\u003ckey\u003e);\n\n// https://tailwindcss.com/docs/box-shadow\n@debug tailwind(shadow-\u003ckey\u003e);\n\n// https://tailwindcss.com/docs/transition-timing-function\n@debug tailwind(ease-\u003ckey\u003e);\n```\n\nNote that Tailwind CSS design tokens [can be configured in the same manner as Duomo](#configuration).\n\nAnd finally, unit functions for converting between types. Note that Duomo relies on `rem` units exclusively behind the scenes.\n\n```scss\n@use \"duomo\" as *;\n\n// Convert to `rem` units\n@debug rem(16);\n// -\u003e 1rem\n\n// Convert to `em` units\n@debug em(16);\n// -\u003e 1em\n\n// Convert to `px` units\n@debug px(16);\n// -\u003e 16px\n\n// Dynamically convert to `rem`, `em`, or `px` units\n@debug resolve-unit(16, rem);\n// -\u003e 1rem\n```\n\n## Themeable API (Sass)\n\nThe `themeable` API exports functions for:\n\n- `background-color`\n- `border-color`\n- `box-shadow`\n- `color`\n- `fill`\n- `opacity`\n- `stroke`\n\nNote that the second argument `$dark-value` is optional.\n\n```scss\n@use \"duomo\" as *;\n\n// Note that Sass CSS variables need to use interpolation syntax, e.g. `#{...}`\n:root {\n  --color: #{color(#000, #fff)};\n  --background-color: #{background-color(#fff, #000)};\n}\n// -\u003e :root {\n// -\u003e   --color: #000;\n// -\u003e   --background-color: #fff;\n// -\u003e }\n// -\u003e :root[data-theme=\"dark\"] {\n// -\u003e   --color: #fff;\n// -\u003e   --background-color: #000;\n// -\u003e }\n\n.foo {\n  @include color(#000, #fff);\n  @include background-color(#fff, #000);\n}\n// -\u003e .foo {\n// -\u003e   color: #000;\n// -\u003e   background-color: #fff;\n// -\u003e }\n// -\u003e :root[data-theme=\"dark\"] .foo {\n// -\u003e   color: #fff;\n// -\u003e   background-color: #000;\n// -\u003e }\n```\n\n## Transition API (Sass)\n\n```scss\n@use \"duomo\" as *;\n\n.foo {\n  transition: transition((color, background-color), 1s, ease-out);\n}\n// -\u003e .foo {\n// -\u003e   transition: color 1s ease-out,\n// -\u003e     background-color 1s ease-out;\n// -\u003e }\n\n.foo {\n  transition: transition((background-color, border-color, box-shadow, color, fill, opacity, stroke), 1s, ease-out);\n}\n// -\u003e .foo {\n// -\u003e   transition: background-color 1s ease-out,\n// -\u003e     border-color 1s ease-out,\n// -\u003e     box-shadow 1s ease-out,\n// -\u003e     color 1s ease-out,\n// -\u003e     fill 1s ease-out,\n// -\u003e     opacity 1s ease-out,\n// -\u003e     stroke 1s ease-out;\n// -\u003e }\n```\n\nNote that the last argument `$delay` is optional.\n\n---\n\n## License\n\nDuomo is licensed as [MIT open source](/LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzaydek%2Fduomo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzaydek%2Fduomo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzaydek%2Fduomo/lists"}