Partially sassy

Organizing partials for your stylesheets can help to: Quickly add and remove elements/features, reduce merge conflicts, reduce ramp-up time, and keep your styles out of the html markup.

Key Structure Points

  • Have one master file to visualize your cascades.
  • Separate Visual and Positional Styles.

Separation of .class

Visual styles belong in mixins. Example: If you’re styling a button, that button’s mixin should be defined in a _buttons.scss partial. This would include the gradient, shadow, :hover, :focus and :active states.

Positional styles are best suited for page-specific files. Using our button, styles for position, margin, height and width would be defined on a per-page basis.

Padding, height and width can be tricky at times. Our button style may have some standard padding, but you may feel the need to customize on a page. This is best done in _yourpage.scss rather than in the general style rules.

Pull it together by chaining @mixins or @extend to apply styles. SASS. By using @mixins, your presentational markup will stay within the stylesheet and away from your html. The beauty of that is 1-control point over visual style, 1-control point for the positional style, and best of all: 1-control point for the semantic class of your element.

Example master file

screen.scss
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@import "base/_utilities";
@import "base/_colors";
@import "base/_zindex";
@import "base/_reset";
@import "base/_typography";

@import "elements/_elements";
@import "elements/_buttons";
@import "elements/_links";
@import "elements/_lists";
@import "elements/_forms";
@import "elements/_tables";
@import "elements/_scrollbar";

@import "ui_elements/_tabs";
@import "ui_elements/_tags";
@import "ui_elements/_tool_tip";

@import "shared_partials/_header";
@import "shared_partials/_nav";

@import "pages/_dashboard";
@import "pages/_profile";
@import "pages/_some_page";
@import "pages/_another_page";

Base

Utilities

Vendor prefixes, custom mixins, etc.

_utilities_and_mixins.scss
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@mixin box-sizing( $box-size ) {
  -webkit-box-sizing: $box-size;
   -khtml-box-sizing: $box-size;
    -icab-box-sizing: $box-size;
     -moz-box-sizing: $box-size;
       -o-box-sizing: $box-size;
          box-sizing: $box-size;
}

@mixin fill( $position:absolute ) {
  position: $position;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}

@mixin clearfix( $pseudo:"after" ) {
  &:#{ $pseudo } {
    content: "";
    display: block;
    height: 1px;
    width: 1px;
    clear: both;
    position: relative;
  }
}
%clearfix { @include clearfix; }


//-------------------------------------------------
// centering absolute or fixed positioned elements.
@mixin vertical-middle( $height ) {
  top: 50%;
  margin-top: -($height/2);
}
@mixin horizontal-center( $width ) {
  left: 50%;
  margin-left: -($width/2);
}

Reset

Reset the browser defaults to take control. This will greatly improve the consistency of your styles across devices. The entent of your rest file is up to you and your design goals. A very important piece of the reset file is the box-sizing: border-box.

_reset.scss
1
2
3
4
5
* {
  @include box-sizing(border-box);//save your sanity
  margin: 0;
  padding: 0;
}

Colors

Base colors, using sass $variables.

_colors.scss
1
2
3
4
5
6
7
// sample brand color palette.
$off-white: #FEFEFE;
$blackblue: #162934;
$lightblue: #29AAE2;
$darkblue: #006FAB;
$lightpink: #C9006B;
$maroon: #7C0040;

Typography

@font-face, and typeface @mixins. I like to define @mixins for an icon font and a few weights of sans-serif and serif. This will create one control point for your typefaces, regardless of icon-fonts or design thrashes.

_typography.scss
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// import a sans and serif from google apis
@import url('http://fonts.googleapis.com/css?family=Crimson+Text:400italic,');
@import url(http://fonts.googleapis.com/css?family=PT+Sans:400,700);

// declare your mixins for typeface-styles
$serif-fallback: Georgia, "Times New Roman", serif;
$sans-fallback: Helvetica, Arial, Sans-Serif;

$serif: "Crimson Text", $serif-fallback;
$sans: "PT Sans", $sans-fallback;

@mixin light-text {
  color: $off-white;
  text-shadow: 0 -1px rgba($blackblue, .3);
}

@mixin dark-text {
  color: $blackblue;
  text-shadow: 0 1px rgba($off-white, .3);
}

$body-copy-font-size: 14px;
$body-copy-line-height: 20px;

$h1-font-size: 36px;
$h1-line-height: 44px;

$h2-font-size: 24px;
$h2-line-height: 30px;

html, body {
  font-family: $sans;
  color: $body-copy-color;
}

h1 {
  font-size: $h1-font-size;
  line-height: $h1-line-height;
}


h2 {
  font-size: $h2-font-size;
  line-height: $h2-line-height;
}

Z-index

Every z-index in the entire app. Probably one of the most important files to keep seperate. This will prevent you from dealing with 99, 99999, 99999999, etc. With a simple z-index file, you can use $variables to define z-indexes for various places and will always have a place to find all your z-index. This makes it very easy to solve z-index issues and transition to anther teammate.

_zindex.scss
1
2
3
4
// ALL z-indices go here.
$checkbox-mask-z: 1;
$overlay-z: 2;
$modal-z: 3;

Base Elements

Base elements

Keep the visual-styles of your basic elements here. Things like background-colors and borders for the body, section, article, a, ul, li. Depending on the number of layouts in your app, this may even be a good spot to define the padding for the body or body > section.

_elements.scss
1
2
3
4
5
6
7
8
9
10
11
12
body {
  @include font-sans-serif;
  padding: 10px 20px;
  font-size: $base-font-size;
}

a {
  color: $blackblue;
  text-shadow: none;
  @include transition( color .2s );
  &:hover { color: lighten($darkblue, 10%); }
}

Buttons, Forms, Misc, etc

You may notice that pieces of base_elements.scss need to be seperated after some time. Some form elements, like select and checkboxes may need their own stylesheets in order to keep forms.scss from becoming too large.

UI elements and partials

Tabs, tags, modals, header, footer, etc.

We’ve finally reached the place to begin adding some positional css, but not too much. We should only be assigning positional styling to our container’s/partial’s children. By staying inside of our partial’s own bounds we enable our containers/partials to be postioned by their super-view without conflict.

_modal.scss
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
.modal.form {
  form {
    p {
      display: inline-block;
      width: 50%;
      margin: 10px 0;
      padding: 0 5px; }

    input { width: 100%; }
  }

  input[type=submit] {
    float: right;
    margin-right: 5px;
    @include blue-button;
    display: block;
    width: auto;
  }
}

Pages

Dashboards, search, profile, etc.

Start positioning those elements within your page. Watch out for the gotchas and take note if you start to use more than @mixins for visual styles. This could be sign that you’re either not sticking the styleguide you built, or maybe you could benefit from another @mixin in your deck.

_dashboard.scss
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// keyframes
@include keyframes(spinner) {
  from { @include transform(rotate(0deg)); }
  to { @include transform(rotate(360deg)); }
}

@include keyframes(dashboard-slide-in) {
  from { @include transform( translateX( -$dashboard-nav-expanded-width) ); }
  to { @include transform( translateX(0) ); }
}


.dashboard-main {
  @include respond-to(small-mode) {
    padding-top: $gutter-vertical;
    padding-bottom: $gutter-section*2;
  }


  > * {
    padding-right: $gutter-section;
    padding-left: $gutter-section;
  }


  #main & .page-title { display: block; }


  @include respond-to(medium-up) {
    h2, h3 { margin-bottom: 0; }

    .mobile-top { display: none; }

    .rose-chart-wrapper {
      text-align: right;
      h3 { padding-right: $gutter-section*2; }
    }
  }

  .rose-chart {
    margin: 0;
    max-width: 100%;
    @include animation(spinner 72s infinite linear);
  }
}



@include respond-to(medium-up) {
  .dashboard-page {
    #main {
      left: $dashboard-nav-expanded-width;
      overflow-y: scroll;
      overflow-x: hidden;
    }


    #main-nav {
      @include kill-main-nav-tool-tip;
      width: $dashboard-nav-expanded-width;

      @for $i from 1 through length($nav-links) {
        li:nth-of-type(#{$i}) span { @include animation(dashboard-slide-in #{0.1*$i}s) }
      }

      span {
        left: 0;
        padding-left: 0;
      }
    }
  }
}