{"id":16350457,"url":"https://github.com/zspecza/stylus-conventions","last_synced_at":"2026-02-07T11:02:07.401Z","repository":{"id":14169063,"uuid":"16875108","full_name":"zspecza/stylus-conventions","owner":"zspecza","description":"A collection of Stylus best practices composed by active members of the Stylus community","archived":false,"fork":false,"pushed_at":"2015-07-23T17:08:19.000Z","size":168,"stargazers_count":11,"open_issues_count":2,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-20T03:20:38.740Z","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":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zspecza.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":"2014-02-16T00:30:04.000Z","updated_at":"2023-10-27T04:48:45.000Z","dependencies_parsed_at":"2022-08-28T22:42:12.947Z","dependency_job_id":null,"html_url":"https://github.com/zspecza/stylus-conventions","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/zspecza/stylus-conventions","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zspecza%2Fstylus-conventions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zspecza%2Fstylus-conventions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zspecza%2Fstylus-conventions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zspecza%2Fstylus-conventions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zspecza","download_url":"https://codeload.github.com/zspecza/stylus-conventions/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zspecza%2Fstylus-conventions/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29193089,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-07T07:37:03.739Z","status":"ssl_error","status_checked_at":"2026-02-07T07:37:03.029Z","response_time":63,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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-10-11T01:05:02.105Z","updated_at":"2026-02-07T11:02:07.382Z","avatar_url":"https://github.com/zspecza.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"stylus-conventions\n==================\n\n\u003e **note:** these best practices are outdated. some may still apply, but stylus has evolved a lot over the last few months.\n\u003e unfortunately, I do not have enough time on my hands to research and amend this at the moment, but if you have any questions\n\u003e about ways to do things in stylus, you can always hit me up on twitter (i'll try respond asap), or just open an issue on here.\n\u003e **in the meantime, you can check the issues page (be sure to check both open issues and closed issues) for any discussion/updates** - [@declanjdewet](https://twitter.com/declanjdewet)\n\n## Introduction\n\nThis is a curated set of conventions and best practices for\n[Stylus](http://learnboost.github.io/stylus/), an expressive, dynamic, robust\nand advanced CSS preprocessor. Frustrated with there not being a set of\nconventions set in place (that could be easily found), I set forth to find out\non my own.\n\nThe majority of my findings come from working on [Axis](http://roots.cx/axis/),\na terse, modular and powerful CSS framework by the awesome\n[Jeff Escalante](https://github.com/jenius) of\n[Carrot Creative](http://carrot.is). Some findings come from examining any\nrepeating patterns in existing libraries\n(like [Nib](http://visionmedia.github.io/nib/)).\n\n## Why?\n\nStylus is nice and welcoming. It's syntax is warm and forgiving. This friendly\nneighbourhood preprocessor does not differentiate between pure-CSS or\nindentation-based, bracketless code. It tries to be as transparent as possible,\nespecially when it comes to mixins.\n\n_This is its biggest flaw._\n\nNot that Stylus is an overly-flawed preprocessor, it's actually quite the\nopposite. Out of all of the preprocessors I've tried, Stylus is - in my opinion -\nthe most superior.\n\nIt's problem lies in the fact that because its syntax is so forgiving, and\nthere are so many different ways to write a block of Stylus code; it can be\nconfusing to learn - it supplies the developer with no definitive direction.\nThis, I postulate, is the main reason that it has not received as much attention\nas it should have.\n\nThe confusion doesn't stop at learning, though. Once you're engrained in\nvariables, mixins and functions not requiring a prepended dollar sign ($) or\n'at' symbol (@), you'll soon start to realize that you can no longer tell the\ndifference between them. This makes for very confusing code - and this is only\none example of Stylus' quirks.\n\nThis is why conventions and best practices need to be put in place _(and I'm\nrather surprised it's taken this long!)_.\n\n## Letter Casing\n\nIf you're wondering how to structure tidbits of your Stylus code, and one of the\nquestions you have is \"Camel Case, Underscores or Hyphenated?\", then you need to\nexamine HTML and CSS very closely.\n\nWhich of the following do you see more often in CSS?\n\n    a) linearGradient\n    b) linear_gradient\n    c) linear-gradient\n\nIf you chose 'C', then there's your answer. Try keep things hyphenated.\nIt _just makes sense_.\n\n## Which syntax?\n\nStylus supports near to anything you throw at it. You have the freedom of choice\nhere.\n\nIf you prefer looking at neat code, this syntax is for you:\n```stylus\n.selector\n  border-radius: 15px\n  border: 1px solid blue\n```\nIf you're fond of your curly braces, then you can have them (and keep them,\nthanks):\n```stylus\n.selector {\n  border-radius: 15px;\n  border: 1px solid blue\n}\n```\n\nStylus supports punctuated code as well as code that has an inherent lack of\npunctuation. It even allows you to remove colons. But you should not do this, as\nit makes for very unreadable code in large projects. It may be quick to type,\nbut it is _not_ quick to scan or read.\n\n```stylus\n.selector\n  border-radius 15px // hard to read.\n```\n\n## Variable Naming\n\nThis convention splits off into two categories, and there are approximately the\nsame amount of users for both conventions.\n\nStylus doesn't force you to declare variables with anything prepended to them -\nyou simply define a variable like so:\n\n```stylus\nmy-variable = 'hey look, a variable!'\n```\n\nSome developers like this, others don't. Some like to declare them with a dollar\nsign:\n\n```stylus\n$my-variable = \"I've got bling\"\n```\n\nI've seen a few developers argue that adding in that extra dollar sign adds\n\"way too much bloat\". Well, in Stylus - there are actually _benefits_ to using\nthe dollar sign.\n\nThe first benefit; your variables are now easier to spot. You know what to look\nfor in order to quickly find them in your code.\n\nThe second benefit, and most important - is that you will never run into\nTransparent Mixin Keyword Argument Conflicts (patent pending).\n\nIf you're wondering what I mean by that gargantuan term, let me demonstrate.\nSuppose you wanted to port\n[Compass' Vertical Rhythm module](http://compass-style.org/reference/compass/typography/vertical_rhythm/)\nto Stylus, and you reached the point of bringing in the shorthand **rhythm()**\nmixin. This is what you'd end up with:\n\n```stylus\nrhythm(leader = 0, padding-leader = 0, padding-trailer = 0, trailer = 0, font-size = base-font-size)\n  leader: leader, font-size\n  padding-leader: padding-leader, font-size\n  padding-trailer: padding-trailer, font-size\n  trailer: trailer, font-size\n```\n\nThis is invalid Stylus. It does not throw an error, though. It fails silently.\nEverything compiles except this mixin. If there were any best way to confuse a\ncompiler, this would be the way to do it. What's happening here is that the\nrhythm mixin has it's own local variable scope, and within that scope, leader,\ntrailer and friends are not mixins. They are keyword arguments.\n\nBy prepending the dollar sign, your mixins stay safe - **$leader** is not the\nsame as **leader**.\n```stylus\nrhythm($leader = 0, $padding-leader = 0, $padding-trailer = 0, $trailer = 0, $font-size = $base-font-size)\n  leader: $leader, $font-size\n  padding-leader: $padding-leader, $font-size\n  padding-trailer: $padding-trailer, $font-size\n  trailer: $trailer, $font-size\n```\nThe code may be relatively long, but it's readable, and that is a good thing.\n\nFor those developers who want to do away with the dollar sign, though - an\naccepted convention is to sacrifice a little readability by aliasing the keyword\narguments to a short acronym:\n```stylus\nrhythm(l = 0, pl= 0, pt = 0, t = 0, font-size = base-font-size)\n  leader: l, font-size\n  padding-leader: pl, font-size\n  padding-trailer: pt, font-size\n  trailer: t, font-size\n```\n\n## Mixin Naming\n\nNaming mixins in Stylus is fairly straightforward, but eventually you might run\ninto a problem that Jeff and I encountered in Axis. There's no snappy name for\nit (yet), but there is a rule to follow. The problem we encountered was with a\nmixin that Jeff created for rapid creation of navigation bars in Axis:\n```stylus\nnav()\n  // pretend there's some code here\n```\nCan you spot the problem yet? No? C'mon - it's easy to see what's wrong here.\nIt's just a mixin definition with nothing underneath it!\n\nStill can't guess? Well - here's the thing; **nav** is an element that is\nalready present in HTML5.\n\nSo, what does that mean for us? I'll tell you. Suppose, later on down the line,\nyou want to style a **ul** inside a separate **nav** element...\n```stylus\nnav ul\n  list-style-type: none\n```\n\n...And then things start to break. You get a confusing error message that makes\nno sense, and you don't know what to do. It took me three hours to learn what\nwas actually going on. Stylus interpreted the **nav** selector as a mixin, and\npassed **ul** as a parameter. That's some pretty weird behaviour. So, quick tip:\n\n**_Never name your mixins after HTML elements!_**\n\n## Mixin Introspection\n\nStylus has two different levels of introspection, meaning that mixins and\nfunctions can be called at either the _root_ or _block_ level, and are capable\nof being aware of what level they were called at.\n\nBlock level mixins are called inside the body of a CSS selector. Root level\nmixins are called outside of that scope.\n\n```stylus\nroot-mixin() // a root level mixin\nbody\n  block-mixin() // a block level mixin\n```\n\nRoot-level mixins **and** block-level mixins without arguments should _always_\nbe called with parentheses. Block-level mixins **with arguments** should be\ncalled transparently, as if they were a CSS property:\n\n```stylus\nfoo() // root level w/ parens\nbody\n  bar() // no arguments, must have parens\n  baz: 1px, 3px, 5px // has args, no parens\n```\nFolowing this particular convention will not only make your code more readable\nand maintainable, but it will also prevent a few rare compilation errors.\n\n## Function Naming\n\nWe've discussed most of the apparent conventions in Stylus - but what about\nfunctions? They're still kinda hard to differentiate from mixins...\n\nWell, have a good look at Nib and a few other Stylus libraries. Notice anything?\n\nI bet you did - it seems like most functions are prepended with a hyphen. Now,\nit's easy to tell mixins and functions apart!\n\n```stylus\n-random-number()\n  return 4px // guaranteed to be random. Now look away ;)\nbody\n  font-size: -random-number()\n```\n\n## Conditional Assignment\n\nStylus supports two forms of conditional assignment. One of them is the\nrecommended way to establish a global settings file.\n\nI'll let you guess which one looks better in a conditional statement and which\none looks more... settings-appropriate.\n\n```stylus\n$my-variable1 ?= red\n$my-variable2 := blue\n```\n\nIf you guessed that the second one is better for settings files, then you were\nright.\n\n## Placeholder Selectors\n\nStylus didn't always use to have placeholder selectors, and there were some\nconventions regarding this. But now, it _does_ have placeholder selectors. They\nare prepended with a dollar sign.\n\n```stylus\n$placeholder\n  background: red\n.red-thing\n  @extends $placeholder\n```\n\n## Optional Child Selector\n\nSometimes, when you're working with dynamic content - you might have a selector,\ninside a selector, inside another selector. Let's assume they have a class of\n**.a, .b and .c**, respectively.\n\nYou want to select **.c**, but **.b** is not always present on the page. Using\nthe Stylus **parent selector (\u0026)**, you can still adjust your stylesheet to be\naware of that:\n\n```stylus\n.a\n  \u003e .b, \u0026\n    \u003e .c\n      color: red\n```\nNow, even if **.b** is not present, **.c** will still get styled appropriately.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzspecza%2Fstylus-conventions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzspecza%2Fstylus-conventions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzspecza%2Fstylus-conventions/lists"}