2016年11月1日火曜日

Sassの基本的な記述方法

記法の前に

Sass記法の前に、SassCSSの「完全な上位互換」と言えるので、CSSのルールはすべてそのまま利用することが出来ます。
その為、cssファイルをそのまま拡張子だけ .scssに変更して変換(コンパイル)し直すみたいな事も可能です。(圧縮できる程度のメリットしか有りませんが)

軽く余談ですが、このCSSとの完全な互換性が従来のSassには無かったのですが、現行のバージョンではそれが出来るので、余計な事を覚える必要がなく、Sassの機能を今までのCSSの知識にプラスアルファとして使えるんです。
これに寄ってハードルが下がり、学習コストも最低限で済むので非常に意味の有る事かなーと。

ただ、一部のCSSハックに関しては変換した際にエラーになってしまうので、その場合は別の方法で書く必要があります。
細かい部分まで把握できていませんが、引っかかる可能性が高いハックとしては次のような「/」を使ったIE6/7用のハックを使うとエラーになります。

view plaincopy to clipboardprint?

1.  .item {  

2.      /zoom1;  

3.  }  

/」が使えないので、この場合は「*」にすれば問題有りません。

view plaincopy to clipboardprint?

1.  .item {  

2.      *zoom1;  

3.  }  

いきなりちょっと不便っぽい部分が出てきましたが、Sassの素敵なトコの1つとしてエラーがちゃんと表示されることです。
その為、ScoutLogを見ると下記のように表示されます。

>>> Change detected to: style.scss
error style.scss (Line 12: Invalid CSS after ".item {": expected "}", was "/zoom: 1;")
overwrite style.css 

英語が出来なくても『style.scss 12行目でエラーが出てる!何か /zoom: 1; InvalidCSSっぽい!』って感じで分かるので、変にハマって時間を取られません。

/」以外にも単純な文法違反でもちゃんとエラーが返ります。
例えば、、、

view plaincopy to clipboardprint?

1.  .item {  

2.      width350px;  

3.  }s  

何か、} の後に s が残ってる!!!(きっと、Ctrl+SしたつもりでCtrlが押せてなかったんですね)とかでもちゃんとエラーになるので、ケアレスミスが原因で時間を取られてしまう事が減ると思います。
記事書いてて思いましたけど、これって結構ステキですね。

互換性の話だったのに、気付けばエラー処理の話になってしまいましたが、こんな感じで今のCSS知識はそのまま使うことが出来ます。


Sassの基本的な記法

ルールのネスト - Nested Rules

何はともあれコレだけはマスターしておきたい記法です。
基本的な機能の中でもダントツで利用するのがネストで、入れ子でスタイルを書いていく事が可能です。

いつものCSS

view plaincopy to clipboardprint?

1.  #main {  

2.      width600px;  

3.  }  

4.  #main p {  

5.      margin-bottom1.5em;  

6.  }  

いつもはこんな感じですよね?
これを、Sass記法のネストを使うと、、、

Sass

view plaincopy to clipboardprint?

1.  #main {  

2.      width600px;  

3.      p {  

4.          margin-bottom1.5em;  

5.      }  

6.  }  

と、書くことが可能です。
上記は一番シンプルな例ですが、多少入れ子が多い例も上げてみます。

いつものCSS

view plaincopy to clipboardprint?

1.  #header {  

2.      width940px;  

3.  }  

4.  #header h1 {  

5.      floatleft;  

6.  }  

7.  #header ul#nav {  

8.      height50px;  

9.  }  

10. #header ul#nav li {  

11.     floatleft;  

12. }  

13. #header ul#nav li a {  

14.     floatleft;  

15.     width80px;  

16. }  

ヘッダーっぽい部分を例にしてみました。
これを、Sass記法のネストを使うと、、、

Sass

view plaincopy to clipboardprint?

1.  #header {  

2.      width940px;  

3.      h1 {  

4.          floatleft;  

5.      }  

6.      ul#nav {  

7.          height50px;  

8.          li {  

9.              floatleft;  

10.             a {  

11.                 floatleft;  

12.                 width80px;  

13.             }  

14.         }  

15.     }  

16. }  

こんな風に書くことが出来ます。
これを保存して変換するといつものCSSと同じ感じにしてくれます。

ちなみに、インデントは無くても大丈夫です。この辺りは可読性が良いと思う方法で書いてもらえれば。

これだけでもコピペから解放され、単純に記述量も減っているのが分かると思いますが、このネストのメリットはメンテナンス性の部分でもかなり力を発揮します。

例えば、上記の #header #globalHeader に変更する必要が出たとします。
この際に、いつものCSSでは #header から始まる全てを変更なり置換なりをしないと行けませんが、ネストを利用して書いている場合、最初の #header を変更するだけでOKです。

これにより、IDやクラス名が違う別の案件へのコピペも楽になり、再利用性が向上しますよね。

ネストには、プロパティやmedia queriesでも使うこと出来たりするんですが、その辺りの詳細は後のエントリーで書く予定です(ちゃんと書けよ自分)。

& 親セレクタの参照 - Referencing Parent Selectors

セレクタに「&」を使うことでネストしている際の親セレクタの参照が可能です。

Sass

view plaincopy to clipboardprint?

1.  a {  

2.      font-weightbold;  

3.      &:hover {  

4.          colorred;  

5.      }  

6.  }  

& が親セレクタを参照するので、&:hover a:hover としたのと同じ扱いですね。
これを、変換すると次のようになります。

変換されたCSS

view plaincopy to clipboardprint?

1.  a {  

2.      font-weightbold;  

3.  }  

4.  a:hover {  

5.      colorred;  

6.  }  

変換されたCSSは、実際に変換されたCSSとは違う可能性が有ります(これ以降のも同様に)。

この例だと殆ど利点が分かりませんが、これの最たる例がCSSシグネチャとして利用したい場合かと思います。

例えば、トップページだけ色が変わってる場合なんかに、body要素に指定したclassIDでスタイルを振り分けることが有ると思います。

いつものCSS

view plaincopy to clipboardprint?

1.  #sub {  

2.      floatright;  

3.      width200px;  

4.      background#ccc;  

5.  }  

6.  .body-top #sub {  

7.      background#fff;  

8.  }  

いつものだと、こんな風にしますよね。
Sass
のネストを使って書いていると、部分的にスタイルを振り分けるのにネストされた中だと親は参照できないので、そう言った場合に「&」を利用します。

Sass

view plaincopy to clipboardprint?

1.  #sub {  

2.      floatright;  

3.      width200px;  

4.      background#ccc;  

5.      .body-top & {  

6.          background#fff;  

7.      }  

8.  }  

こんな感じで、&を使うことでネストされた状態でも親セレクタを参照できます。
この程度の例なら、ネストしないで外に書けば良いんですが、ネストされた状態が長くなると、記述する位置がだいぶ変わってしまい分かりにくくなるので、そんな場合に使っていけます。

コメント - Comments: /* */ and //

CSSのコメントは /* */ で囲みますが、Sassだと通常のコメントに加え、// による1行コメントが可能です。

Sass

view plaincopy to clipboardprint?

1.  //メインコンテンツ  

2.  #main {  

3.      width600px;  

4.      // p要素  

5.      p {  

6.          margin-bottom1.5em;  

7.      }  

8.      // ul要素  

9.      ul {  

10.         margin0 0 1.5em 20px;  

11.         li {  

12.             margin-bottom5px;  

13.         }  

14.     }  

15. }  

JSとかちょっとでも触れてれば、1行コメントは馴染みが有ると思うので詳しい説明は不要かと思いますが、変換した際に1行コメントに関しては削除され、いつものCSSによるコメントは変換しても基本的に残ります。

変数 - Variables

変数と聞くと、軽くプログラムアレルギーが出る人も居るかも知れませんが、ちょっと使うだけならとても便利な機能なのでこれもぜひ覚えましょう。

変数は、任意の名前を付けて、任意の場所で呼び出したりすることが出来る機能です。

Sass

view plaincopy to clipboardprint?

1.  $yokohaba: 250px;  

こんな風に変数を定義しておけば、任意の場所で変数の値を呼び出すことが出来ます。
変数の名前は$から始め、その後は、いつものCSSと似た感じで「:」で区切ってから値を指定します。

Sass

view plaincopy to clipboardprint?

1.  #sub {  

2.      width: $yokohaba;  

3.      ul.bnrList {  

4.          width: $yokohaba;  

5.      }  

6.  }  

定義した変数を、値の部分に入れることで呼び出されます。
これを変換すると次のようになります。

変換されたCSS

view plaincopy to clipboardprint?

1.  #sub {  

2.      width250px;  

3.  }  

4.  #sub ul.bnrList {  

5.      width250px;  

6.  }  

変数を上手く利用することで、重複したスタイルを何度も書く必要が無く、値とかも間違えたりしなくなります。

ちなみに、変数はファイルの最初の方にまとめておいたり別ファイルに記述しておくと見通しが良くメンテナンス性が向上するかと思います。

他の例として、基本のフォントカラーやリンクカラーを予め指定しておけば良い感じです。また、変数の値にはマルチバイト文字も使えるのでfont-familyの指定とかも可能です。

Sass

view plaincopy to clipboardprint?

1.  // ベースフォント  

2.  $base_font: "メイリオ""Meiryo"verdana"ヒラギノ角ゴ Pro W3""Hiragino Kaku Gothic Pro", Osaka, "MS Pゴシック""MS PGothic", Sans-Serif;  

3.     

4.  // ベーステキストカラー  

5.  $font_color: #333;  

6.     

7.  // ベースリンクカラー  

8.  $link_color: #06f;  

9.  $link_color_hover: #00f;  

10.    

11.    

12. body {  

13.     color: $font_color;  

14.     font-family: $base_font;  

15. }  

16. #main {  

17.     a:link {  

18.         color: $link_color;  

19.     }  

20.     a:hover {  

21.         color: $link_color_hover;  

22.     }  

23. }  

これを、変換すると次のような感じになります。

変換されたCSS

view plaincopy to clipboardprint?

1.  body {  

2.      color#333333;  

3.      font-family"メイリオ""Meiryo"verdana"ヒラギノ角ゴ Pro W3""Hiragino Kaku Gothic Pro", Osaka, "MS Pゴシック""MS PGothic", Sans-Serif;  

4.  }  

5.  #main a:link {  

6.      color#0066ff;  

7.  }  

8.  #main a:hover {  

9.      colorblue;  

10. }  

この例だけだと、記述する量が増えてるのでアレですが、#main以外にも#footerで同じ色を使いたいとかそんな時に値を覚えてる必要が無いので、微妙に色を間違えるとかが無くなって統一性が出しやすくなったりします。

この他にも変数には、便利な使い方が多くありますが、その辺りの詳細は後のエントリーで書く予定です(ちゃんと書けよ自分)。

演算

Sassでは、足したり引いたりって言う演算が出来ます。
この演算がかなり頭が良いので非常に素晴らしいのですが、複雑なことは抜きにしてココではカンタンで実用性が高そうな例を。

Sass

view plaincopy to clipboardprint?

1.  .item {  

2.      width300px - 14px;  

3.      padding7px;  

4.  }  

こんな風に書けます。これを変換すると、、、

変換されたCSS

view plaincopy to clipboardprint?

1.  .item {  

2.      width286px;  

3.      padding7px;  

4.  }  

こうなるんです!もう電卓から解放される!!
ボクみたいに暗算が苦手な人からすると、これヤバイ。
box-sizing: border-box;
が使えれば、paddingの計算とか不要ですけど、あのブラウザに対応させるには、こんなプロパティは使えないですからね...

ちなみに、単位は省略してもよしなにやってくれるので「14」と書いても同じ結果が返ってきます。
単位の省略に加えこんな風にすることも。

Sass

view plaincopy to clipboardprint?

1.  .item {  

2.      width300px - (7 * 2) - 2;  

3.      padding7px;  

4.      border1px solid #666;  

5.  }  

お前どんだけ計算したくないんだよ!って感じもしますが、感覚的にはあくまでも横幅は300pxなんだよ!!と思うわけです。ボクは。
これを変換すると期待した通り次のようになります。

変換されたCSS

view plaincopy to clipboardprint?

1.  .item {  

2.      width284px;  

3.      padding7px;  

4.      border1px solid #666;  

5.  }  

ミックスイン - Mixins

ミックスインは、プロパティやセレクタをまとめてワンセットにしておく事が可能で、それらをカンタンにインクルード(読み込む)する事が出来ます。
変数の機能を強化したと言うか便利にしたようなイメージです。

Sass

view plaincopy to clipboardprint?

1.  @mixin inline_block {  

2.      display: inline-block;  

3.      *displayinline;  

4.      *zoom1;  

5.  }  

@mixinの後に半角スペース、任意の名前って感じで定義します。

この例では、display: inline-block; IE でも使う場合に、 *display: inline; *zoom: 1; を指定する必要があります。
これを毎回書くと面倒なので、ミックスインを使って予め定義しておくことで、次のように1行書くだけでインクルード出来ます。

Sass

view plaincopy to clipboardprint?

1.  .sampleBox {  

2.      @include inline_block;  

3.      background#eee;  

4.  }  

@includeの後に半角スペース、ミックスインで定義した名前って感じで記述します。
当然、他の宣言と一緒に書くことが可能です。
これを変換すると、、、

変換されたCSS

view plaincopy to clipboardprint?

1.  .sampleBox {  

2.      display: inline-block;  

3.      *displayinline;  

4.      *zoom1;  

5.      background#eee;  

6.  }  

無事にインクルードされ、展開されました。
こんな感じで、何度も使うようなスタイルや長めの宣言を予め定義してインクルード出来るので、かなりの工数削減になると思います。
特にCSS3使ってて、ベンダープレフィックスが多い場合とか。

このミックスインもかなり強力な機能なので、がっつりやり出すとかなり覚えたりやることが多いですが、いきなり複雑な事はせずに、この宣言何度も書いてるなーと思ったらミックスインで定義しておく位が最初は良いのかなと。

ちなみに、この inline-block程度ならミックスインではなく次に説明する セレクタを継承出来る @extend を使った方が良いかもです。

セレクタの継承 - Selector Inheritance@extend

@extend は、一度使ったセレクタを継承して使うことが出来ます。
ミックスインと似てる部分も多いのですが、似て非なるものって感じで用途がだいぶ変わってきます。
文だと伝わる気がしないので、例を見てください。

Sass

view plaincopy to clipboardprint?

1.  .imgR {  

2.      floatright;  

3.      margin-left10px;  

4.      margin-bottom1.5em;  

5.  }  

これだけ見ても、いつものCSSと何ら変わりは有りませんが、この一度使ったセレクタを使うことが出来ます。

Sass

view plaincopy to clipboardprint?

1.  .photo {  

2.      @extend .imgR;  

3.  }  

と書くことで .imgR で指定した宣言が .photo でも継承されます。
これを変換すると、、、

変換されたCSS

view plaincopy to clipboardprint?

1.  .imgR, .photo {  

2.      floatright;  

3.      margin-left10px;  

4.      margin-bottom1.5em;  

5.  }  

こんな感じで変換されるので、clearfix等のように一度使ったセレクタを再利用したい場合に便利な機能です。

ちなみに、clearfix @extend で利用する場合はこんな感じです。

Sass

view plaincopy to clipboardprint?

1.  .clearfix {  

2.      *zoom1;  

3.      &:after {  

4.          content".";  

5.          displayblock;  

6.          clearboth;  

7.          height0;  

8.          visibilityhidden;  

9.      }  

10. }  

11.    

12. ul.menu {  

13.     @extend .clearfix;  

14.     background#ccc;  

15.     li {  

16.         floatleft;  

17.         width100px;  

18.     }  

19. }  

変換されたCSS

view plaincopy to clipboardprint?

1.  .clearfix, ul.menu {  

2.      *zoom1;  

3.  }  

4.  .clearfix:after, ul.menu:after {  

5.      content".";  

6.      displayblock;  

7.      clearboth;  

8.      height0;  

9.      visibilityhidden;  

10. }  

11.    

12. ul.menu {  

13.     background#ccc;  

14. }  

15. ul.menu li {  

16.     floatleft;  

17.     width100px;  

18. }  

clearfixから話を戻して。
また次のように、スタイルを上書きしたい場合も有ると思います。

Sass

view plaincopy to clipboardprint?

1.  .imgR {  

2.      floatright;  

3.      margin-left10px;  

4.      margin-bottom1.5em;  

5.  }  

6.  .photo {  

7.      @extend .imgR;  

8.      margin-left5px;  

9.  }  

この様な場合は、次のようにちゃんと分けて変換してくれます。

変換されたCSS

view plaincopy to clipboardprint?

1.  .imgR, .photo {  

2.      floatright;  

3.      margin-left10px;  

4.      margin-bottom1.5em;  

5.  }  

6.  .photo {  

7.      margin-left5px;  

8.  }  

部分的に、スタイルを上書きしたい場合も問題ないですね。
こんな感じで便利な @extend ですが、現状だと単独のセレクタしか使うことしか出来ません。
よく分からない説明ですが、次の場合はエラーになっちゃいます。

Sass(エラー)

view plaincopy to clipboardprint?

1.  .item .imgR {  

2.      floatright;  

3.      margin-left10px;  

4.      margin-bottom1.5em;  

5.  }  

6.  .photo {  

7.      @extend .item .imgR;  

8.  }  

子孫セレクタとかセレクタを組み合わせるとダメって事ですね。
これは、将来的に対応されるのかな。

@extend は使い方に寄ってはミックスインでも何ら問題が無いのですが、大きな違いとして、ミックスインはインクルードする度に展開され、@extend はグループ化されて変換されます。
なので、例えばclearfixをミックスインで定義して、複数ヶ所でインクルードするとその数だけ宣言が増えていきますが、@extend だとグループ化されるのでより合理的なCSSになります。

0 件のコメント:

コメントを投稿