CSS - OOCSS, SMACSS and more

Post on 08-Sep-2014

19426 Views

Category:

Technology

2 Downloads

Preview:

Click to see full reader

DESCRIPTION

An introduction to the changing world of CSS. Slides from Brisbane Web Designer Meetup 13 March 2013.

Transcript

CSSoocss, smacss & more...

what’s wrong with

CSS

CSS is simple... It’s simple to

understand. But CSS is not

simple to use or maintain.

”http://chriseppstein.github.com/blog/2009/09/20/why-stylesheet-abstraction-matters/

If you’ve ever worked on a medium to large website, you have probably come across a range of issues with CSS.

Issues

Lots of floats, font-size references, heading levels repeated...

Repetition

It may have started out well, but it has become a mess?

Unmanageable

You need to add some CSS - so you have to start adding to selectors in order to win.

Weight war

Your CSS is specifically tied to HTML or location...

Coupling

Developers have been telling us for years that “CSS sucks”. We all know it’s time for our CSS practices to evolve.

CSS sucks!

Luckily, there are a wide range of exciting new developments to explore.

New stuff!

Before we start... put aside any biases. At least until after the presentation, when you can rip into me :)

Biases aside...

oocssobject oriented css

What is OOCSS?

In 2009, Nicole Sullivan introduced a new way of looking at CSS. She defined this as Object Oriented CSS (OOCSS).

After optimising Facebook’s CSS, she discovered some amazing statistics... about how we reapply CSS properties throughout our style sheets.

Statistics

Facebook:Facebook blueUnique colors

colors

Salesforce:padding

h1-h6

261548

6,498

3,668511

“We have been doing it all

wrong.... Our best practices are

killing us”

Nicole Sullivan

The purpose of OOCSS is to

encourage code reuse and,

ultimately, faster and more

efficient stylesheets that are

easier to add to and maintain.

http://coding.smashingmagazine.com/2011/12/12/an-introduction-to-object-oriented-css-oocss/

Looking for patterns - rows

One of the key aims of OOCSS is to abstract as many components of the layout as possible.

Abstraction

Can you see any repeating visual patterns?

Example

The first layout pattern could be the rows.

Rows

row

row

row

row

row

row

row

row

In the past, people may have styled these rows using a series of IDs.

Past practice

#header

#main

#news

#footer

1. use a single class so that it can be reused as needed2. abstract the module down to core purposes

OOCSS aims

These rows have two purposes:1. clear each row2. trigger the block formatting context.

Core purposes

.row

.row

.row

.row

Then we can write one simple, but very powerful class that can be reused anywhere in the layout.

Re-use

.row {! clear: left;! overflow: hidden;! zoom: 1;! _overflow: visible;}

IE6 underscore hack

Triggers haslayout in IE5-7

Triggers block formatting

Clears each row

Different rows

Did you notice that two of the rows were different? They have different background colours and additional padding above and below.

Different rows

We could now add some classes based on the purpose of these rows - such as “news” and “footer”.

New names?

.news {! padding: 1em 0;! background-color: blue;!}

.footer {! padding: 1em 0;! background-color: pink;!}

However, it would be better to abstract these names further so that they are more flexible.

Abstract

.row {! clear: left;! overflow: hidden;! zoom: 1;! _overflow: visible;}

.row-alt1 {! padding: 1em 0;! background-color: blue;!}

.row-alt2 {! padding: 1em 0;! background-color: pink;!}

<div class="row"></div><div class="row"></div><div class="row row-alt1"></div><div class="row row-alt2"></div>

If you wanted, these could be abstracted even further into padding and backgrounds as separate concepts.

Further

.row-padding {! padding: 1em 0;}

.bg-color1 {! background-color: blue;!}

.bg-color2 {! background-color: pink;!}

<div class="row"></div><div class="row"></div><div class="row row-paddingbg-color1"></div><div class="row row-paddingbg-color2"></div>

It depends on the site and circumstances as to how far you think you need to abstract these concepts.

Up to you

The row module

The “row” class is our primary module. The additional classes are “modifiers” as they modify the primary class.

Primary module

Modifiers should not rewrite any aspect of the primary module, they only modify or add to the primary module.

Modifiers

Primary module

.row-alt1

Sub-module Modifier

.row-alt1

Types of class

Looking for patterns - columns

The second layout pattern could be the columns. The wide layout looks like it has four columns.

Columns

Column 1 Column 2 Column 4Column 3

Some of the rows spread across all columns. Others spread across two or one column.

Patterns

4 columns

2 columns

2 columns

1 columns

2 columns

2 columns

1 columns 1 columns1 columns

Column 1 Column 2 Column 4Column 3

To be safe, we should assume we need containers for 4, 3, 2 and 1 column widths. We can convert these column options into a simple grid framework.

Framework 1

Wide layout4 column box 3 column box2 column box1 column box

Class names.w-4col .w-3col .w-2col .w-1col

<div class="row">! <div class="w-4col"></div></div><div class="row">! <div class="w-2col"></div>! <div class="w-2col"></div></div><div class="row row-alt1">! <div class="w-2col"></div>! <div class="w-2col"></div></div><div class="row row-alt2">! <div class="w-1col"></div>! <div class="w-1col"></div>! <div class="w-1col"></div>! <div class="w-1col"></div></div>

The same is true of the narrow layout, except this time it has only two overall columns.

Narrow

Column 1 Column 2

2 columns

1 columns 1 columns

1 columns 1 columns

1 columns 1 columns

We could also create a second, different grid for narrow screen. This would allow us to control whether columns sat beside each other or below at a narrower screen size.

Framework 2

Narrow layout2 column box 1 column box

Class names.n-2col .n-2col

<div class="row">! <div class="w-4col"></div></div><div class="row">! <div class="w-2col n-2col"></div>! <div class="w-2col n-2col"></div></div><div class="row row-alt1">! <div class="w-2col n-2col"></div>! <div class="w-2col n-2col"></div></div><div class="row row-alt2">! <div class="w-1col n-2col"></div>! <div class="w-1col n-2col"></div>! <div class="w-1col n-2col"></div>! <div class="w-1col n-2col"></div></div>

With these two simple grids, we can control complicated layouts - both wide and narrow.

Control!

Looking for patterns - boxes

You may have noticed that there were also a series of smaller boxes, each with an image to the left or right.

Boxes?

1. contain content2. feature object to left or right3. content beside feature object4. margin below

Core purpose

Adaptable boxWe need to create an adaptable box:- could be placed anywhere- any width or height- any feature content- feature content could be left/right- any content inside the body

We need to be able to target - the overall box- the object (left or right)- the body content within the box- a possible heading (h1-h6)- possibly even the contents itself

Target

This is a headingLorem ipsum dolor sit amet consect etuer adipi scing elit sed diam nonummy nibh euismod tinunt ut laoreet dolore magna aliquam erat volut.

box

box feature

box bodybox heading

box content

.box { }

.box-feature { }

.box-feature-alt { }

.box-body { }

.box-heading { }

.box-content { }

There are a range of possible class we could use here.

Do not give the box a width - allow it to spread to fit the width of any parent container.

Width

This box module must contain (and therefore wrap around) either a left or right floating object. We can solve this by triggering the block formatting context on the parent.

Contain floats

.box {! overflow: hidden;! zoom: 1;! _overflow: visible;! margin-bottom: 1em;}

Triggers block formatting

The box must work when placed anywhere within the layout. The box must be “location agnostic”.

Location Agnostic

aside .box { }.box { }

The box may contain objects that have varying widths. We need our content box (“box-body”) to sit beside these objects, regardless of their widths.

Sit beside

We can solve this by triggering the block formatting context on the “box-body” class.

BFC again

This is a headingLorem ipsum dolor sit amet consect etuer adipi scing elit sed diam nonummy nibh euismod tinunt ut laoreet dolore magna aliquam erat volut.

box-body

.box-body {! overflow: hidden;! zoom: 1;! _overflow: visible;}

Triggers block formatting

The box module

We have just made a very powerful box. Nicole Sullivan refers to this box as the “media” element.

Powerful box

.box,.box-body {! overflow: hidden;! zoom: 1;! _overflow: visible;}

.box { margin: 0 0 10px; }

.box-feature {! float: left;! margin: 0 10px 0 0;}

.box-feature-alt {! float: right;! margin: 0 0 0 10px;}

In this case, the “box” class is our primary module. There are no modifiers, but there are a range of sub-modules.

Primary module

Sub-modules are other classes associated with the primary module. They do not alter or add directly to the primary module.

Sub-modules

Types of classPrimary module

.row-alt1

.box

Sub-module

.box-feature

.box-body

Modifier

.row-alt1

Moving forward

For years, we have been taught to keep our markup clean and only use “semantic” class names.

Semantic classes

OOCSS seems to break both of these rules - and in a big way. But have we been thinking about “semantic” class names in the wrong way?

Break the rules?

HTML class names offer no

semantic value to search engines

or screen readers, aside from

microformats.

http://www.brettjankord.com/2013/02/09/thoughts-on-semantic-html-class-names-and-maintainability/

Rather than concerning

ourselves with creating semantic

class names, I think we should be

thinking about creating sensible

class names. Sensible class

names offer semantics, but they

also offer flexibility/reusability.

http://www.brettjankord.com/2013/02/09/thoughts-on-semantic-html-class-names-and-maintainability/

If your class is called “blue” and

you want to change it to red, you

have far bigger problems than

class names to deal with!

https://speakerdeck.com/andyhume/css-for-grown-ups-maturing-best-practises

In order to move forward, especially on large scale sites, we cannot keep using old practices.

Move forward

OOCSS offers front end developers an alternative - light weight, modular CSS that can be re-used repeatedly across sites.

Solution?

smacsscss architecture

What is SMACSS?

SMACSS is more style guide than

rigid framework - an attempt to

document a consistent approach

to site development when using

CSS.

http://alistapart.com/article/frameworksfordesigners

In 2011, Jonathan Snook introduced a new way of looking at CSS architecture. He called this Scalable and Modular Architecture for CSS (SMACSS)

Categorization

Base rulesLayout rulesModule (and sub-module) rulesState rulesTheme rules

Categories

Base rules are the defaults. They are almost exclusively single element selectors.

Base

Layout rules divide the page into sections. Layouts hold one or more modules together.

Layout

Modules are the reusable, modular parts of our design. They are the callouts, the sidebar sections, the product lists and so on.

Modules

SMACSS allows for primary modules, modifiers and sub-modules, though they are labelled slightly differently.

Primary module

.row-alt1

.box

Sub-moduleSub-component

.box-feature

.box-body

ModifierSub-module.row-alt1

State rules are ways to describe how our modules or layouts will look when in a particular state. Is it hidden or expanded?

States

Theme rules describe how the layout or modules might look.

Themes

Naming Convention

Use classes rather than IDs for styling purposes. Classes are more flexible. Using classes can reduce specificity issues.

Avoid IDs

Class names should be meaningful for other authors, so that other developers can understand their purpose.

Meaningful

Class names should follow understandable patterns.

Pattern

Use “pseudo-namespaces” as prefixes - so that modules, modifiers and sub-modules can be identified.

Prefixes

Possibly use different naming conventions for modifiers, sub-modules and states.

.example-widget { }

.example-widget--modifier { }

.example-widget__sub-module { }

.example-widget--is-somestate { }

Modifiers

Decouple HTML/CSS

I’ve noticed that designers

traditionally write CSS that is

deeply tied to the HTML that it is

designed to style. How do we

begin to decouple the two for

more flexible development with

less refactoring?

http://coding.smashingmagazine.com/2012/04/20/decoupling-html-from-css/

So how do we “decouple” our HTML and CSS.1. using additional class names2. using child selectors

Decouple

To see this in action, let’s look at the “box” example from earlier. What if we wanted to style the heading inside the “box-body”.

Example

This is a headingLorem ipsum dolor sit amet consect etuer adipi scing elit sed diam nonummy nibh euismod tinunt ut laoreet dolore magna aliquam erat volut.

heading

We could style this heading using something like this:

.box { }

.box h2 { }

Style the h2?

<div class="box">! <img class="box-feature"! src="dummy-140.png" alt="">! <div class="box-body">! ! <h2>Heading</h2>! ! </p>Lorem ipsum dolor</p>! </div></div>

The problem is that the CSS is “coupled” with the HTML. What happens if there is an <h3> element inside the box?

Problem?

One solution would be to set all heading levels.

.box { }

.box h1 { }

.box h2 { }

.box h3 { }

.box h4 { }

.box h5 { }

.box h6 { }

However, the safest way to “uncouple” the CSS and HTML would be to use a simple class.

Use a class

<div class="box">! <img class="box-feature"! src="dummy-140.png" alt="">! <div class="box-body">! ! <h2 class="box-heading">! ! ! Heading</h2>! ! </p>Lorem ipsum dolor</p>! </div></div>

Now our HTML and CSS are more flexible. It doesn’t matter what heading level is used.

.box { }

.box-heading { }

More flexible

modulesa closer look at

The following “module” guidelines apply regardless of whether you are coming from OOCSS or SMACSS.

Guidelines

Rule 1: keep modules simple

By making your base objects this

simple your choices become

boolean; you use the object or

you don’t. The object is either

entirely suitable as a basis, or

entirely _un_suitable.

http://csswizardry.com/2012/06/the-open-closed-principle-applied-to-css/

The base module should be defined as simply as possible. This means that they are highly flexible.

Keep ‘em simple

Let’s use an example of our “row” class. What if we added some padding to this rule?

.row {! clear: left;! overflow: hidden;! padding: 20px 0;}

But what if we want a row that doesn’t have padding? The problem is that this rule is now very specifically defined. It is therefore not as flexible.

Rule 2: don’t undo styles

Any CSS that unsets styles (apart

from in a reset) should start

ringing alarm bells... Rulesets

should only ever inherit and add

to previous ones, never undo.

http://csswizardry.com/2012/11/code-smells-in-css/

Leading on from the first rule, you should avoid writing rules to undo a previous module.

Don’t undo

For example, what if you wanted almost all of your headings to have a border-bottom?

h2 {! font-size: 1.5em! margin-bottom: 1em;! padding-bottom: 1em;! border-bottom: 1px solid red;}

But in some cases you might want a heading without a border-bottom.

You could write a new rule like this:

.no-border {! padding-bottom: 0;! border-bottom: none;}

This is not ideal. It is much better to write sub-modules that add styles, rather than write sub-modules to undo styles.

So, a better way might be to write two rules like this:

/* default style */h2 {! font-size: 1.5em! margin-bottom: 1em;}

/* only when border needed */.headline {! padding-bottom: 1em;! border-bottom: 1px solid red;}

Rule 3: extend but don’t

modify

Base modules can be extended using sub-modules. However, the base module itself should never be modified.

Don’t modify

This is based on the object oriented programming “open/close principle”.

Software entities (classes,

modules, functions, etc.) should

be open for extension, but closed

for modification.

http://en.wikipedia.org/wiki/Open/closed_principle

If a based module needs to be modified to suit a specific case, it is probably better to create a new module.

Rule 4: think before adding

new modules

It is always tempting to add a module based on your need at the time... as well as based on the needs of the system.

Don’t rush

This often happens after the initial planning and build has been done. It’s easy to be tempted by “I’ll just drop this new class in at the bottom of my CSS”.

However, adding poorly structured new modules, without rigorous abstraction, will lead to bloated, hard-to-manage CSS.

practicescoding

Comment conventions

There is a growing trend to use the DocBlock as an overall comment convention. In fact, a movement around this type of commenting began over 6 years ago with the CSSdoc group

DocBlock

"A DocBlock is an extended C++-

style PHP comment that begins

with "/**" and has an "*" at the

beginning of every line.

DocBlocks precede the element

they are documenting...

http://en.wikipedia.org/wiki/PHPDoc

/** * Short desc * * Long description first sentence starts * and continues on this line for a while * finally concluding here at the end of * this paragraph * * The blank line above denotes a paragraph */

Formatting CSS rules

In the early days of CSS, a lot of developers preferred single line CSS rules as they could easily see the selectors.

Single line?

Today, with the complexity of individual rules, most developers seem to prefer either the multi-line format, or multi-line with indenting format.

Multi-line

Multi-line Format with IndentingMulti-line FormatSingle-line FormatSingle-line Format with Indenting/TabbingMostly Single-line FormatSingle-line Format with TabbingOther

44%28%11%5%5%4%3%

*CSS-tricks poll: http://css-tricks.com/different-ways-to-format-css/

CSS Tricks rule formatting poll

.navigation_rss_icon {! position: absolute;! left: 940px;! bottom: 0px;}

#navigation_rss {! position: absolute;! left: 720px;! font-family: Verdana, Arial, Helvetica, sans-serif;! text-transform: uppercase;! color: #897567;! line-height: 2.5em;}

#navigation_rss li {! display: inline;}

#navigation_rss li a:link, #navigation_rss li a:visited {! color: #fffffe;! text-decoration: none;! padding: 0px 2px;! letter-spacing: -0.05em;}#navigation_rss li a:hover {! color: #eed2a1;! text-decoration: none;}

.navigation_rss_icon { position: absolute; left: 940px; bottom: 0px;}

#navigation_rss { position: absolute; left: 720px; font-family: Verdana, Arial, Helvetica, sans-serif; text-transform: uppercase; color: #897567; line-height: 2.5em;}

#navigation_rss li { display: inline; }

#navigation_rss li a:link, #navigation_rss li a:visited { color: #fffffe; text-decoration: none; padding: 0px 2px; letter-spacing: -0.05em; }

Declaration order

Similarly, many developers used to prefer to sort their declarations alphabetically.

Alphabet?

Today, most people prefer to group their declarations by type.

Group

Grouped by type 45%Random - 39%Alphabet - 14%By line - 2%

45%39%14%2%

*CSS-tricks poll: http://css-tricks.com/different-ways-to-format-css/

CSS Tricks declaration formatting poll

.selector { /* Positioning */ position: absolute; z-index: 10; top: 0; right: 0;

/* Display & Box Model */ display: inline-block; overflow: hidden; box-sizing: border-box; width: 100px; height: 100px; padding: 10px; border: 10px solid #333; margin: 10px;

/* Color */ background: #000; color: #fff /* Text */ font-family: sans-serif; font-size: 16px; line-height: 1.4; text-align: right;

/* Other */ cursor: pointer;}

Of course, many tools and pre-processors take care of this for you. If your tools do not have this capability, take a look at CSS Combhttp://csscomb.com/

get busy!

Russ WeakleyMax Design

Site: maxdesign.com.auTwitter: twitter.com/russmaxdesignSlideshare: slideshare.net/maxdesignLinkedin: linkedin.com/in/russweakley

top related