CSS Units of Measurement

Defining Length

According to the W3C:

Lengths refer to distance measurements

The format of a length value (denoted by >length< in this specification) is a number (with or without a decimal point) immediately followed by a unit identifier (e.g., px, em, etc.). After a zero length, the unit identifier is optional.

Some properties allow negative length values, but this may complicate the formatting model and there may be implementation-specific limits. If a negative length value cannot be supported, it should be converted to the nearest value that can be supported.

If a negative length value is set on a property that does not allow negative length values, the declaration is ignored.

http://www.w3.org/TR/CSS2/syndata.html#length-units

Absolute length (size) units`

Absolute length units are fixed in relation to each other. They are mainly useful when the output environment is known. Absolute values can be expressed in:

  • in: inches — 1in is equal to 2.54cm.
  • cm: centimeters
  • mm: millimeters
  • pt: points — the points used by CSS are equal to 1/72nd of 1in.
  • pc: picas — 1pc is equal to 12pt.
  • px: pixel units — 1px is equal to 0.75pt.

Or using one of the following pre-defined keywords

  • xx-small
  • small
  • medium
  • large
  • x-large
  • xx-large

Examples of absolute size values

h1 { margin: 0.5in }      /* inches  */
h2 { line-height: 3cm }   /* centimeters */
h3 { word-spacing: 4mm }  /* millimeters */
h4 { font-size: 12pt }    /* points */
h4 { font-size: 1pc }     /* picas */
p  { font-size: 12px }    /* px */

In the example above all elements will retain the assigned measurements, regardless of their parent or surrounding elements measurements.

Absolute size keywords are calculated by the User Agent (browser) and will be slightly different from one to another.

Relative length (size) units

Relative lengths and measurements are based on the computed-style of the current element. The only exception is font-size where the size is calculated based on the parent element

According to W3C:

Relative length units specify a length relative to another length property. Style sheets that use relative units can more easily scale from one output environment to another.

cite=”http://www.w3.org/TR/CSS2/syndata.html”

Relative units defined in CSS2 and CSS3

  • em: the ‘font-size’ of the relevant font
  • rem (root em): calculated based on the font-size of the root element
  • ex: the ‘x-height’ of the relevant font
  • percentages: a fraction of the parent element’s measurement

Any of the predefined keywords:

  • Larger
  • Smaller

Examples using em, ex and percentages

h1 { margin: 0.5em; }      /* em */
h1 { margin: 1ex; }        /* ex */
h1 { margin: 125%; }       /* percentage */ 

Examples using rem

html { font-size: 16px /* to make the example clearer */ } 
body { font-size: 1.5rem; } /* =24px */
h1   { font-size: 2.5rem; } /* =40px */

CSS paged media

In paged media the content of the document is split into one or more discrete pages. Paged media includes paper, transparencies, pages, Microsoft Word documents, Adobe PDF (portable document format) files among others

This needs to be tested with modern browsers. As far as I know this is only supported on Chrome and, maybe, Firefox

I am currently working on a sample page and associated stylesheet to test the concept and see how well it works. See the bottom of this post for more information

We no longer need to convert our documents into PDF or Word in order to print them. Using paged media and good layout and typography there is no reason not to expect high quality print results from our web content.

This is not a widely supported technology in browsers but it’s getting there and, when it does, it’ll make HTML an even better format to publish content.

There are formatters; programs that will take an HTML file and the style sheet and output a file suitable for printing. Some of the formatters include:

This is not quite the ideal I had in mind when I first started looking at Paged Media but until browser support gets better than it may just have to do.

Before we jump in to the code, there’s one great article from A List Apart that covers book making with CSS: Building books with CSS

Defining Pages: the @page rule

CSS defines a “page box”, a box of finite dimensions where content is rendered. It is formed by two areas:

  • The page area: The page area includes the boxes laid out on that page. The edges of the page area act as the initial containing block for layout that occurs between page breaks.
  • The margin area: which surrounds the page area.

You can specify the dimensions, orientation, margins, etc. of a page box within an @page rule. The dimensions of the page box are set with the ‘size’ property. The dimensions of the page area are the dimensions of the page box minus the margin area.

For example, the following @page rule sets the page box size to 8.5 x 11 inches and creates ‘1in’ margin on all sides between the page box edge and the page area:

<style tyle="text/css">
<!--
@page { size:8.5in 11in; margin: 1in; }
-->
</style>

You can use the margin, margin-top, margin-bottom, margin-left, and margin-right properties within the @page rule to set margins for your page same as you would for your regular CSS rules.

Setting Page Size:

The size property specifies the size and orientation of a page box. There are four values which can be used for page size:

  • auto: Same as the target paper size.
  • landscape: Vertical layout, larger side of the page are left and right
  • portrait: Horizontal layout, larger sides of the pare are top and bottom
  • length: Length values for the ‘size’ property create an absolute page box. Values are entered manually.

We’ll concentrate in length for this document. Once we’ve done some testing we will go back to how the auto, portrait and landscape value interact with the other parameters set up on the stylesheet

The example belows explicitly says the dimensions of the page to 8.5in by 11in. The pages created from the example requires paper that is 8.5″x11″ or larger.

<style tyle="text/css">
<!--
@page {
  size: 8.5in 11in;  /* width height */
}
-->
</style>

Once you create a named page layout, you can use it in your document by adding the page property to a style that is later applied to an element in your document. For example, this style renders all the tables in your document on landscape pages:

<style tyle="text/css">
<!--
@page { size : portrait }
@page rotated { size : landscape }
table { page : rotated }
-->
</style>

If the browser encounters a <table> element in your document and the current page layout is the default portrait layout, it will print the table in a new landscape page.

Left, right, and first pages:

When printing double-sided documents, the page boxes on left and right pages should be different. This can be expressed through two CSS pseudo-classes below:

<style tyle="text/css">
@page :first {
  size: 8.5in 11in;
}
@page :left {
  margin-left: 2.5in;
  margin-right: 1in;
}

@page :right {
  margin-left: 1in;
  margin-right: 2.5in;
}
</style>

The margins are mirror opposites from each other. When printed the pages will acommodate the margins for binding by providing additional space on the spine side.

The first page has it’s own pseudo class. Using the :first attribute we can style our first page independently from the rest of our content and make our first or title page look different like we do in the example below:

<style tyle="text/css">
<!--
@page { 
  margin: 1in /* All margins set to 2cm */
} 

@page :first {
  margin-top: 4in    /* Top margin on first page 10cm */
}
-->
</style>

Controlling pagination

Unless you specify otherwise, a page break only happens when there is a change in the page format or when the content fills the current page. To force or suppress page breaks, use the page-break-before, pagebreak-after, and page-break-inside properties.

Keywords for both page-break-before and page-break-after properties are: auto, always, avoid, left, and right.

The keyword auto is the default, it generate page breaks as needed. The keyword always forces a page break before or after the element, while avoid suppresses a page break immediately before or after the element. The left and right keywords force one or two page breaks, so that the element is rendered on a left-hand or right-hand page.

Suppose your document has level-1 headers start new chapters, with sections denoted by level-2 headers. We will start chapters on a new, right-hand page, but don’t want section headers to be split across a page break from the subsequent content. You can achieve this using following rule:

<style tyle="text/css">
<!--
h1 { page-break-before : right }
h2 { page-break-after : avoid }
-->
</style>

Use only the auto and avoid keywords with the page-break-inside property. To prevent tables from being broken accross pages, if possible, you would use the following rule:

<style tyle="text/css">
<!--
table { page-break-inside : avoid }
-->
</style>

Controlling widows and orphans:

Widow
A paragraph-ending line that falls at the beginning of the following page/column, thus separated from the rest of the text.

Orphan
A paragraph-opening line that appears by itself at the bottom of a page/column.

A word, part of a word, or very short line that appears by itself at the end of a paragraph. Orphans result in too much white space between paragraphs or at the bottom of a page.

From Wikipedia

Generally, printed pages do not look attractive with single lines of text stranded at the top or bottom. Most printers try to leave at least two or more lines of text at the top or bottom of each page.

  • The orphans property specifies the minimum number of lines of a paragraph that must be left at the bottom of a page.
  • The widows property specifies the minimum number of lines of a paragraph that must be left at the top of a page.

Here is the example to create 4 lines at the bottom and 3 lines at the top of each page:

<style tyle="text/css">
@page{
  orphans:4; 
  widows:2;
}
</style>

Initial stab at paged media stylesheet

See the test stylesheet for a possible way to make this work and the HTML document I’m using to experiment with the technology.

Expressing colors in CSS

As part of my research in Web Typography I got reacquainted with the many ways you can express colors in CSS. This was originally in my typography document but I think it’s better if I move it out to prevent an already long document from becoming unmanageable.

sRGB colors (3 or 6 digits)

This was what I always associted with colors in CSS and until not too long ago it was the only way to express colors. You can use either syntax but, as you can see in the example below, the 6 digit syntax allows for more precision in defining your colors.

The three definitions of a div container express the same color.

div {
  color: #0f0;   // The color 'lime' defined using the 3-digit hexadecimal notation
}

div {
  color: #00ff00; // The color 'lime' defined using the 6-digit hexadecimal notation
}

div {
  color: rgb(0, 255, 0) // The color 'lime' expressed with RGB notation
}

RGBa colors

This should be run behind a modernizr test as it’s not widely supported

This allows us to fill areas with transparent color; the first thee numbers representing the color in RGB values and the fourth representing a transparency value between 0 and 1 (zero being fully transparent and one being fully opaque). We have long had the opacity property, which is similar, but opacity forces all decendant elements to also become transparent and there is no way to fight it (except weird positional hacks) Cross-browser opacity is also a bit sloppy.

With RGBa, we can make a box transparent and leave its descendants alone

div {
   background: rgba(200, 54, 54, 0.5); 
}

Declaring a fallback color

Not all browsers support RGBa, so if the design permits, you should declare a “fallback” color. This color will be most likely be solid (fully opaque). Not declaring a fallback means no color will be applied in browsers that don’t support it. This fallback does fail in some really old browsers.

div {
   background: rgb(200, 54, 54); /* The Fallback */
   background: rgba(200, 54, 54, 0.5); 
}

Table below taken from the Mozilla Documentation Project. Credited according to a Creative Common Attribution-Share Alike License

Color keywords

Color keywords are case-insensitive identifiers which represent a specific color, e.g. red, blue, brown, lightseagreen. The name describes the color, though it is mostly artificial. The list of accepted values varied a lot through the different specification:

  • CSS Level 1 only accepted 16 basic colors, named the VGA colors as they were taken from the set of displayable colors on VGA graphic cards
  • CSS Level 2 added the orange keyword
  • From the beginning, browsers accepted other colors, mostly the X11 named colors list as some early browsers were X11 applications, though with a few differences. SVG 1.0 was the first standard to formally define these keywords; CSS Colors Level 3 also formally defined these keywords. They are often referred as the extended color keywords, the X11 colors, the SVG colors

There are a few caveats to consider when using keywords:

  • Except the 16 basic colors which are common with HTML, the others cannot be used in HTML. HTML will convert these unknown values with a specific algorithm which will lead to completely different colors. These keywords should only be used in SVG & CSS
  • Unknown keywords make the CSS property invalid. Invalid properties being ignored, the color will have no effect. This is a different behavior than the one of HTML.
  • No keyword-defined colors in CSS have any transparency, they are plain, solid colors.
  • Several keywords denote the same colors:
    • darkgray / darkgrey
    • darkslategray / darkslategrey
    • dimgray / dimgrey
    • lightgray / lightgrey
    • lightslategray / lightslategrey
    • gray / grey
    • slategray / slategray
  • Though the names of the keywords have been taken by the usual X11 color names, the color may diverge from the corresponding system color on X11 system as these are tailored for the specific hardware by the manufacturer .
Specifications Color Keyword RGB cubic coordinates Live Example
CSS3 CSS2 CSS1   black rgb(  0,   0,   0)  
  silver rgb(192, 192, 192)  
  gray[*] rgb(128, 128, 128)  
  white rgb(255, 255, 255)  
  maroon rgb(128,   0,   0)  
  red rgb(255,   0,   0)  
  purple rgb(128,   0, 128)  
  fuchsia rgb(255,   0, 255)  
  green rgb(  0, 128,   0)  
  lime rgb(  0, 255,   0)  
  olive rgb(128, 128,   0)  
  yellow rgb(255, 255,   0)  
  navy rgb(  0,   0, 128)  
  blue rgb(  0,   0, 255)  
  teal rgb(  0, 128, 128)  
  aqua rgb(  0, 255, 255)  
    orange rgb(255, 165,   0)  
    aliceblue rgb(240, 248, 255)  
  antiquewhite rgb(250, 235, 215)  
  aquamarine rgb(127, 255, 212)  
  azure rgb(240, 255, 255)  
  beige rgb(245, 245, 220)  
  bisque rgb(255, 228, 196)  
  blanchedalmond rgb(255, 235, 205)  
  blueviolet rgb(138,  43, 226)  
  brown rgb(165,  42,  42)  
  burlywood rgb(222, 184, 135)  
  cadetblue rgb( 95, 158, 160)  
  chartreuse rgb(127, 255,   0)  
  chocolate rgb(210, 105,  30)  
  coral rgb(255, 127,  80)  
  cornflowerblue rgb(100, 149, 237)  
  cornsilk rgb(255, 248, 220)  
  crimson rgb(220,  20,  60)  
  darkblue rgb(  0,   0, 139)  
  darkcyan rgb(  0, 139, 139)  
  darkgoldenrod rgb(184, 134,  11)  
  darkgray[*] rgb(169, 169, 169)  
  darkgreen rgb(  0, 100,   0)  
  darkgrey[*] rgb(169, 169, 169)  
  darkkhaki rgb(189, 183, 107)  
  darkmagenta rgb(139,   0, 139)  
  darkolivegreen rgb( 85, 107,  47)  
  darkorange rgb(255, 140,   0)  
  darkorchid rgb(153,  50, 204)  
  darkred rgb(139,   0,   0)  
  darksalmon rgb(233, 150, 122)  
  darkseagreen rgb(143, 188, 143)  
  darkslateblue rgb( 72,  61, 139)  
  darkslategray[*] rgb( 47,  79,  79)  
  darkslategrey[*] rgb( 47,  79,  79)  
  darkturquoise rgb(  0, 206, 209)  
  darkviolet rgb(148,   0, 211)  
  deeppink rgb(255,  20, 147)  
  deepskyblue rgb(  0, 191, 255)  
  dimgray[*] rgb(105, 105, 105)  
  dimgrey[*] rgb(105, 105, 105)  
  dodgerblue rgb( 30, 144, 255)  
  firebrick rgb(178,  34,  34)  
  floralwhite rgb(255, 250, 240)  
  forestgreen rgb( 34, 139,  34)  
  gainsboro rgb(220, 220, 220)  
  ghostwhite rgb(248, 248, 255)  
  gold rgb(255, 215,   0)  
  goldenrod rgb(218, 165,  32)  
  greenyellow rgb(173, 255,  47)  
  grey rgb(128, 128, 128)  
  honeydew rgb(240, 255, 240)  
  hotpink rgb(255, 105, 180)  
  indianred rgb(205,  92,  92)  
  indigo rgb( 75,   0, 130)  
  ivory rgb(255, 255, 240)  
  khaki rgb(240, 230, 140)  
  lavender rgb(230, 230, 250)  
  lavenderblush rgb(255, 240, 245)  
  lawngreen rgb(124, 252, 0)  
  lemonchiffon rgb(255, 250, 205)  
  lightblue rgb(173, 216, 230)  
  lightcoral rgb(240, 128, 128)  
  lightcyan rgb(224, 255, 255)  
  lightgoldenrodyellow rgb(250, 250, 210)  
  lightgray[*] rgb(211, 211, 211)  
  lightgreen rgb(144, 238, 144)  
  lightgrey[*] rgb(211, 211, 211)  
  lightpink rgb(255, 182, 193)  
  lightsalmon rgb(255, 160, 122)  
  lightseagreen rgb( 32, 178, 170)  
  lightskyblue rgb(135, 206, 250)  
  lightslategray[*] rgb(119, 136, 153)  
  lightslategrey[*] rgb(119, 136, 153)  
  lightsteelblue rgb(176, 196, 222)  
  lightyellow rgb(255, 255, 224)  
  limegreen rgb( 50, 205,  50)  
  linen rgb(250, 240, 230)  
  mediumaquamarine rgb(102, 205, 170)  
  mediumblue rgb(  0,   0, 205)  
  mediumorchid rgb(186,  85, 211)  
  mediumpurple rgb(147, 112, 219)  
  mediumseagreen rgb( 60, 179, 113)  
  mediumslateblue rgb(123, 104, 238)  
  mediumspringgreen rgb(  0, 250, 154)  
  mediumturquoise rgb( 72, 209, 204)  
  mediumvioletred rgb(199,  21, 133)  
  midnightblue rgb( 25,  25, 112)  
  mintcream rgb(245, 255, 250)  
  mistyrose rgb(255, 228, 225)  
  moccasin rgb(255, 228, 181)  
  navajowhite rgb(255, 222, 173)  
  oldlace rgb(253, 245, 230)  
  olivedrab rgb(107, 142,  35)  
  orangered rgb(255,  69,   0)  
  orchid rgb(218, 112, 214)  
  palegoldenrod rgb(238, 232, 170)  
  palegreen rgb(152, 251, 152)  
  paleturquoise rgb(175, 238, 238)  
  palevioletred rgb(219, 112, 147)  
  papayawhip rgb(255, 239, 213)  
  peachpuff rgb(255, 218, 185)  
  peru rgb(205, 133,  63)  
  pink rgb(255, 192, 203)  
  plum rgb(221, 160, 221)  
  powderblue rgb(176, 224, 230)  
  rosybrown rgb(188, 143, 143)  
  royalblue rgb( 65, 105, 225)  
  saddlebrown rgb(139,  69,  19)  
  salmon rgb(250, 128, 114)  
  sandybrown rgb(244, 164,  96)  
  seagreen rgb( 46, 139,  87)  
  seashell rgb(255, 245, 238)  
  sienna rgb(160,  82,  45)  
  skyblue rgb(135, 206, 235)  
  slateblue rgb(106,  90, 205)  
  slategray[*] rgb(112, 128, 144)  
  slategrey[*] rgb(112, 128, 144)  
  snow rgb(255, 250, 250)  
  springgreen rgb(  0, 255, 127)  
  steelblue rgb( 70, 130, 180)  
  tan rgb(210, 180, 140)  
  thistle rgb(216, 191, 216)  
  tomato rgb(255,  99,  71)  
  turquoise rgb( 64, 224, 208)  
  violet rgb(238, 130, 238)  
  wheat rgb(245, 222, 179)  
  whitesmoke rgb(245, 245, 245)  
  yellowgreen rgb(154, 205,  50)  

[*] The ‘e’-grey colors (with an e) (grey, darkgrey, darkslategrey, dimgrey, lightgrey, lightslategrey) are only supported since IE 8.0. IE 3 to IE 6 only support the ‘a’ variants: gray, darkgray, darkslategray, dimgray, lightgray, lightslategray.

See the Mozilla Documentation Project CSS Color page for more information.

HSLa colors

This needs to be used behind a modernizr test, it is not fully supported

Using HSLa is similar to RGBa in that you declare three values determining the color and then a fourth value for its transparency level. You can read more about browser support below, but it’s basically any browser that supports rgba supports hsla too.

#some-element {
   background-color: hsla(170, 50%, 45%, 1);
}
  • Hue Think of a color wheel. Around 0o and 360o are reds 120o are greens, 240o are blues. Use anything in between 0-360. Values above and below will be modulus 360
  • Saturation 0% is grayscale. 100% is fully saturated (full color)
  • Lightness 0% is completely dark (black). 100% is completely light (white). 50% is average lightness
  • alpha Opacity/Transparency value. 0 is fully transparent. 1 is fully opaque. 0.5 is 50% transparent.

Using SASS smartly

This is a continuation to my earlier post on SASS: SASS, SCSS and Modular Design. This presents new ideas and more advanced mixins, tools and concepts.

During development, watch what you’re doing

An additional parameter to the SASS command line tool allows you to watch files for changes and then automatically recompile them. This reduces the commands that you have to type at the terminal and it makes it easier to track changes. The command I use to watch the folder containing my SASS is:

sass \
  --scss \ # tells SASS that we're using the SCSS syntax
  --update \ # compile the files to CSS
  --style expanded \ # use the expanded SASS/SCSS syntax
  --line-numbers \ # prints originating SCSS file and line number for debugging
  --line-comments \ 
  --watch \ # Makes sass update on change
  scss/:css/ # source SCSS and target CSS folders

I usually create a shell script with this command so I don’t have to type it over and over.

Start small, build big

Partials, mixins and SASS extension mechanism give you the ability to create small building blocks that you can then use as needed in larger blocks and applications.

Extension and placeholder selectors

(http://12devs.co.uk/articles/handy-advanced-sass/)

Your SASS stylesheets will grow quickly if you use the @include directive; this is unavoidable since it duplicates all the instructions that it is adding to each rule it is used in. Fortunately SASS gives us @extend which will group declarations together instead of copying from one into another

A Basic Example

.inline-block {
  display: inline-block; 
  vertical-align: baseline; 
  *display: inline; 
  *vertical-align: auto;
  *zoom: 1;
}

.btn {
  @extend .inline-block;
  padding: 0.5em 1em;
}

.foo {
  @extend .inline-block;
  color: red;
}

CSS Output

// selectors are grouped
.inline-block, .btn, .foo {
  display: inline-block; 
  vertical-align: baseline; 
  *display: inline; 
  *vertical-align: auto;
  *zoom: 1;
}

.btn {
  padding: 0.5em 1em;
}

.foo {
  color: red;
}

Instead of adding the styles from .inline-block into both of our .btn and .foo declarations, the extend directive grouped our classes alongside the .inline-block class, reducing duplication significantly.

Placeholder Selectors

In the previous example our .inline-block class was also generated amongst the group of declarations and had we not even extended the .inline-block class, it still would have been output in our final CSS file. This is not ideal and is exactly where Placeholder Selectors come in handy.

Any CSS declared within a placeholder will not be compiled in your final CSS file unless it has been extended (think abstract classes in languages like Java or C++). It also means that other developers cannot inadvertently hook onto these styles in their markup. It may be a better and less troublesome method to extend classes to extend placeholders instead.

Placeholders are declared and extended exactly the same way as classes except the dot is replaced with a percentage symbol:

%inline-block {
  display: inline-block; 
  vertical-align: baseline; 
  *display: inline; 
  *vertical-align: auto;
  *zoom: 1;
}

.btn {
  @extend %inline-block;
  padding: 0.5em 1em;
}

.foo {
  @extend %inline-block;
  color: red;
}

CSS Output

.btn, .foo {
  display: inline-block; 
  vertical-align: baseline; 
  *display: inline; 
  *vertical-align: auto;
  *zoom: 1;
}

.btn {
  padding: 0.5em 1em;
}

.foo {
  color: red;
}

Now, the selectors are grouped as before but without an .inline-block class in the group. Much better 🙂

Partials are your friends

I hate having to search a large file for a given piece of code. Thankfully I don’t have to work with just one file… that’s what partials are for. Similar to Ruby on Rails partials, partials in SASS allow you to break large stylesheets based on function, use or any other criteria you want to use.

In order to create a partial just follow your standard development practices and save the file with an underscore as the first character in the file name. To create a partial that contains your base variables, you can name it _base-vars.scss. and reference it from all other files using the variables or functionality implemented in the partial.

As discussed elsewhere we can then structure our content with only the partials that we need for a given project. Furthermore we can experiment with ideas and concepts without having to worry about polluting our production code until the experiment is ready to go

Build variable libraries

Rather than repeat values over and over in many different stylesheets, we can build a library with values of things that are not likely to change or that will repeat themselves multiple times at different levels.

Note that this is a suggested way of organizing SASS content, not the only one. Use whatever makes the most sense for you and your project

Take the following snippet of a variable library:

# Link Colors
$magenta: #FF00FF
$blue: #000011
$dark_grey: #eee

# Border Properties
# We have 3 different thickness 
$thin: 1 * 1px
$medium: $thin * 2px
$thick: $thin * 3px
$base_border_style: solid    
$border_color: $dark_grey

We can then use all the properties we defined in another round of mixins that will be used directly on our SASS stylesheets, like so:

@mixin solid-thin {
  border-width: $thin;
  border-style: solid;
  border-color: $border_color 
}

And finally use our solid-thin mixing wherever we need the same characteristics, like so:

blockquote {
  @include solid-thin;
}

So now if we ever need to change the vaues for any of our solid thin mixin, we only need to change them in one place and then recompile our SASS. The resulting CSS will pick the changes without having to worry if we got them everywhere… we know we did.

Keep your CSS DRY

A concept that is popular in nthe development community (I think it originated in Rails) is DRY, don’t repeat yourself. This is particularly dangerous in large development teams or large codebases.

Mixins with variable attribute values

(and default values when we need them)

Although this is not needed anymore (I believe all browsers now support border radius natively) this was the first time when I realized the power of mixing and how far we can really take them.

$radius: 5px !default;

@mixin border-radius($radius) {
  -webkit-border-radius: $radius;
     -moz-border-radius: $radius;
      -ms-border-radius: $radius;
       -o-border-radius: $radius;
          border-radius: $radius;
}

The code snipet above sets a variable for the default radius (5 pixels) and uses it when we don’t provide a value. These two declarations are the same:

.case1 {
  @include border-radius();
}

.case1 {
  @include border-radius(5px);
}

Extending our SASS

Don’t reinvent the wheel

I’m all for learning with your own code but there are times when it’s worth taking a look at what other people have done. There are several SASS-based frameworks available. The two I refer to the most are:

Useful Mixins and Tools for your own code

Better mediaqueries using @content

Mediaqueries are a pain in the ass. So much repetition and so error prone makes for cranky developers and cranky developers make things not fun for people around them.

In addition to bubbling media queries, we can use the @content variable to feed in the content that is specific to that media query.

// breakpoints defined in settings
$break-medium:  31em !default;
$break-large:   60em !default;
$break-x-large: 75em !default;          

@mixin breakpoint($type, $fallback:false, $parent:true) {

  @if $type == medium {
    @media (min-width: $break-medium) {
      @content;
    }
  }

  @if $type == large {
    @media (min-width: $break-large) {
      @content;
    }
  } 

  @if $type == x-large {
    @media (min-width: $break-x-large) {
      @content;
    }
  }

  @if $fallback {
    @if $parent {
      .#{$fallback} & {
        @content;
      }
    } @else {
      .#{$fallback} {
        @content;
      }
    }
  }
}

here are some uses for the mixing above:

.features__item {
  width: 100%;
}

.foo {
  color: red;
}

.bar {
  color: green;

  // use inside a declaration
  @include breakpoint(medium) {
    color: red;
  }

  @include breakpoint(large, lt-ie9) {
    color: blue;
  }
}

// use outside any declarations
@include breakpoint(medium) {
  .features__item {
    width: 50%;
  }

  .foo {
    color: blue;
  }
}

// remember to tell the fallback that 
// it's not within a declaration
@include breakpoint(large, lt-ie9, false) {
  .features__item {
    width: 25%;
  }

  .foo {
    color: green;
  }
}

and the resulting CSS:

features__item {
  width: 100%;
}

.foo {
  color: red;
}

.bar {
  color: green;
}

@media (min-width: 31em) {
  .bar {
    color: red;
  }
}

@media (min-width: 60em) {
  .bar {
    color: blue;
  }
}

.lt-ie9 .bar {
  color: blue;
}

@media (min-width: 31em) {
  .features__item {
    width: 50%;
  }

  .foo {
    color: blue;
  }
}

@media (min-width: 60em) {
  .features__item {
    width: 25%;
  }

  .foo {
    color: green;
  }
}

.lt-ie9 .features__item {
  width: 25%;
}

.lt-ie9 .foo {
  color: green;
}

Clearfix

@mixin clearfix() {
    &:before,
    &:after {
        content: "";
        display: table;
    }
    &:after {
        clear: both;
    }
}

Normalize.css

Vertical Rhythm

From: http://codepen.io/sturobson/pen/jFKlJ

Vertical Rhythm is simply when a body of text is aligned to evenly spaced horizontal lines (think of your lined paper from grade school), making it more cohesive and easier to read.

@mixin font-size($size, $keyword: null, $line-height:$doc-line-height) {
// note that the numeric font-size is required to allow the line-height to be generated correctly.

// the addition of the $keyword has been borrowed from this technique - http://seesparkbox.com/foundry/scss_rem_mixin_now_with_a_better_fallback

  @if $keyword{ 
    font-size: $keyword; 
  }
  @else {
    font-size: 0px + $size;
    font-size: $size / $doc-font-size +rem;
  } 
  // because you have to include the font size as a number for the keyword you can still get the line-height 
    
  line-height: round($line-height / $size*10000) / 10000;
  margin-bottom: 0px + $line-height;
  margin-bottom: ($line-height / $doc-font-size)+rem ;
}

Calculate REM size

One of the issues I find with using em as my sizing unit is that the values don’t remain constant; they are relative to the parent element.

CSS3 introduced a new unit for sizing: rem.

The em unit is relative to the font-size of the parent, which causes the compounding issue. The rem unit is relative to the root—or the html—element. That means that we can define a single font size on the html element and define all rem units to be a percentage of that.

html { font-size: 62.5%; /* =12px*/ } 
body { font-size: 1.4rem; } /* =14px */
h1   { font-size: 2.4rem; } /* =24px */

I’m defining a base font-size of 62.5% to have the convenience of sizing rems in a way that is similar to using px.

Code and idea originally from Stubornella

@function calculateRem($size) {
  $remSize: $size / 16px;
  @return #{$remSize}rem;
}
@mixin fontSize($size) {
  font-size: $size; //Fallback in px
  font-size: calculateRem($size);
}
h1 {
  @include fontSize(32px);
}

Becomes:

h1 {
  font-size: 32px;
  font-size: 2rem;
}

Build a grid with SASS

Programming-like functions and commands.

Please note that the material discussed below is not meant for day to day coding but more for larger projects where you’re building the infrastructure for other people to use. Hide as much of these details from your developers 🙂

SASS also allows you to create program-like funtionality that we can later include into our SASS files and then into our CSS. Let’s take a look at the example below:

@function cp($target, $container) {
  @return ($target / $container) * 100%;
}

It removes the need to run the same calculation every time we need to calculate an element’s width in relation to a container. Say we have a div we call nav that we want to be 650px width in a container that is 1000px wide; the sass declaration for this element’s width will look like this:

#nav {
  width: calc-percent(650px, 1000px);
}

and will produce the following CSS:

#nav {
  width: 65%;
}

Other control mechanisms

@if

The @if directive takes a condition to evaluate and returns the nested styles if the condition is truthy (not false or null).

p {
  @if 1 + 1 == 2 { border: 1px solid;  }
  @if 5 < 3      { border: 2px dotted; }
  @if null       { border: 3px double; }
}

Since only the first condition is true, the rule is compiled to:

p {
  border: 1px solid; 
}

Specifying what to return if the condition is falsey can be done using the @else statement. If the @if statement fails, the @else if statements are tried in order until one succeeds or the @else is reached. For example in the following SASS rule:

$type: monster;
p {
  @if $type == ocean {
    color: blue;
  } @else if $type == matador {
    color: red;
  } @else if $type == monster {
    color: green;
  } @else {
    color: black;
  }
}

the first else statement is true, so the rule resuls in:

p {
  color: green; 
}

@for

The @for directive iterates over it’s contents a set number of times passing a variable whose value increases for each iteration. For instance, if you find yourself repeating similar CSS you can save yourself a lot of manual work by using a for loop.

The directive has two forms: @for $var from <start> through <end> and @for $var from <start> to <end>. For the form from … through, the range includes the values of and , but the form from … to runs up to but not including the value of .

$var can be any variable name, like $i; <start> and <end> are SassScript expressions that should return integers.

@for $i from 1 through 3 {
  .item-#{$i} { width: 2em * $i; }
}

is compiled to:

.item-1 {
  width: 2em; }
.item-2 
  width: 4em; }
.item-3 {
  width: 6em; }

If you use the @for $var from <start> to <end> the result will be different. Fore example:

$columns: 4;

@for $i from 1 to $columns {
  .cols-#{$i} {
    width: ((100 / $columns) * $i) * 1%;
  }
}

This will only iterate 3 times instead of 4 so would not generate our final .cols-4 declaration in the example above.

@each

The @each directive takes the item from the list and outputs styles with the listed values

$people: Aragorn, Legolas, Gimli, Gandalf;

@each $name in $people {
  .icon-#{$name} {
    background-image: url(/images/icons/#{$name}.png);
  }
} 

compiles to:

.icon-Aragorn {
  background-image: url(/images/icons/Aragorn.png);
}

.icon-Legolas {
  background-image: url(/images/icons/Legolas.png);
}

.icon-Gimli {
  background-image: url(/images/icons/Gimli.png);
}

.icon-Gandalf {
  background-image: url(/images/icons/Gandalf.png);
}

@while

The @while statement will continually iterate and output it’s nested styles until it’s condition evaluates to false. This can be used to achieve more complex looping than the @for statement is capable of. For example:

$column: 4;

@while $column > 0 {
  .cols-#{$column} {
    width: 10px * $column;
  }
  $column: $column - 2;
}

This will only loop twice as we are subtracting 2 from the $column variable in each iteration so when it attempts to loop a third time, $column will not be greater than 0 and the output would be:

.cols-4 {
  width: 40px;
}

.cols-2 {
  width: 20px;
}