nodebugme / site

the nodebug.me site.
27 stars 3 forks source link

Move to OOCSS methodology #16

Open twolfson opened 9 years ago

twolfson commented 9 years ago

As mentioned in #8, moving OOCSS would make CSS more flexible and cause less issues in the future.

Background

A brief explanation of OOCSS is it defines groups of CSS selectors/rules based on visual patterns. A classic example is the media object, an image element on the left with content on the right:

Media object example

We can define a set of CSS rules to fit this. If we go the content semantic route, we would get something like:

.status-image {
  float: left;
}
.status-content {
  /* Nothing goes here */
}

Then, we continue working on our project and see a similar pattern but can't reuse it because the selector is content semantic:

Nested media objects

.status-image,
.reply-image {
  float: left;
}
.status-content,
.reply-content {
  /* Nothing goes here */
}

When we encounter the same visual pattern, it needs to add to the selectors. What if a selector has a lot of overrides? This turns into unnecessary maintenance and code bloat.

Instead, we can make the classes visually semantic:

<div class="media attribution">

  <a href="http://twitter.com/stubbornella" class="img">
    <img src="http://stubbornella.com/profile_image.jpg" alt="me" />
  </a>

  <div class="bd">
    @Stubbornella 14 minutes ago
  </div>

</div>
.media {margin:10px;}
.media, .bd {overflow:hidden; _overflow:visible; zoom:1;}
.media .img {float:left; margin-right: 10px;}
.media .img img{display:block;}
.media .imgExt{float:right; margin-left: 10px;}

This affords us a few things:

All images and some code referenced here came from:

http://www.stubbornella.org/content/2010/06/25/the-media-object-saves-hundreds-of-lines-of-code/

Suggestions for nodebugme

https://github.com/nodebugme/site/blob/771d3832a5cc0b2f0f42754c02cfa3cd83fb0e9a/public/style.css

Rename .login-btn to .btn--primary or similar. This would allow similarly styled buttons to use the same class.

Optionally remove margin from .btn--primary as it might cause issues in other locations. Ideally, this would be scoped to what the page needs (e.g. leave a .login-btn class which only does the margin).

This is taken from another OOCSS concept which is to separate chrome from layout (e.g. color and margin).

Remove width from input[type=text], that will definitely have issues in the future. Replace it with width helper classes (e.g. one-whole (100%), one-third (33.333%)).

Relocate all HTML selectors to the top of the CSS file. Since CSS is cascading the heavier overrides should be located towards the bottom of the file to make it easier for programmers to keep track of.

Relocate overrides for ul and ul > li into another visual pattern. At some point, there might be a need for bulleted lists and having a selector that destroys the default behavior will likely cause more maintenance than was necessary (e.g. need to create new rule to style these lists or revert the rule).

Don't use 2 classes to select modified buttons (e.g. button.danger). The cascade is already performing the override and using 2 classes will make it harder to override later on in the cascade. Instead, consider adopting a naming convention like BEM which indicates a modifier but doesn't require more classes:

.button {
  /* Normal button styles */
}

.button--danger {
  color: #e84f42;
}
chrisdickinson commented 9 years ago

Thanks for writing this up, this is great. Does OOCSS have any particular prescriptions for responsive design? That's probably the next big hurdle the site will face -- being able to triage issues from a phone would be rad.

Other than that question, I'm +1 on moving to an OOCSS style provided it comes with some (light) documentation on "how to modify nodebug.me's CSS".

twolfson commented 9 years ago

Cool, I am not sure how soon I can work on this so feel free to give it a shot. OOCSS doesn't talk about responsive design that much. The most obvious corollary that people adopt is to make components handle their own adjustments.

For a grid, these can be done via selectors which scope to a screen size:

https://github.com/csswizardry/inuit.css/blob/v5.0.1/generic/_widths.scss

.desk-one-half /* size to one-half on desktop screens */
.palm-one-whole /* size to one-whole on mobile screens */