{"id":13652100,"url":"https://github.com/anthonyshort/idiomatic-sass","last_synced_at":"2025-04-12T05:20:45.881Z","repository":{"id":8243359,"uuid":"9687892","full_name":"anthonyshort/idiomatic-sass","owner":"anthonyshort","description":"Principles for writing consistent, clean, friendly Sass","archived":false,"fork":false,"pushed_at":"2016-06-07T12:28:45.000Z","size":125,"stargazers_count":230,"open_issues_count":3,"forks_count":14,"subscribers_count":15,"default_branch":"master","last_synced_at":"2024-04-15T03:16:20.296Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/anthonyshort.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-04-26T05:19:18.000Z","updated_at":"2023-11-04T13:15:17.000Z","dependencies_parsed_at":"2022-08-06T23:15:30.868Z","dependency_job_id":null,"html_url":"https://github.com/anthonyshort/idiomatic-sass","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anthonyshort%2Fidiomatic-sass","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anthonyshort%2Fidiomatic-sass/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anthonyshort%2Fidiomatic-sass/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anthonyshort%2Fidiomatic-sass/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/anthonyshort","download_url":"https://codeload.github.com/anthonyshort/idiomatic-sass/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248520096,"owners_count":21117875,"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","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-08-02T02:00:55.328Z","updated_at":"2025-04-12T05:20:45.853Z","avatar_url":"https://github.com/anthonyshort.png","language":null,"funding_links":[],"categories":["Styling","Others"],"sub_categories":["Sass"],"readme":"# Principles of writing idiomatic Sass\n\nWhile many people think of Sass as just CSS there are many unique challenges that \nneed to be addressed if we want to be able to write the best possible code. In\nthis document I'll go through some coding styles that will help you share code\nwith others and avoid a common pitfalls.\n\nIn addition to many of these principles you should read [Idiomatic CSS](https://github.com/necolas/idiomatic-css)\nand apply standard CSS best-practices along with these. Understanding how to write\ngreat CSS is the foundation this is built upon. For this reason, there will be a\nbit of overlap.\n\n## Table of Contents\n\n1. [Object-Oriented Sass](#oosass)\n2. [Naming Conventions](#naming-conventions)\n3. [Selectors](#selectors)\n4. [Properties](#properties)\n   * [Ordering](#ordering)\n5. [Nesting](#nesting)\n6. [Indentation](#indentation)\n7. [File Structure](#file-structure)\n8. [Functions](#functions)\n9. [Mixins](#mixins)\n10. [Modules](#modulespackages)\n   * [File Structure](#file-structure-1)\n   * [Namespacing](#namespacing)\n   * [Module Entry Point](#module-entry-point)\n   * [Package Management](#package-management)\n   * [Load Paths](#load-paths)\n   * [Dependencies](#dependencies)\n11. [Definitions](#definitions)\n\n## Object-Oriented Sass\n\nWriting good Sass code starts with correctly dividing and modularizing your objects. It is arguably more\nimportant than any other aspect of writing CSS.\n\nWell-written Sass is:\n\n### Decoupled\n\nObjects should never manipulate other objects. eg. `.message` would never change the style of a nested object \ncalled `.list`. Instead use child selectors like `.message__list` and use both classes in the markup \n`\u003cdiv class=\"list message__list\"\u003e` or use a modifier `\u003cdiv class=\"message\"\u003e\u003cdiv class=\"list list--small\"\u003e\u003c/div\u003e\u003c/div\u003e`\n\n### Specific\n\nBreak functionality into smaller objects. Each object should do one thing and do it well.\n\n### Not location-based\n\nNever, ever use location-based styling. This means a block is never styled different because it is within another block. Objects should have \"modifiers\" instead of location-related styles `.block--large {}` instead of `#sidebar .block {}`\n\n### Never uses IDs\n\nYep, never. You don't need them and they aren't re-usable by nature\n\n### Separates layout from style. \n\nThis means an object that handles background and border won't control padding and margin. \nStyles generally fall into a couple of categories: layout, texture, typography. Each object \nshould generally only handle one of these. But be pragmatic about it and consider reusability at all times.\n\nEnforce these rules by using one of the naming conventions in the next section.\n\n## Naming Conventions\n\nIt's important that you use a consistent naming convention for your selectors. For this,\nI recommend looking at the [BEM](http://bem.info) or [Montage](http://montagejs.org/docs/Naming-Conventions.html).\n\n### BEM\n\n```scss\n.block-name {}\n.block-name__child-name {}\n.block-name--modifier {}\n```\n\n### Montage\n\n```scss\n.namespace-BlockName {}\n.namespace-BlockName-childName {}\n.namespace-BlockName--modifier {}\n```\n\nThe most important thing is that you pick one as a team and stick with it.\n\n## Selectors\n\n* Use one discrete selector per line in multi-selector rulesets.\n* Quote attribute values in selectors, e.g., input[type=\"checkbox\"].\n* Place the closing brace of a ruleset in the same column as the first character of the ruleset.\n* Separate each ruleset by a blank line.\n* Include a single space before the opening brace of a ruleset.\n\n## Properties\n\n* Include one declaration per line in a declaration block.\n* Use one level of indentation for each declaration.\n* Use lowercase and shorthand hex values, e.g., #aaa.\n* Use single or double quotes consistently. Preference is for double quotes, e.g., content: \"\".\n* Where allowed, avoid specifying units for zero-values, e.g., margin: 0.\n* Include a semi-colon at the end of the last declaration in a declaration block.\n* Include a space after each comma in comma-separated property or function values.\n\n### Ordering\n\n1. `$variable` should **always** appear at the top. \n2. `@extend` should always appear before properties. It's like extending a class in Ruby.\n3. `@include` should appear second. This allows the properties to override the mixins.\n4. Properties should appear after this, optionally grouped by type or sorted alphabetically.\n5. Mixins with content blocks should appear next. `@include someMixin { properties }`\n6. Selectors that target itself. `\u0026.modifier`\n7. Child selectors appear last.\n\nThe basic rule of thumb is at-rules, properties, then blocks.\n\nHere is an example of a well-formed selector:\n\n```scss\n.selector-1,\n.selector-2,\n.selector-3[type=\"text\"]  {\n  $bg: blue;\n  $fallback: green;\n\n  @extend .clearfix;\n  @include border-box;\n\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n  display: block;\n  font-family: helvetica, arial, sans-serif;\n  color: #333;\n  background: #fff;\n  background: linear-gradient(#fff, rgba(0, 0, 0, 0.8));\n\n  @include after {\n    position: absolute;\n  }\n\n  \u0026.selector--modifier {\n    background: red;\n  }\n\n  .selector__child {\n    display: none;\n  }\n}\n```\n\n## Nesting\n\n* Avoid nesting more than 2 deep. This is a sign of bad CSS as selectors become too specific.\n* Rulesets within selectors should be separated by a single line and follow the same rules as any other selector.\n\n## Indentation\n\n* Indentation should be 2 spaces\n\n## File Structure\n\n* Each logical module of code should belong in its own file. Avoiding putting multiple objects in the same file. This allows you to use the filesystem to navigate your Sass rather than relying on comment blocks.\n* Mixins/placeholders/functions should, if possible, belong in their own file.\n* Files should be named for the component they are housing. A `block-list` object will live in a `block-list.scss` file.\n\n## Functions\n\n* Functions should be prefix with a dash and a namespace: `-rg-columns`\n* The namespace can be dropped if it is a private function: `columns`\n* Functions should be documented using DocBlock or similar.\n\n## Mixins\n\n* Mixins should only be used when there are dynamic properties, otherwise use `@extend`\n* Mixins that output selectors should be capital-case: `@mixin GridBuilder`\n* Mixins that output only properties should be camel-case: `@mixin borderBox`\n* Mixins should be prefixed if they are part of a public module: `@mixin as-GridBuilder`\n* In general, mixins with logic should not be longer than ~50 lines just like any other programming language\n* Private mixins that are not used outside of the current file should be prefixed with a dash: `@mixin -gridHelper`\n* Avoid using more than 4 parameters. It is a sign that a mixin is too complex. When Sass adds hashes life will be easier.\n* Mixins should be documented\n\n```scss\n// Loop through each breakpoint and build\n// classes for each using the breakpoint mixins\n// First breakpoint is no media query — mobile-first.\n// \n// @param {List} $breakpoints List of column breakpoints\n// @param {Boolean} $spacing Include spacing classes? \n// @param {Boolean} $visibility Include visibilty classes? \n// @param {Boolean} $layout Include layout classes? \n// @api private\n@mixin -rg-Breakpoints($breakpoints, $spacing: true, $visibility: true, $layout: true) {\n  @each $columns in $breakpoints {\n    @if index($breakpoints, $columns) == 1 {\n      @include -rg-BreakpointClasses($columns, $spacing, $visibility, $layout);\n    }\n    @else {\n      @include rg-from($columns) {\n        @include -rg-BreakpointClasses($columns, $spacing, $visibility, $layout);\n      }\n    }\n  }\n}\n```\n\n## Modules/Packages\n\nSharing Sass code is becoming more important. Without the use of a proper module system in Sass \nwe need to establish a few rules so that sharing code is consistent and behaviour is predictable.\nSass packages are popping up in Bower and Github but there is no consistency in the way they \nare implemented. \n\nA few general rules:\n\n* Every module *must* have a namespace\n* Private functions and mixins should be prefixed with a dash: `@mixin -rg-gridUnit`\n* Importing a module should not render any selectors \n* Mixins/placholders/functions should be able to be imported separately `@import \"rg-Grid/mixins\"`\n* Avoid relying on global variables.\n* Use placeholder selectors whenever possible.\n* All global variables must be namespaced.\n\n### File Structure\n\n* Third-party, installed modules should always be placed in a `components` directory.\n* Local modules should live in a `local` directory adjacent to the `components` directory.\n* All images, fonts and other assets should live in an `assets` directory\n\nExample structure: \n\n```\n/module-name\n  /assets\n    /fonts\n    /images\n  /components\n    /responsive-grid\n    /clearfix\n    /animation\n  /local\n    /homepage\n  /lib\n    /mixins\n    /functions\n  bower.json\n  index.scss\n```\n\n### Namespacing\n\n* Every selector, placeholder, mixin and function that is imported should be namespaced\n* Namespaces should be short (2-5 characters) and suffixed with a dash: `rg-Grid`\n\n### Module Entry Point\n\n* Each module should have an `index.scss` file as the entry point: `@import \"module-name/index\"`. \n* The entry point file does not require an underscore in the file name as each module should be able to be compiled and used individually.\n* Importing this entry point file should not render anything in the output\n* There must be an **entry-point mixin named for that module**. eg. a `rg-Grid` module would have a `rg-Grid` mixin\n\n### Package Management\n\n* The preferred package manager for Sass packages at the moment is Bower. \n* Avoid registering packages in Bower whenever possible and instead rely on the Github shorthand syntax - `user/project` eg. `fonzie/responsive-grid`\n* All packages are installed into the `components` directory\n\n### Load Paths\n\n* A load path to the `components` directory is assumed.\n\n### Dependencies\n\nAs every module does not output anything just by being imported, packages can safely import other packages\nwithout the fear that a file has already been imported. Because of this, dependencies can safely require\ntheir own dependencies.\n\nFor example, a `Grid` package depends on a `Clearfix` package, but so does the `LayoutHelpers` package. Both\nof these packages can `@import \"clearfix/index\"` without fear that there will be two `.clearfix` classes in the output.\n\nIt is assumed that the `components` directory is added as a load path, so packages can easily require their dependencies.\n\n\n## Definitions\n\n#### Object\n\nA single piece of the design, usually fairly small. This could be things like `.message`, `.block`, `.list`, `.post`.\nObjects should be independent. Think of them as lego blocks. Objects have \"modifiers\" and \"children\".\n\n#### Children\n\nIf an \"object\" is the parent, any sub-parts of that object are considered its children. Children are only ever\ncontrolled by the object it belongs to. A `.message` object may have a title that it styles, `.message__title`,\nthis would be referred to as a child element. \n\n#### Module\n\nA single piece of functionality that can be composed of CSS, mixins, functions and assets (such as images or fonts).\nA module has a single entry point and a single purpose and role. eg. A grid framework could be a module.\n\n#### Package\n\nWhen a module is shared with others via a package manager like Bower it will generally be referred to as a package.\nThis means that the term \"module\" and \"packages\" are fairly interchangable.\n\n#### Block\n\nThis is another term for the concept of an \"object\".\n\n#### Element\n\nWhen referring to \"objects\" and \"blocks\", the word \"element\" is interchangable with the word \"children\".\n\n#### Modifier\n\n\"Objects\" may be modified in a way that changes their style in small ways, think of them as themes or alternative\nstyles. For example, a `.list` object may have a `.list--small` modifier to make the text smaller.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanthonyshort%2Fidiomatic-sass","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fanthonyshort%2Fidiomatic-sass","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanthonyshort%2Fidiomatic-sass/lists"}