第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%); }