第5章 現場で使える実践Sassコーディング

5-3 レイアウト・パーツで使える

clearfix を @extend で活用する

$supportIE: true; // IE非対応の場合 false

.clearfix {
	@if $supportIE {
		*zoom: 1;
	}
	&:after {
		content: "";
		display: table;
		clear: both;
	}
}
.item {
	@extend .clearfix;
	background: #eee;
	.image {
		float: left;
		height: 100px;
	}
	.text {
		float: left;
	}
}
.clearfix, .item {
  *zoom: 1;
}
.clearfix:after, .item:after {
  content: "";
  display: table;
  clear: both;
}

.item {
  background: #eee;
}
.item .image {
  float: left;
  height: 100px;
}
.item .text {
  float: left;
}

@function を使って px 指定する感覚でフォントサイズを % 指定する

//フォントサイズのリスト
$fontSizeList: 62%, 70%, 77%, 85%, 93%, 100%, 108%, 116%, 123.1%, 131%, 138.5%, 146.5%, 153.9%, 161.6%, 167%, 174%, 182%, 189%, 197%, 205%, 213%, 220%, 227%, 235%, 243%, 250%, 258%, 265%, 272%, 280%, 288%, 295%, 302%;

//指定したフォントサイズに該当する%を返す関数
@function fz($size) {
    @if $size < 8 {
        $size: 8;
    }
    @if $size > 40 {
        $size: 40;
    }
    @return nth($fontSizeList, $size - 7);
}
article {
	font-size: fz(16);
}
article {
  font-size: 123.1%;
}

変数を使って YUI の CSS Fonts を管理する

$fz_10: 77%;
$fz_11: 85%;
$fz_12: 93%;
$fz_13: 100%;
$fz_14: 108%;
$fz_15: 116%;
$fz_16: 123.1%;
$fz_17: 131%;
$fz_18: 138.5%;
$fz_19: 146.5%;
$fz_20: 153.9%;
$fz_21: 161.6%;
$fz_22: 167%;
$fz_23: 174%;
$fz_24: 182%;
$fz_25: 189%;
$fz_26: 197%;
#main {
	font-size: $fz_15;
}
#main {
  font-size: 116%;
}

変数を使って、サイドバーの幅を自動的に計算する

// 全体の幅
$wrap_width: 960px;

// メインエリアの幅
$main_width: 640px;

// サイドバーの幅
$side_width: $wrap_width - $main_width - 20;


#contents {
	float: left;
	width: $wrap_width;
}
#main {
	float: left;
	width: $main_width;
}
#side {
	float: right;
	width: $side_width;
}
#contents {
  float: left;
  width: 960px;
}
#main {
  float: left;
  width: 640px;
}
#side {
  float: right;
  width: 300px;
}
#side {
  float: right;
  width: 294px;
}

null でカンタンに条件分岐をしてレイアウトをする

$height: false;
.item {
	width: 500px;
	@if $height {
		height: $height;
	}
}
.item {
  width: 500px;
}
// 高さが必要な場合は値を単位付きで。不要な場合はnull。
$height: null;
.item {
	width: 500px;
	height: $height;
}
.item {
  width: 500px;
}
@mixin itemBox ($width, $height, $margin:null, $padding:null) {
	width: $width;
	height: $height;
	margin: $margin;
	padding: $padding;
}

.itemA {
	// 不要なプロパティはnull。
	@include itemBox(100px, null, 10px, 20px);
}
.itemB {
	@include itemBox(null, auto, 20px auto);
}
.itemA {
  width: 100px;
  margin: 10px;
  padding: 20px;
}

.itemB {
  height: auto;
  margin: 20px auto;
}
$duration: null;
a {
	transition: all $duration linear;
}
a {
  transition: all linear;
}

calcを使って全体の横幅からボーダーの横幅をカンタンに計算する

.item {
	width: calc(100% - 1px * 2);
}
.item {
  width: calc(100% - 1px * 2);
}
$border: 1px;
.item {
	width: calc(100% - $border * 2);
}
.item {
  width: calc(100% - $border * 2);
}
$border: 1px;
.item {
	width: calc(100% - #{$border} * 2);
}
.item {
  width: calc(100% - 1px * 2);
}
$border: 100px - 1px * 2;
.item {
	width: calc(#{$border});
}
.item {
  width: calc(98px);
}
$border: "100px - 1px * 2";
.item {
	width: calc(#{$border});
}
.item {
  width: calc(100px - 1px * 2);
}

@for を使って余白調整用のclassを生成する

$spaceClass: true !default;
$spacePadding: false !default;
$endValue: 10 !default;

@if $spaceClass {
	@for $i from 0 through $endValue {
		.mt#{$i * 5} {
			margin-top: 5px * $i !important;
		}
		.mb#{$i * 5} {
			margin-bottom: 5px * $i !important;
		}
		@if $spacePadding {
			.pt#{$i * 5} {
				padding-top: 5px * $i !important;
			}
			.pb#{$i * 5} {
				padding-bottom: 5px * $i !important;
			}
		}
	}
}
.mt0 {
  margin-top: 0px !important;
}
.mb0 {
  margin-bottom: 0px !important;
}
.mt5 {
  margin-top: 5px !important;
}
.mb5 {
  margin-bottom: 5px !important;
}

...(略)...

.mt50 {
  margin-top: 50px !important;
}
.mb50 {
  margin-bottom: 50px !important;
}

リストマーカー用の連番を使ったclass名を作成する

%markBase {
	padding-left: 15px;
	background-position: 0em .5em;
	background-repeat: no-repeat;
}

@for $i from 1 through 3 {
	.mark_#{$i} {
		@extend %markBase;
		background-image: url(../img/mark_#{$i}.png);
	}
}
.mark_1, .mark_2, .mark_3 {
  padding-left: 15px;
  background-position: 0em .5em;
  background-repeat: no-repeat;
}

.mark_1 {
  background-image: url(../img/mark_1.png);
}
.mark_2 {
  background-image: url(../img/mark_2.png);
}
.mark_3 {
  background-image: url(../img/mark_3.png);
}

連番を使ったclass名のゼロパディング(0埋め)をする

$tmp: "";
@for $i from 1 through 15 {
	@if $i < 10 {
		$tmp: "0#{$i}";
	} @else {
		$tmp: $i;
	}
	.mark_#{$tmp} {
		background-image: url(../img/mark_#{$tmp}.png);
	}
}
.mark_01 {
  background-image: url(../img/mark_01.png);
}

.mark_02 {
  background-image: url(../img/mark_02.png);
}

...(略)...

.mark_14 {
  background-image: url(../img/mark_14.png);
}

.mark_15 {
  background-image: url(../img/mark_15.png);
}

変数と演算で opacity を使った簡易ロールオーバーを作成する

%opacity {
	$opacityValue: .7 !default;
	opacity: $opacityValue;
	-ms-filter: "alpha(opacity=#{$opacityValue * 100})";
	filter: alpha(opacity=#{$opacityValue * 100});
}

p.btn a:hover img {
	@extend %opacity;
}
p.btn a:hover img {
  opacity: 0.7;
  -ms-filter: "alpha(opacity=70)";
  filter: alpha(opacity=70);
}

グローバルナビゲーションのCSSスプライトを作成する

<header class="global">
	<h1><a href="/">Web制作者のためのSass入門(仮) 公式サポートサイト</a></h1>
	<p class="description">~ これからのWeb制作の現場で活用するCSSメタ言語 ~</p>
	<nav>
		<ul>
			<li><a href="/">トップ</a></li>
			<li><a href="/about/">書籍について</a></li>
			<li><a href="/source/">サンプルソース</a></li>
			<li><a href="/dl/">ダウンロード</a></li>
			<li><a href="/profile/">著者プロフィール</a></li>
			<li><a href="/contact/">お問い合わせ</a></li>
		</ul>
	</nav>
</header>
/* グローバルナビゲーション */
header.global nav {
	margin: 0 0 50px;
	ul {
		overflow: hidden;
		margin: 0;
		padding: 0;
		li {
			list-style: none;
			float: left;
			width: 160px;
			a {
				display: block;
				height: 50px;
				text-indent: 100%;
				white-space: nowrap;
				overflow: hidden;
				background: url(../img/nav.png) no-repeat left top;
				&:hover {
					background-position: 0 -50px;
				}
			}
		}
	}
}
header.global nav {
	// スライドさせる距離
	$pos-x: -160px;
	
	margin: 0 0 50px;
	ul {
		overflow: hidden;
		margin: 0;
		padding: 0;
		li {
			list-style: none;
			float: left;
			// 絶対値を返すabs() 関数を使って - を + に
			width: abs($pos-x);
			a {
				display: block;
				height: 50px;
				text-indent: 100%;
				white-space: nowrap;
				overflow: hidden;
				background: url(../img/nav.png) no-repeat left top;
				&:hover {
					background-position: 0 -50px;
				}
				&[href^="/about/"] {
					background-position: $pos-x 0;
					&:hover {
						background-position: $pos-x -50px;
					}
				}
				&[href^="/source/"] {
					background-position: $pos-x * 2 0;
					&:hover {
						background-position: $pos-x * 2 -50px;
					}
				}
				&[href^="/dl/"] {
					background-position: $pos-x * 3 0;
					&:hover {
						background-position: $pos-x * 3 -50px;
					}
				}
				&[href^="/profile/"] {
					background-position: $pos-x * 4 0;
					&:hover {
						background-position: $pos-x * 4 -50px;
					}
				}
				&[href^="/contact/"] {
					background-position: $pos-x * 5 0;
					&:hover {
						background-position: $pos-x * 5 -50px;
					}
				}
			}
		}
	}
}
header.global nav {
	// 各コンテンツのリスト
	$navList: about, source, dl, profile, contact;
	// スライドさせる距離
	$pos-x: -160px;

	margin: 0 0 50px;
	ul {
		overflow: hidden;
		margin: 0;
		padding: 0;
		li {
			list-style: none;
			float: left;
			width: abs($pos-x);
			a {
				display: block;
				height: 50px;
				text-indent: 100%;
				white-space: nowrap;
				overflow: hidden;
				background: url(../img/nav.png) no-repeat left top;
				&:hover {
					background-position: 0 -50px;
				}
			}
			@for $i from 1 through length($navList) {
				a[href^="/#{nth($navList, $i)}/"] {
					background-position: $i * $pos-x 0;
					&:hover {
						background-position: $i * $pos-x -50px;
					}
				}
			}
		}
	}
}
/* グローバルナビゲーション */
header.global nav {
  margin: 0 0 50px;
}
header.global nav ul {
  overflow: hidden;
  margin: 0;
  padding: 0;
}
header.global nav ul li {
  list-style: none;
  float: left;
  width: 160px;
}
header.global nav ul li a {
  display: block;
  height: 50px;
  text-indent: 100%;
  white-space: nowrap;
  overflow: hidden;
  background: url(../img/nav.png) no-repeat left top;
}
header.global nav ul li a:hover {
  background-position: 0 -50px;
}
header.global nav ul li a[href^="/about/"] {
  background-position: -160px 0;
}
header.global nav ul li a[href^="/about/"]:hover {
  background-position: -160px -50px;
}
header.global nav ul li a[href^="/source/"] {
  background-position: -320px 0;
}
header.global nav ul li a[href^="/source/"]:hover {
  background-position: -320px -50px;
}
header.global nav ul li a[href^="/dl/"] {
  background-position: -480px 0;
}
header.global nav ul li a[href^="/dl/"]:hover {
  background-position: -480px -50px;
}
header.global nav ul li a[href^="/profile/"] {
  background-position: -640px 0;
}
header.global nav ul li a[href^="/profile/"]:hover {
  background-position: -640px -50px;
}
header.global nav ul li a[href^="/contact/"] {
  background-position: -800px 0;
}
header.global nav ul li a[href^="/contact/"]:hover {
  background-position: -800px -50px;
}

文字リンクカラーのミックスインを作る

@mixin link-color($normal, $hover) {
	color: $normal;
	&:hover { 
		color: $hover;
		text-decoration: none;
	}
}

a {
  @include link-color(#f00, #00f);
}
a {
  color: red;
}
a:hover {
  color: blue;
  text-decoration: none;  
}
$normal: #f00;
$hover: #00f;
@mixin link-color($n:$normal, $h:$hover) {
	color: $n;
	&:hover { 
		color: $h;
		text-decoration: none;
	}
}

a {
  @include link-color;
}
a {
  color: red;
}
a:hover {
  color: blue;
  text-decoration: none;
}
@mixin link-color2($n) {
	color: $n;
	&:hover { 
		color: lighten($n, 30%);
		text-decoration: none;
	}
}

a {
  @include link-color2(#f00);
}
a {
  color: red;
}
a:hover {
  color: #ff9999;
  text-decoration: none;
}

複数の値を@eachでループし、ページによって背景を変更する

$setBG: top, about, company, contact;

@each $i in $setBG {
	.body-#{$i} {
		background-image: url(../img/bg_#{$i}.png);
	}
}
.body-top {
  background-image: url(../img/bg_top.png);
}
.body-about {
  background-image: url(../img/bg_about.png);
}
.body-company {
  background-image: url(../img/bg_company.png);
}
.body-contact {
  background-image: url(../img/bg_contact.png);
}
$setBG: top red, about blue, company green, contact yellow;
@each $i in $setBG {
	.body-#{nth($i, 1)} {
		background-image: url(../img/bg_#{nth($i, 2)}.png);
	}
}
.body-top {
  background-image: url(../img/bg_red.png);
}

.body-about {
  background-image: url(../img/bg_blue.png);
}

.body-company {
  background-image: url(../img/bg_green.png);
}

.body-contact {
  background-image: url(../img/bg_yellow.png);
}
$setBG: (top red)(about blue)(company green)(contact yellow);
$setBG: (top,red)(about,blue)(company,green)(contact,yellow);
$setBG: ((top)(red))((about)(blue))((company)(green))((contact)(yellow));

シンプルなグラデーションのミックスインを作る

@mixin linear-gradient($color:#f00, $way:top, $percent:20%) {
	background-color: $color;
	background-image: -webkit-linear-gradient($way, $color 0%, lighten($color, $percent) 100%);
	background-image: -moz-linear-gradient($way, $color 0%, lighten($color, $percent) 100%);
	background-image: linear-gradient($way, $color 0%, lighten($color, $percent) 100%);
}
.item {
	@include linear-gradient;
}
.item {
  background-color: red;
  background-image: -webkit-linear-gradient(top, red 0%, #ff6666 100%);
  background-image: -moz-linear-gradient(top, red 0%, #ff6666 100%);
  background-image: linear-gradient(top, red 0%, #ff6666 100%);
}
.item {
	@include linear-gradient(#999, left, 50%);
}
.item {
  background-color: #666666;
  background-image: -webkit-linear-gradient(left, #666666 0%, #e6e6e6 100%);
  background-image: -moz-linear-gradient(left, #666666 0%, #e6e6e6 100%);
  background-image: linear-gradient(left, #666666 0%, #e6e6e6 100%);
}

【追記】「to」を使った新しい構文の場合、
グラデーションの開始位置と終了位置を指定しましょう。

@mixin linear-gradient($color:#f00, $start:top, $end:bottom, $percent:20%) {
	background-color: $color;
	background-image: -webkit-linear-gradient($start, $color 0%, lighten($color, $percent) 100%);
	background-image: -moz-linear-gradient($start, $color 0%, lighten($color, $percent) 100%);
	background-image: linear-gradient(to $end, $color 0%, lighten($color, $percent) 100%);
}
.item {
	@include linear-gradient;
}
.item {
  background-color: red;
  background-image: -webkit-linear-gradient(top, red 0%, #ff6666 100%);
  background-image: -moz-linear-gradient(top, red 0%, #ff6666 100%);
  background-image: linear-gradient(to bottom, red 0%, #ff6666 100%);
}