Skip to content

Instantly share code, notes, and snippets.

@azusa-tomita
Created November 26, 2012 06:11
Show Gist options
  • Save azusa-tomita/4146804 to your computer and use it in GitHub Desktop.
Save azusa-tomita/4146804 to your computer and use it in GitHub Desktop.
compass ベンダープリフィックス

compassのベンダープリフィックス

CSS3関連のmixinはなにをしてるか

box-sizingを例で見てみる。

http://compass-style.org/reference/compass/css3/box_sizing/

リンク先のview sorceをクリックすると、内容を見ることができる。

@mixin box-sizing($bs) {
  $bs: unquote($bs);
  @include experimental(box-sizing, $bs, -moz, -webkit, not -o, not -ms, not -khtml, official); } 

unquote()で引数の値からクォートを外したあと、プロパティ名、プロパティの値(=引数の値)、ベンダープリフィックスの有無といった内容を、box-sizingからexperimentalというミックスインに渡している。

experimentalはなにをしているか

http://compass-style.org/reference/compass/css3/shared/

@mixin experimental($property, $value, $moz: $experimental-support-for-mozilla, $webkit: $experimental-support-for-webkit, $o: $experimental-support-for-opera, $ms: $experimental-support-for-microsoft, $khtml: $experimental-support-for-khtml, $official: true) {
  @if $webkit and $experimental-support-for-webkit {
    -webkit-#{$property}: $value; }
  @if $khtml and $experimental-support-for-khtml {
    -khtml-#{$property}: $value; }
  @if $moz and $experimental-support-for-mozilla {
    -moz-#{$property}: $value; }
  @if $ms and $experimental-support-for-microsoft {
    -ms-#{$property}: $value; }
  @if $o and $experimental-support-for-opera {
    -o-#{$property}: $value; }
  @if $official {
    #{$property}: $value; } }

ズラズラと読みづらい。

まずは引数部分を見てみる。
↓改行して見やすくしてみた。

experimental(
  $property, 
  $value, 
  $moz: $experimental-support-for-mozilla, 
  省略
) {

experimentalの3番目の引数である$mozには、初期値として$experimental-support-for-mozillaが設定されている。

3番目の引数か、$moz:**が存在しない場合はこの変数の値が有効になるが、 box-sizingのミックスインからは、3番目の引数として-mozが渡されている。

  @include experimental(
    box-sizing,
    $bs,
    -moz, //← $moz
    -webkit,
    not -o,
    not -ms,
    not -khtml,
    official);

experimentalに渡された$moz:-moz;は、プロパティの表示/非表示を指定している条件文で使われる。

  @if $moz and $experimental-support-for-mozilla {
    -moz-#{$property}: $value; }

$mozと、$experimental-support-for-mozillaの両方が真の場合のみ、ベンダープリフィックス付きの値をCSSで出力されるようになっている。

前述のとおり、$mozにはbox-sizingから渡された-mozが入っている。
@ifの条件式に文字列が指定されていると真となるので、$mozは真。

次に$experimental-support-for-mozillaに定義された値を確認する。
compassで使われているサポート系の変数のデフォルト値は以下から確認できる。

http://compass-style.org/help/tutorials/exclude_vendor_prefixes/

実際のソースでは以下のようになっている。

https://github.com/chriseppstein/compass/blob/stable/frameworks/compass/stylesheets/compass/_support.scss

$experimental-support-for-mozillaを見てみると

$experimental-support-for-mozilla      : true !default;

trueが宣言されている。

以上により、@ifの条件式である$moz$experimental-support-for-mozillaはどちらも真、 条件式全体も真であると判断され、

-moz-#{$property}: $value;

がCSSに出力される。

以上が、includeからベンダープレフィクス出力までの挙動である。

プロパティが出力されないケースの挙動

experimentalに"not **"が渡された場合

以下は、box-sizingの引数。

  @include experimental(
    box-sizing,
    $bs,
    -moz,
    -webkit,
    not -o,    // ← $o
    not -ms,
    not -khtml,
    official);

このうちの5番目の引数($oに渡す引数)のように、experimentalnot **が渡されるケースがある。
引数はそのまま次条件文に入るため、experimentalでは次のようになる。

  @if $o and $experimental-support-for-opera {
    -o-#{$property}: $value; }

  @if not -o and $experimental-support-for-opera {
    -o-#{$property}: $value; }

@if $o@if not -oとなり、notによって文字列-oの真偽値が反転して偽となる。
結果条件式全体も偽となって、プロパティは出力されなくなる。

このケースはcompassのcss3関連のミックスインの定義によるため、ユーザ側が意識することはない。
どうしても変えたい場合は、compass内のmixinファイルを書き換えるか、
同じ内容のmixinを、compassより"あと"に再定義してcompassのmixinを上書きする必要がある。

$experimental-supportに"flase"が渡された場合

プロパティが出力されないもう一つのケースは、
$experimental-support変数が偽の場合。
$experimental-support変数は次のように@import宣言前に宣言しておくことで、デフォルト値を上書きできる。

$experimental-support-for-opera:false;
@import "compass";

変数がflaseとなることで、

  @if $o and $experimental-support-for-opera {
    -o-#{$property}: $value; }

このif文の条件式は偽となって、プロパティは出力されなくなる。

こちらは、ユーザが簡単に制御することができる方法だが、
全プロパティで出力されなくなる。

まとめ

デフォルトの出力はcommpassのcss3系のミックスインの初期値によって決められている。
例えばbackground_sizeは、msは出力しない設定になっている。
http://compass-style.org/reference/compass/css3/background_size/

デフォルトの出力が知りたい場合はjsdoitなどで入力してみるとよい

プロジェクト全体で、特定のベンダープリフィックスを出力させたくない

プロジェクト全体で特定のベンダープリフィックスを非表示にしたい場合は

$experimental-support-for-opera:false;
@import "compass";

このように@import前に$experimental-support変数を上書きする。
この場合、プロジェクト全体に一律で特定のベンダープリフィックスが非表示になる。

$experimental-supportの初期値はこちら https://github.com/chriseppstein/compass/blob/stable/frameworks/compass/stylesheets/compass/_support.scss

特定のプロパティに限定して、特定のベンダープリフィックスを出力させたくない

border-radiusbox-shadowといった、ブラウザサポートの範囲によってベンダープリフィックスが不要になるプロパティについて、
個別に制御したい場合は

  • プロパティごとのミックスインは使わず、experimentalミックスインを使って、引数で出力するベンダープリフィックスを制御する
  • 同名のミックスインを作り、compassよりもあとで読み込んで優先的に実行させる
  • compassのソース自体を書き換える

のいずれかの対応となる。

experimentalミックスインを使う

experimentalを使う場合は次のようにな指定となる。

 @include experimental(
    box-sizing,  //プロパティ名
    border-box,  //値
    -moz,        //-mozの出力
    -webkit,     //-webkitの出力
    not -o,      //-oの出力
    not -ms,     //-msの出力
    not -khtml,  //-khtmlの出力(デフォルトでは`$experimental-support-for-khtml`がflaseなので出力されない)
    official     //ベンダープリフィックス無しの出力
    );

  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;

出力させたくないベンダープリフィックスにnotをつければ出力しなくなる。

プロパティではなく、値にベンダープリフィックスを当てたい場合はexperimental-valueを使う。

 @include experimental-value(
    display,
    flex,
    -moz,
    -webkit,
    not -o,
    not -ms,
    not -khtml,
    official
    );

  display: -webkit-flex;
  display: -moz-flex;
  display: flex;

ただし、compassのcss3系のミックスインは、単純にベンダープリフィックスをつけるだけではなく、 ブラウザのバクfixも行なっている場合がある。

例えばborder_radiusの説明を見てみると、 http://compass-style.org/reference/compass/css3/border_radius/

Note: webkit does not support shorthand syntax for several corners at once. So in the case where you pass several values only the first will be passed to webkit.

という注意書きがある。
要は古いsafariが/で区切ったショートハンドに対応していないため、

 @include border-radius(2px 5px,3px 6px);

  -webkit-border-radius: 2px 3px;
  -moz-border-radius: 2px 5px / 3px 6px;
  border-radius: 2px 5px / 3px 6px;

というように、-webkitの値のみcompass側で古いsafariでも表示できる形に変換している。 こういった処理は、experimentalを使うと実行されなくなる。 (experimentalは、ベンダープリフィックスをつけるだけのmixinのため)

※これは新しいsafariではすでに修正されているバグのfixのため、fix自体が現状ではほとんど不要だと思われる。
 しかしこのfixのみを省く方法は用意されていない。
 このような、css3系のmixinに組み込まれたfix処理を実行したくない場合は、
 ベンダープリフィックスの制御と同様に、experimentalを使うか、同名のmixinで上書きくかする必要がある。

同名のmixinで上書きする

同名のmixinが複数存在した場合、あと勝ちになることを利用して、
@import compassの後で同名のミックスインを作成して読み込ませることで制御する。
具体的には以下のようになる。

@import "compass";
@mixin border-radius($radius: $default-border-radius) {
 $radius: unquote($radius);
 @include experimental(border-radius, $radius,not -moz, not -webkit, not -o, not -ms, not -khtml);
}

こうすることで、ベンダープリフィックスの制御や、不要なfixを省くことができる。

compassのソースを書き換える

macだと、

/Library/Ruby/Gems/1.8/gems/compass-0.12.2/frameworks/compass/stylesheets/compass/css3

あたりに入っているsassを書き換えれば多分できると思われる。自己責任でお願いします。windowsの場所は知りません。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment