suitcss / suit

Style tools for UI components
http://suitcss.github.io/
3.81k stars 229 forks source link

Document the variable naming convention. #91

Closed philipwalton closed 6 years ago

philipwalton commented 10 years ago

I didn't see any docs on the variable naming convention, but you've implicitly outlined some type of convention in your examples:

:root {
  --Excerpt-padding: 20px;
  --Excerpt-highlight-color: orange;
}

As far as I can tell, the only real "rule" is that component variables should be prefixed with the full component name. However, I think the example above can be confusing given the other conventions. For example, --Excerpt-padding is clearly a variable scoped to the .Excerpt component, but is --Excerpt-highlight-color the highlight color for .Excerpt or is it the color for the sub-element .Excerpt-highlight? Granted, in this case it's pretty clear from the semantics, but there may be other cases where it's not nearly as obvious. Perhaps it should be camelCase after the component namespace, e.g. --Excerpt-hightlightColor.

I haven't spent much time thinking about this, so consider these just a few ideas/questions off the top of my head:

  1. Should all variables be scoped to the module, or does it makes sense to have some variables (that will only be applied to children) named as such. E.g. Tweet-bgColor vs. --Tweet-btn-bgColor
  2. Is there a differentiator for global variables vs module-specific variables? Perhaps a leading capital letter. E.g. --Tweet-textColor vs --textColor
  3. Since CSS variables are really just custom properties and in the future will follow the cascade, namespacing them will eventually be counter to their utility. If the goal of SUIT is to be forward thinking, have you thought about a conversion plan for when something like this is possible?
/* In variables.css */
:root {
  --space: 1em;
}

/* In tweet.css */
.Tweet {
  --space: calc(var(--space) * 2);
}
.Tweet-btn {
  margin-bottom: var(--space); /* 2em in this context. */
}
necolas commented 10 years ago

Should all variables be scoped to the module…

The custom properties are "global", and the components shouldn't expose the internal structure, so having a flat structure after the namespace seems like a suitable choice: --ComponentName-someVariableName. The non-component variables would be --someVariableName

…have you thought about a conversion plan…

Not possible to do outside of the browser. See https://github.com/reworkcss/rework-vars/issues/30. I don't think there's anything wrong with namespacing them now – it provides a clear link that would make it easy to migrate to native custom properties at the component level.

philipwalton commented 10 years ago

Yeah, I know it's not actually possible to do this outside of the browser, but I see this as similar to how calc is supported despite not being full-featured.

Given the conventions of SUIT, someone could write the following CSS in their module and a rework plugin could handle it:

.ComponentName {
  --space: calc(var(--space)*2);
}

.ComponentName-subElementName { 
  color: var(--space);
}

The plugin would apply the following logic:

.ComponentName {
  --space: calc(var(--space)*2);
}

/**
 * Rework sees that a custom property is being set on a component and
 * translates that into this:
 */
:root {
  --ComponentName-space: calc(var(--space)*2);
}

/**
 * Because this selector starts with `.ComponentName` and `.ComponentName`
 * defined the property `--space`, Rework would know to use the property
 * `--ComponentName-space` instead of `--space`.
 */
.ComponentName-subElementName { 
  color: var(--space);
}

Anyway, I'm not necessarily suggesting this idea, I was just wondering if you or anyone had been thinking about how to handle this moving forward.

Also, the value isn't just to save a few characters and not have to prefix things, the value is that browser that do support custom properties could potentially get them (with obvious caveats) before having to wait until full support exists.

Given what I've described above, the Rework plugin could output something like this:

/* Output fallback, translating `var(--Component-space)` to a value. */
.ComponentName-subElementName { 
  color: var(--Component-space);
}

@supports (/* some custom property check */) {
  .ComponentName-subElementName { 
    /* Literally output this, without translating to a value. */
    color: var(--space);
  } 
}
necolas commented 10 years ago

Yeah it could work in some form when you have a convention like SUIT, and you bake that into the assumptions. But the native implementation would expose --space to any element in the sub-tree, including other components. So you'd be depending on behaviour in the preprocessing that doesn't exist in the native implementation, which is risky because it's not longer forward-compatible.

necolas commented 10 years ago

What I find myself wanting quite often is local variables that aren't exposed outside the file.

giuseppeg commented 8 years ago

I am a bit late to the party but I am using suit in a project and all of a sudden some of these issue are relevant to me.

so having a flat structure after the namespace seems like a suitable choice: --ComponentName-someVariableName. The non-component variables would be --someVariableName

Agreed, I use the following convention:

--ComponentName[-descendant|--modifier][-onState]-(cssProperty|variableName)

Examples

--ComponentName-backgroundColor
--ComponentName-descendant-backgroundColor
--ComponentName--modifier-backgroundColor
--ComponentName-onHover-backgroundColor
--ComponentName-descendant-onHover-backgroundColor
...

@philipwalton thoughts? If you like it I will try to implement this convention in postcss-bem-linter.

simonsmith commented 8 years ago

Looks good to me. Be a good one to add to the docs and finally close this issue

kristoforsalmin commented 6 years ago

Hi guys, since this has been already merged, shall we close the issue?

simonsmith commented 6 years ago

@racse1 Good spot!

cyonder commented 1 year ago

How would you guys approach to naming variables if it involves numbers? In SUIT I guess I shouldn't be separating numbers with a dash but it reads better with a dash.

  --colorNeutral-0: #FFFFFF;
  --colorNeutral-50: #......;
  --colorNeutral-100: #......;
  --colorNeutral-200: #......;
  ...
  --colorNeutral-900: #......;
  --spacing-0: 4px;
  --spacing-1: 8px;
  --spacing-2: 16px;
  --spacing-3: 24px;
  ...
  --spacing-9: 72px;