benfrain / ecss

Home for questions and answers relating to the implementation of the ECSS methodology
http://ecss.io
10 stars 0 forks source link

Building a framework with ECSS #9

Closed badlydrawnrob closed 7 years ago

badlydrawnrob commented 7 years ago

Hi Ben!

I've been working with ECSS for a while now, currently building out a framework for Material Design. Here are the goals:

So, as Material Design is a monster document, I'm thinking of sticking to basic components similar to Material Lite — after which, you're on your own! My question is, how to set up this extension without assuming too much? How to keep it extensible yet maintainable?

For example:

Base layout

I'm considering whether to make some elements default, like styling basic html with Material. So an <ul> could look like a list component

Mixins

Going with the button() mixin as an example:

button($font-color = $root.text.color, $flat = false)
  body-button($font-color)  // Typographic styles mixin
  ...

  if $flat
    ...
  else
    ...  

Now, I want to reduce cognitive load as much as possible. Having mixins inside other mixins, editing/extending other mixins gets confusing.

button-floating($font-color = $root.text.color, $mini = false)
  // No typographic styles required
  elevation(1) // Box shadow mixin (Cardinal Material only)

  if $mini
    ...
  else
    ...

I'm trying to keep Cardinal Stylus as minimal as possible. Sometimes it's difficult to reason where mixins should go (which framework), or how they should interact with each other.

The end user

You can see an example of how I'm rendering the components here:

.type-Group
  padding: $spacing.base

.type-GroupHeading
   display-2($margin-bottom: $spacing.base)

.type-GroupHeading
  .type-Group-align &
    margin-bottom: $spacing.double

.btn-flat,
input[type="button"].btn-flat,
input[type="submit"].btn-flat
  button($flat: true)

A final example

A simple example of user extendibility with mixins is, for example, the typography settings. CSS baseline isn't perfect, so there's debate over whether to baseline-shift headings or all elements to the baseline grid:

baseline Here we've nudged headers down so they fit on the baseline grid

Summing up

So as I see it, ECSS is a way to reduce cognitive load, as well as demystifying what goes on behind the scenes. Code should be self documenting as much as possible, so I'd like it to be fairly simple for myself, and other folks to skim through the code base and make sense of what to do, and what's going on.

This is a lot to digest I know, but I think it's important to offload some repetitive tasks to a framework!

Be great to get your thoughts :)

badlydrawnrob commented 7 years ago

FYI any suggestions on cleaning up the code welcomed. I know it isn't as strict in parts as it could be. I think naming conventions are quite open to opinion :)

benfrain commented 7 years ago

Hi Rob, personally, I'm not a great fan of frameworks but I accept that they are often undeniably popular so caveat my opinion with those factors!

I think the choices you make should be largely shaped by who you are targeting this framework at. Is it co-workers in the same organisation? If that's the case can probably be quite prescriptive.

If you want to make something more general, my first question would be — why! There's a bazillion frameworks out there so what makes yours different? If this is the situation you are in, what differentiates your framework from others? Why would I want to use it?

Is it for devs? If that's the case, you could concentrate on 'power' features like only producing the CSS relevant for their project (and the complexity of mixins may be less of an issue).

If it's for designers or non-devs then you should perhaps concentrate on simplicity. In that case overrides for base styles might be a more sensible route to take rather than mixins; which I feel flummox even experienced devs a lot of the time, hence my general avoidance of them.

Ultimately, at this point I don't feel clear what problems you are trying to solve. Subsequently, I'm unsure how best to make use of ECSS here to solve those problems.

Happy to try and help more if you could clarify?

badlydrawnrob commented 7 years ago

Hey @benfrain, so I'll clarify further:

I understand some of what I'm proposing might break ECSS guidelines and totally get your points.

The problem I've had with frameworks in the past is constantly having to refer to the docs to remember what's going on. Especially when I've been away from the project a while.

This framework is predominantly for myself, as a foundation to build on. With the aim of not having to think too hard about how to implement X. It's open source, and one of the projects I'm working for may allow other developers to extend it — but I'd like them to stick to Material guidelines so things look consistent (hence the grid mixins).

I'm looking for a happy balance of site-wide styles, (which as you've mentioned, are unavoidable), with an easier way (through mixins and variables) of declaring things that are "unlikely" to change.

That's my only concern with ECSS, often there are mixins, variables or styles I feel would be safe enough to set up and reuse in component classes; only "resetting" when there is deviation from the site-wide styles. Typography and theme colors are two good examples of these, they follow very set conditions per project (especially in Material).

Also, these following differences I feel warrant building something new:

I do think the site-wide issue is one of the biggest issues I'm trying to solve. I'd like to build something that satisfies 99% of projects, but isn't too prescriptive about how you build with it. So for material; typography, lists, forms — these all feel like elements that won't need much modification — ECSS repetition seems overkill.

Where I'm struggling however, is where this attitude towards reusability should stop. For instance:

elevation($level = 1)
  if $level == 1
    box-shadow: 0 1px 3px alpha(#000, 12%), 0 1px 2px alpha(#000, 24%)
  else if $level == 2
    box-shadow: 0 3px 6px alpha(#000, 16%), 0 3px 6px alpha(#000, 23%)
  else if $level == 3
      box-shadow: 0 10px 20px alpha(#000, 19%), 0 6px 6px alpha(#000, 23%)
  else if $level == 4
      box-shadow: 0 14px 28px alpha(#000, 25%), 0 10px 10px alpha(#000, 22%)
  else if $level == 5
      box-shadow: 0 19px 38px alpha(#000, 30%), 0 15px 12px alpha(#000, 22%)

Now, it would be easy enough to just use css for this, but it's also a handy abstraction. I imagine your thoughts on this would be, "just use css" :)

Maybe it would be better to add a style guide which can be copy and pasted:

// Elevation 1
box-shadow: 0 1px 3px alpha(#000, 12%), 0 1px 2px alpha(#000, 24%)
// Elevation 2
box-shadow: 0 3px 6px alpha(#000, 16%), 0 3px 6px alpha(#000, 23%)
// ...

Or, using a design tool (or one of the upcoming Google tools) to rip the css per component.

So, perhaps it's just my difficulty fully embracing ECSS, perhaps it's a personal choice we need to make. I just want something low hassle, easily maintained and a solid start for all my projects!

All this with the caveat that I know ECSS is supposed to be complete separation of concerns. However, when it comes to switching out to what ever Android UI is the flavour of the month, it's going to take a big chunk of work to switch out any methodology :)

Does that make things any clearer?

benfrain commented 7 years ago

Hi Rob,

OK, I think you need to either embrace isolation (e.g. ECSS, CSS Modules et al.) or embrace abstraction (e.g. ACSS); you're trying to have your cake and eat it!

My opinion is that either approach, followed entirely provides the greatest benefit. Mixing the two does not. When people say things like (emphasis added),

" easier way (through mixins and variables) of declaring things that are "unlikely" to change"

alarm bells start to ring! ;) Things change and always do. If change is as cheap and easy to you as writing something new, then you have a maintainable system. That is the goal. Embracing either approach will solve more of your problems than mixing the two!

From the sounds of your prior post, I think you know this in your heart! I think you should either just build each of your components with ECSS, using only variables to make tweaks to your components for each project e.g.:

$card-primary-color: XXXX
$card-secondary-color: XXXX
$card-padding-standard: XXXX
$card-padding-half: XXXX
$card-shadow-height: XXXX
$card-shadow-color: XXXX

Or get used to doing it all at a template level as in the ACSS approach.

Personally, a bunch of mixins to define possibilities is just over-engineering but ultimately it needs to be whatever reduces cognitive load for you. :)

badlydrawnrob commented 7 years ago

Hi @benfrain ... apologies for the late response, it's been in the back of my mind but haven't had the chance to take a look at it until now!

I think you're right. I've been thinking that it's highly possible to use code snippets, or gists, as a way to get the benefit of mixins (a single, updateable source for components), while sticking to the ECSS style.

I also think I'm going to go about this in a much more agile way, as I'm learning a bunch of stuff in tandem (Python, Rest, Elm), so building only what I need is going to reduce the load.

Thanks for your time and advice :)