Skip to content

Instantly share code, notes, and snippets.

@mrmrs
Last active August 29, 2015 13:57
Show Gist options
  • Save mrmrs/03ea4c0907b17c7e5a13 to your computer and use it in GitHub Desktop.
Save mrmrs/03ea4c0907b17c7e5a13 to your computer and use it in GitHub Desktop.

CSS ramblings

Context

"If you are going to do something you should do it to the best of your ability." - Ken Morse

My Dad

These are words that my dad imparted on me over and over again. I'm quite sure he did not make them up. And to be honest the words weren't that powerful. But that's how my dad lived his life and after years of observing it in practice I am quite sure it has informed my approach to designing things.

I am a designer who is simply trying to design the best possible products. If it has anything to do with the overall product, I care about it deeply.

Some facts

Re: http://www.kapowaz.net/articles/cargo-cult-css

A few things that should be made clear that were presented incorrectly.

  • OOCSS is an architecture pattern.
  • BEM is a naming convention.

They are not mutually exclusive or inclusive to each other at all.

OOCSS methodology origins

I cannot speak for everyone who promotes OOCSS but I can say this. I don't care about expounding methodologies. I don't care about fitting things into how I want them to work. What I'm trying to do is build the best product, the fastest, with the least amount of effort. These are some of the lessons I've learned along the way working by myself, with small teams, and now with 100 other designers in one department :)

On using IDs

Don't do it. Professional web developers who do understand how specificity works should never have to use them to style something. Many people who touch html and css are not expert front-end developers. Let's not make their lives unneccessarily harder.

Semantics

"Since class names in this type of project must describe their presentation, they are inherently non-semantic"

This quote seems to indicate a misunderstanding of what the word semantic means.

Semantics are

'the study of the relationships between signs and symbols and what they represent'

To say something IS semantic in a dictionary sense is to say

'Of or relating to meaning'

Let's look at one of the css / markup examples provided.

@mixin news-item($color) {
   border: 2px solid $color;
   border-radius: 5px;
   padding: 20px;
   font-family: Helvetica, Arial, sans-serif;
   font-weight: normal;
   font-size: 1rem;
   line-height: 1.4;
}

div.news {
  @include news-item(blue);
}

div.breaking {
  @include news-item(red);
  font-weight: bold;
}
<div class="news">
  Here is a news item.
</div>

<div class="breaking">
  Here is a breaking news item!
</div>

This example to me involves several unneccessary and detrimental abstractions to providing any type of real meaning that will allow me to design or develop an interface faster. There are now two classes that represent mostly the same visual style (with some custom overrides). I now have no visibility that they are related when looking through the markup. This would be my workflow to discover that these classes are related / coupled together in anyway:

  1. Look up definition of class in css.
  2. See that it includes a mixin or @extend
  3. Look up definition of mixin / @extend
  4. Grep for all instances where that mixin / @extend is included and look for other classes it is included in

If a class is comprised of more than one mixin or extend, then the process continues...

  1. Look up definition of second mixin / @extend
  2. Grep for all instances of mixin and diff it against the first list to output one discreet list

This is a lot of steps. And the subsequent information is very difficult to memorize and leverage later on during development. It gets even more difficult when jumping from project to project. Across projects you will most-likely have more similarity in visual patterns than in content patterns. So why base your visual style naming schemes around the content that it's styling?

Class names that describe semantic content are more than likely redundant in the information they are conveying. This in turn, dilutes the intended semantics.

<span class="item-price">{{ item.price }}</span>

The most important part of the semantics is the actual element used to mark up the content. After that, naming a class "news" doesn't help me or anyone else. This couples together content to visual styles and that is actually what we are trying to seperate. A piece of news might be styled many different ways. In a list view, in a single post or article, or maybe it's in a summary view on the homepage. It's all 'news' content. So now I need to create additional hooks or ovverides to style them independently. This generally results in poorly chosen class names because there isn't something 'unique' that describes the semantics of the content. Or new parent classes used as hooks to override styles.

In turn, increasing the number of overrides in your css, makes it more difficult for browsers (yes even modern faster ones) to render your page. And your code requires more and more cognitive strain for humans reading it. This seems like a lose lose situation.

When I think of designing I think of using scales. In the example above of the .box-standard class, we've included border styles, padding, typography, and color into one class. This seems very difficult to remember if you're familiar with the system and even more difficult to learn if you are new to the system. You definitively have to read css to understand what visual styles will be applied to an element. CSS must be read at times to understand things. You cannot understand code without reading it. But we can reduce the amount of times you need to read it and make it easier to grock.

Why declare a font-size to be 1rem? You should never have to override a class to set the font-size to what is presumably intended to render as 16px. We could most likely get away with only having a few classes (and no overrides!) that are actually pretty easy to read and understand. Depending on other parts of your design scales and patterns I would probably name these classes a bit differently.

<!-- news -->
<div class="border border--red pam sans-serif">
</div>
<!-- breaking -->
<div class="border border--blue pam sans-serif bold">
</div>

The corresponding css could look like this:

 .sans-serif { font-family: Helvetica, Arial, sans-serif; }
 .bold { font-weight: bold; }
 
 .pam { padding: 20px; } /* would be apart of a larger spacing scale */
 
 .border { 
     border-width: 2px; 
     border-style: solid; 
     border-radius: 5px; 
  }
 .border--red { border-color: red; }
 .border--blue { border-color: blue; }

This gives me a sequence of symbols that mean something to me without needing to investigate any more. If I was confused about what a class did - there is a one to one relationship between a class and its definition. This is not the case when you combine mixins and @extends. In a small example like this often times oocss and single purpose class architecture don't shine. Their strength is really in creating a large maintainable system. But even in this example - I find more meaningful 'semantic' information in the class names than in the example of 'news' and 'breaking'. When I style things, the type of content never matters. The type of styles do though.

Lastly on performance and velocity

Performance is a browser level issue, it is not something for HTML/CSS authors to fix or work around. As long as we are authoring valid and sensible HTML and CSS, we should not need to resort to such ridiculous rules simply to enhance the speed at which a given page renders. - Matt Wilcox

This seems like a fair point that I can't argue against as I guess I'm not an HTML/CSS author. I'm a designer. And to my earlier point - I am attempting to design the best products for my users. That means I am not going to sit around and wait for browsers to get faster when I know how to deliver a faster product, to my users, TODAY. Not tomorrow. Not later. Right fucking now. And who knows if my users are even using new browsers? I certainly don't. It's a big open web and I want everyone to be able to get to the content they want, as fast as possible.

CSS performance falls into two categories. First being how long it takes to download the css file(s). So file size matters a bit. But the more important part is render time. Because no amount of caching a file will ever speed up how long it takes the browser to parse your css. The more "overrides" you have and the more unqualified elements you use in selectors, the longer each page will take to paint out to the screen. Using telemetry to test paint speed I have commonly found css to be easily optimized to the tune of .5 to 2.5 seconds a page. That is a lot of time to save. The fastest thing I have found is small classes that don't override eachother. You create a shallow but wide cascade. You spend way less time debugging CSS. AND THAT IS IMPORTANT as it has a huge impact on dev velocity. Time you aren't spending debugging can be used for better things like designing stuff. Or laying on the floor with cats. Or looking at cat gifs. Or thinking about cats. But let's certainly spend less time wrangling css.

Finally, the argument that oocss slows down dev velocity is not backed by any data that I have seen. I have found it to be the opposite actually. But that is a different story for a different time.

Hope this rant helps. Feel free to hit me with questions.

Amazing articles by amazing people:

http://nicolasgallagher.com/about-html-semantics-front-end-architecture/ http://www.stubbornella.org/content/2011/04/28/our-best-practices-are-killing-us/ http://csswizardry.com/2012/10/a-classless-class-on-using-more-classes-in-your-html/

@jxnblk
Copy link

jxnblk commented Mar 27, 2014

Few quick notes for @mrmrs:

  • Mispelling: "seperate"
  • "When I style things, content never matters. The styles do though." - I sort of get what you're trying to say, but this just sounds bad.
  • I think the Semantics section needs some subheads/bullets/etc. to help break up the content. It's easy to glaze over that section and get lost.

@mrmrs
Copy link
Author

mrmrs commented Mar 28, 2014

@jxnblk - agree about the content / styles comment. Reworded that like 80 times yesterday.

@mrmrs
Copy link
Author

mrmrs commented Mar 28, 2014

@cbracco

Probably a Mainer thing. There are only a million of us after all :)

Inline Styles vs Multi-class approach

To me these are the main differences between inline-styles and a multi-class approach:

Inline styles are actually very very slow to render to the page. The reason for this is that each style is a one to one mapping to a node. Instead of a one to many mapping that a class provides. This affects browser memory and paint time.

Multi-class patterns aren’t exclusively single class patterns. To me having a base border class of

.border { border-width: 1px; border-style: solid; }

Then extending that with various border colors classes is infinitely more readable than having to read through that whole set of declarations in inline styles every single time. Once media queries are introduced this obviously gets real crazy real fast.

One of the old ‘knocks’ on inline styles was that you had to update multiple things in multiple places. This is not a real problem if you know how to edit text efficiently. Changing one text pattern to another across an entire project, or an arbitrary section of a project, should be a trivial task. But no inline styles are extremely verbose compared to classes which you can make readable. As someone who develops code, it’s your job to edit text. Tough to avoid in my opinion.

Code example

If you want to have a border for certain viewports but not others, this to me is a perfect example of multi class patterns strength in responsive design. I’d have something like

<div class=“border border-none-l”>
</div>
.border { border: 1px solid red; }
@media screen and (min-device-width: 100em) {
   .border-none-l { border: 0; }
}

What’s great about this is ANYTIME you need to override a border at a larger viewport you have a utility to do it.
I think there is a time and place for classes that are larger objects, especially for layout type utilities like
http://jxnblk.github.io/tempo/

I think naming is something that is contextual. There are times where I want more verbose names like sans-serif, other times I find things like fl for float: left are easy to read and pretty easy to grock for beginners and vets in my experience.

t might seem like a petty scenario, but they can add up and make code confusing if not implemented in a thoughtful manner or planned beforehand.

Why would you design anything without a system and scale in place? If you aren’t doing that, yes it can get messy, but that isn’t a css problem. That is a design process problem. Systems and scales SHOULD be thought about ahead of time. They can change - but you should definitely lay one down before you start building something.

Onboarding

Also, with OOCSS you are creating a system of CSS classes, which does effect onboarding time.

What system of code does not take time to become familiar with? Do you have a css system where no one needs to familiarize themselves with it before they start developing? I am guessing whatever time is spent not familiarizing themselves with a system is then wasted in creating duplicate objects that most likely already exist?

I have build large systems with monolithic classes before. It did not make it easier to on board people. You still had thousands of lines of css that people were unfamiliar with. In this case I’ve had enormous success on boarding people. Much faster than any other patterns I’ve worked within.

Take this file for example:
https://raw.githubusercontent.com/mrmrs/css-uncut/master/sass/_spacing.scss

You don’t even need to know css to grock that naming system. It’s well documented, consistent, and means you never have to write out margins or padding into a class ever again. Now you might need a different scale than what is provided here but that isn’t the point. The point is that this isn’t a FILE you memorize. It’s a series of compostable patterns. And that to me is so beautiful.

Doing the majority of your work in the html and not bouncing back and forth to css will speed up dev and design velocity like you wouldn’t believe.

The media object

To be honest it’s 2014 and the media object is a really well established markup pattern. It’s kind of like the $ in jquery at this point :) But to your real point - you imply that you can’t know what that class does by reading the name. I agree, it’s a layout pattern that would be tough to describe in a string like fashion. I think those cases are best covered by good documentation in the form of a style guide. It doesn’t matter what language you are creating a system in, documentation is necessary for people to understand how to reuse code - and it takes time to learn how things work no matter how smart you are. But in this system it doesn’t take much time at all and there in lies the beauty of the whole thing. I have found that I’ve been able to get both back end developers and new designers who are unfamiliar with code - to be able to make more changes easily, with less training.

But I only have anecdotal evidence to support that claim :)

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

@cbracco
Copy link

cbracco commented Mar 28, 2014

Haha, I didn't realize you were from Maine. Nice.

Again, thanks for taking the time to explain your philosophy on the matter, it has most certainly been helpful to me. If you blog, there is plenty of good information here that could be organized into a post. If you ever do that, I'd love to read it.

Cheers!

✌️

@davidpots
Copy link

@mrmrs – thanks so much for writing this (found it a few days ago via @jxnblk), a huge help and wake up call for me personally (I feel like my understanding of CSS hadn't developed past a few years ago, text editing cleverness aside). This past week has been huge though thanks to this and articles like it.

@davidpots
Copy link

@mrmrs – question, which you may have in/directly answered (if so, I missed it / apologies). Thinking about the devil's advocate argument against this approach... how do you respond to the argument that this multi-class approach is bad for load time, since the HTML might have multiple classes being repeated several dozen times per a single page. This is in contrast the alternative approach (which uses far less classes in the HTML, and lets the CSS do a bit more heavy-lifting)... which could likewise be kept more DRY via using @extend.

Now, your argument against use of (nested) @extend I 100% agree with and could argue for easily (that of it being horribly non-trivial to intuit what styles a certain element is ultimately getting, etc). But for the "page load" argument I could see critics slinging, any thoughts / resources you recommend checking out?

@mrmrs
Copy link
Author

mrmrs commented Jun 25, 2014

@davidpots - Thanks for the kind words on my ramblings :)

This multi-class approach is generally very good at improving page load time in my experience. I talk a little bit about that in the last section:
https://gist.github.com/mrmrs/03ea4c0907b17c7e5a13#lastly-on-performance-and-velocity

When you have a lot of single purpose classes that you combine in markup to build new components / interfaces - your css doesn’t grow much (if at all). You can build a pretty complex website with less than 12kb of css (minified and gripped). This is in stark contrast to the 500kb+ css footprint I commonly see on major websites (salesforce and kickstarter being two culprits). Having multiple classes on your elements - will generally only add ~3-5kb of bloat. But file size is only one part of the battle. This multi-class pattern as far as I’ve seen helps reduce scroll jank and decrease paint-times.

Cheers.

@davidpots
Copy link

@mrmrs thanks – and since my initial asking, I also finally read this baby which answered my question (about HTML file size, etc) directly. http://nicolasgallagher.com/about-html-semantics-front-end-architecture/

Another question for you – where do you draw the line for when / when not to create a new UI pattern CSS class? For instance – you could technically create a button via manually piling up the classes (block, padding, round corners, etc). Obviously it'd be nasty, but doable. But instead you created a class called "button". This is a bit of a skewed example, of course, but it technically illustrates the point I'm getting at. You could make a human with classes protein carbon blood bones – but when do you say "screw it, I'm just making human which will include all those for me.

Taking the question / previous paragraph a step further: one benefit of creating a dedicated class for a commonly used UI pattern would be, it seems to me, that it'd be much easier for finding-all-instances-of-that-item-later-on. Using the button example, I could grep my project and see everywhere that the btn class is used, and if I did a button-redesign and wanted to make sure it looked good in all instances, this'd help. But if my buttons were instead created via manual frankensteining of class names, it'd be quite a bit harder for me to track them all down (I'm talking about a medium/large size app here).

Thanks again.

@mrmrs
Copy link
Author

mrmrs commented Jul 8, 2014

@davidpots - sorry for the delayed response.

So I think the human example is flawed as even though that is what humans are made of…
how do I get a human with red hair? How do I get a human with blue eyes? How do I get a human with long legs and a short torso? How do I get a human with green eyes and black hair?

Now would you want to code every possible combination as a monolithic human? Or have a bunch of utilities you can mix and match easily to build ANY COMBINATION OF HUMAN YOU COULD EVER need. That seems pretty boss to me. So to me you just try not to combine things that won’t ALWAYS be coupled. But this is also a larger question with a lot of variables that would help inform the decision. In my experience though - making small or large changes with small lego blocks is an order of magnitude easier than making even small changes to very large lego blocks i.e monolithic components. I do not think it is a feature to be able to mix concerns and couple things together.

I tweeted about this a little while ago but I always think of this stuff like legos. When I was a kid I thought about legos in a very particular way. Which was that I didn’t ever map a lego piece to “content semantics”. A unit 4 blue lego block wasn’t a part of an engine block on a boat. It was a blue lego that had four circles at the top. Sometimes I liked using it with other blue legos. Sometimes I liked using it next to a gray logo to create a stripe on the side of a walkway. WHO KNOWS?! The possibilities seemed unbounded.

I also never glued two lego blocks together. Never. Not once. Because that limited it’s reuse in the future. I always tore them all the way down to their smallest bits and then built things back up. I only had a small amount of lego blocks. But I felt like I could build ANYTHING. Ships. Cars. Buildings. Roads. Weird geometric shapes. My powers as a 7 year old were limitless. Now if you gave me huge power ranger figures built out of larger lego block components i.e a huge arm and a huge leg that connect to a body and a head - maybe my action figures are super cool - maybe they are fun to play with. But I’m a lot less powerful. All I can really build is other power rangers. And who knows how long those will be hip for.

If you want to name a component to find it within views - you can use the data-* attribute for this i.e

<div data-componentName=“media-content-block”>
</div>

I think it’s a misconception that a pattern of classes would be hard to find though. Your button examples is perfect.
If a button is comprised of a button class and some other spacing / sizing utilities - that should be very easy to grep for all elements that have the same combination of inline classes.

ie.

<a href=“#” class=“btn btn--blue f3 f2-ns pas pam-ns”>Button text</a>

In this example we have a btn class, a btn skin class that is blue, font-size-3 in a type scale at mobile sizes, and font-size-2 at larger than mobile sizes. The padding is small at mobile and medium for things larger than mobile.

you should now be able to search for every component that has this series of classes. It is no different than grepping for anything else. It’s just a string of characters in between quotes. Two methods to streamline this further would be to have something in your build process that reorders class declaration by a set of rules. You can also just document those rules and have developers follow them. You might be surprised at how naturally the order of single purpose classes starts to present itself in regards to how you think about developing a component. But that’s a longer thought for a different time.

Please don’t hesitate to disagree or ask more questions :)

@davidpots
Copy link

@_mrmrs big thanks for the answer, love the Lego analogy. Another analogy I've started thinking of recently (with all this stuff) is Batman's utility belt – probably because of the word "utility" also being used to describe these single-purpose classes that are fundamentally agnostic to the many ways they'll be used. I think of the situations Batman would find himself in with bad guys, where he'd need to use several items from his belt in a creative way to stop them: Joker climbing a rope ladder at night while very windy; Penguin escaping on a raft in a river of poison filled with sharks, etc etc – in each circumstance, Batman would need to use a different combination of multiple tools from his utility belt to achieve the goal in those specific scenarios. What he wouldn't do is have an item on his belt named "the Joker-escaping-on-a-rope-ladder-when-it's-windy mega-weapon", because what if it isn't windy OR it's a wooden ladder OR it isn't the Joker... in those cases he might need to mix up a few of the tools in order to catch the bad guy. And obviously, a pre-cooked mega-weapon like that would be huge, take up lots of space on his belt, and probably be used super infrequently (this inferring a large cost of weight, etc).

Ultimately, I think my question stems from the POV of not yet having fully embraced a system like this as part of a much larger project that tons of other people are touching. Different things come up such as what will work best for this particular team, what will the workflow look like when updating markup way-down-the-road for components that are created via some deeply coupled Ruby-builder-thing, etc. So, I look forward to making this happen – and having the actual working experience catch up with all this theory.

Thanks again!

@mrmrs
Copy link
Author

mrmrs commented Jul 8, 2014

@davidpots -
So I was thinking about your question about where to draw the line and I started thinking about it a bit differently this morning which is that instead of thinking - where do you draw the line - raising the question “what are the most useful abstractions?”

I think abstracting out single purpose classes for

  • whitespace i.e padding and margins
  • typescale
  • display and widths / dimensions
  • colors

Then see where you want to go from there. I think just starting with that as a base will greatly reduce redundant code in css, make your html more readable, and make it easier to prototype in the browser.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment