anthonyshort / idiomatic-sass

Principles for writing consistent, clean, friendly Sass
228 stars 14 forks source link

Namespacing, placeholders, and global variables #3

Open robwierzbowski opened 11 years ago

robwierzbowski commented 11 years ago

I really like what you have here. A couple things jump to mind:

Namespacing all mixins and functions can decrease readability and usability for an author. To borrow an argument from the Singularity queue, you're unlikely to be using two Sass grid systems at once, and grid-span() is quite a bit more usable than sing-grid-span(). OTOH there are elements that obviously need to be namespaced, like $padding. I don't know exactly where the best point between consistency and usability falls, but probably somewhere in the middle. Looking back at that Singularity issue, my current opinion is somewhere between my first comment and Scott's.

There was some work being done to take care of name collisions at the Sass level too: https://github.com/nex3/sass/issues/353.

Placeholders defined in the global space can't be extended from inside of @media directives, so I generally don't think they're a good way to expose rules from an extension to an author. I usually suggest all extensions provide mixins to the author, who then makes the decision to use the mixin in a placeholder or not.

I think there's a distinction between using variables in function and mixin calculations and settings variables. The former should always be scoped, the latter should always (and can only) be global. Defining set of standardized global settings variables for sass extension authors to reference would be a good addition to Idiomatic Sass.

Sorry for the briefness, wanted to get these ideas out before heading back to work.

anthonyshort commented 11 years ago

Good points! I really wanted some input on the module section.

Regarding namespacing, because everything is global I think it makes more sense to either namespace everything or nothing. This is mainly for consistency. While it may work for things like grid systems, other libraries may have more generic mixins. Imagine if the grid framework used a clearfix mixin and a util library also provided a clearfix mixin. There would be a clash and possibly breakages.

If people are reading your Sass and see a namespaced mixin, sg-Grid, they will know where it comes from. If everything wasn't global and we had a native module system, you'd be able to see at the top of the file which mixins are being imported and used, just like in Node.

It becomes confusing when some things are namespaced but not all. So variables will be but a mixin won't be. Even though a mixin may look uglier with a namespace, the clarity and consistency are all worth it. I totally agree about providing mixins where possible because of the extending issue.

anthonyshort commented 11 years ago

Here's a module that I'm working on that follows a lot of these https://github.com/fonzie/responsive-grid

I suppose the most important part is that there is consistency across the community. Regardless of how we tackle the module issue.

robwierzbowski commented 11 years ago

Community consistency is key, and I like the idea that the prefix reminds the author where the mixin is coming from.

I have to write out my thoughts more completely at some point, but I feel that a pragmatic and usable balance is going to be somewhere in the middle. For instance I think universal foundational mixins shouldn't be defined multiple places, and should live naked in the global namespace. Clearfix() springs to mind; it's often overwritten by extensions but I'd rather see those extensions assume that an un-namespaced clearfix exists (or tests if it does) than define their preferred clearfix... Damn, this is a good reason to get my blog running.

anthonyshort commented 11 years ago

You wouldn't need to test if something exists if the module @import gets added. That would be a great feature.

@import "grid" as grid;

.selector {
   @extend grid::%unit;
   @include grid::columns(1);
}

One day...

robwierzbowski commented 11 years ago

I was thinking more that an extension would need to test if a likely defined mixin exists before relying on it, e.g.,

// in extension 'gridsystem'
@mixin grid-container($a, $b) {
  // ...bunch of rules...
  @if exists('clearfix', mixin) {
    // Allow the user to define their own clearfix. 
    // Don't assume you as the extension author know best.
    @include clearfix();
  }
  @else {
    // Make sure that the extension functions if there is no clearfix defined.
    @include gs-clearfix();
  }
}

A sort of !default for mixins. Documenting soft dependencies would work here too.