<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:series="http://organizeseries.com/"
	>

<channel>
	<title>上村 光星 &#8211; HTML5Experts.jp</title>
	<atom:link href="/kosei27/feed/" rel="self" type="application/rss+xml" />
	<link>https://html5experts.jp</link>
	<description>日本に、もっとエキスパートを。</description>
	<lastBuildDate>Sat, 07 Jul 2018 03:14:05 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.7.19</generator>
	<item>
		<title>Sass 3.3で追加された「関数」や「変更点」のまとめ解説</title>
		<link>/kosei27/3850/</link>
		<pubDate>Thu, 26 Dec 2013 01:00:39 +0000</pubDate>
		<dc:creator><![CDATA[上村 光星]]></dc:creator>
				<category><![CDATA[デザイン]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[CSSプリプロセッサ]]></category>
		<category><![CDATA[Sass]]></category>

		<guid isPermaLink="false">/?p=3850</guid>
		<description><![CDATA[連載： Sass 3.3まとめ解説 (3) 前二回の記事では、Sass 3.3で追加された「&#38;」の新機能と@at-rootと新しいデータタイプ「マップ」について解説しました。 最後となる今回は、新しく追加された関...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/sass-news/" class="series-155" title="Sass 3.3まとめ解説" data-wpel-link="internal">Sass 3.3まとめ解説</a> (3)</div><p><a href="https://html5experts.jp/wp-content/uploads/2013/12/sass-2.jpg" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer"><img src="/wp-content/uploads/2013/12/sass-2.jpg" alt="sass-2" width="207" height="156" class="alignright size-full wp-image-3865" /></a>
前二回の記事では、Sass 3.3で追加された<a href="https://html5experts.jp/kosei27/3297/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">「&amp;」の新機能と@at-root</a>と<a href="https://html5experts.jp/kosei27/3727/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">新しいデータタイプ「マップ」</a>について解説しました。</p>

<p>最後となる今回は、新しく追加された関数やいくつかの変更点を解説します。少し長くなりましたので目次を作りました。気になるところからお読みください。</p>

<p>新しく追加された関数</p>

<ul>
<li><a href="#a1" data-wpel-link="internal">文字列用の関数</a></li>
<li><a href="#a2" data-wpel-link="internal">リスト用の関数</a></li>
<li><a href="#a3" data-wpel-link="internal">call()</a></li>
<li><a href="#a4" data-wpel-link="internal">unique-id()</a></li>
<li><a href="#a5" data-wpel-link="internal">変数、ミックスイン、関数の存在を調べる関数</a></li>
<li><a href="#a6" data-wpel-link="internal">inspect()</a></li>
</ul>

<p>変更点</p>

<ul>
<li><a href="#a7" data-wpel-link="internal">リスト関連</a></li>
<li><a href="#a8" data-wpel-link="internal">@each</a></li>
<li><a href="#a9" data-wpel-link="internal">if()</a></li>
<li><a href="#a10" data-wpel-link="internal">@extend</a></li>
<li><a href="#a11" data-wpel-link="internal">!globalフラグ</a></li>
</ul>

<p>※Source Mapについては、丁寧に解説しているブログ記事が既にいくつかありますので、ここでは省略させていただきます。</p>

<h2 id="a1">文字列用の関数</h2>

<p>新たに追加された文字列用の関数は6つあります。</p>

<ul>
<li>str-length($string)</li>
<li>str-insert($string, $insert, $index)</li>
<li>str-index($string, $substring)</li>
<li>str-slice($string, $start-at, [$end-at])</li>
<li>to-upper-case($string)</li>
<li>to-lower-case($string)</li>
</ul>

<h3>str-length()</h3>

<p>str-length()は、文字列の長さを取得する関数です。</p>

<p></p><pre class="crayon-plain-tag">// 引数には文字列を指定
str-length($string)</pre><p></p>

<p>次のように使います。</p>

<p></p><pre class="crayon-plain-tag">str-length("foo")  //-&gt; 3
str-length("")     //-&gt; 0
str-length(" ")    //-&gt; 1

str-length("漢字")     //-&gt; 2
str-length("ひらがな") //-&gt; 4</pre><p></p>

<h3>str-insert()</h3>

<p>str-insert()は、文字列の中の指定した位置に別の文字列を挿入する関数です。</p>

<p></p><pre class="crayon-plain-tag">// 引数の1つ目に対象となる文字列、
// 2つ目に挿入する文字列、3つ目に挿入する位置を指定
str-insert($string, $insert, $index)</pre><p></p>

<p>次のように使います。</p>

<p></p><pre class="crayon-plain-tag">str-insert("abcd", "X", 1)
      //-&gt; "Xabcd"
      //   第3引数を0にしても結果は同じ

str-insert("abcd", "X", 4)
      //-&gt; "abcXd"

str-insert("abcd", "X", 5)
      //-&gt; "abcdX"</pre><p></p>

<p>第3引数には負の値を指定することができます。その場合、文字列の末尾からの位置になります。</p>

<p></p><pre class="crayon-plain-tag">str-insert("abcd", "X", -1)
      //-&gt; "abcdX"

str-insert("abcd", "X", -3)
      //-&gt; "abXcd"</pre><p></p>

<p>また、第3引数に文字数を超える値を指定した場合は次のようになります。</p>

<p></p><pre class="crayon-plain-tag">str-insert("abcd", "X", 10)
      //-&gt; "abcdX"

str-insert("abcd", "X", -10)
      //-&gt; "Xabcd"</pre><p></p>

<h3>str-index()</h3>

<p>str-index()は、文字列の中に指定された文字列が含まれているかどうかを調べる関数です。含まれている場合は開始位置を、含まれていない場合は0を返します。</p>

<p></p><pre class="crayon-plain-tag">// 引数の1つ目に文字列、2つ目に調べたい文字列を指定
str-index($string, $substring)</pre><p></p>

<p>次のように使います。</p>

<p></p><pre class="crayon-plain-tag">str-index(abcd, b)   //-&gt; 2
str-index(abcd, bc)  //-&gt; 2
str-index(abcd, X)   //-&gt; 0
str-index(abcd, ad)  //-&gt; 0</pre><p></p>

<p>大文字小文字は区別されます。</p>

<p></p><pre class="crayon-plain-tag">str-index(abcd, c)  //-&gt; 3
str-index(abcd, C)  //-&gt; 0</pre><p></p>

<h3>str-slice()</h3>

<p>str-slice()は、文字列から指定した範囲を取り出す関数です。</p>

<p></p><pre class="crayon-plain-tag">// 引数の1つ目に対象となる文字列、
// 2つ目に取り出す開始位置、3つ目に終了位置を指定
// 3つ目を省略すると文字列の末尾までになる
str-slice($string, $start-at, [$end-at])</pre><p></p>

<p>次のように使います。</p>

<p></p><pre class="crayon-plain-tag">// 2文字目から末尾まで
str-slice("abcd", 2)
     //-&gt; "bcd"

// 2文字目から3文字目まで
str-slice("abcd", 2, 3)
     //-&gt; "bc"

// 0を指定した場合、1とみなされる
str-slice("abcd", 0, 3)
     //-&gt; "abc"</pre><p></p>

<p>第2、3引数には負の値を指定することもできます。負の値を指定した場合、末尾からの位置になります。</p>

<p></p><pre class="crayon-plain-tag">// （末尾から）3文字目から2文字目まで
str-slice("abcd", -3, -2)
     //-&gt; "bc"

// 2文字目から末尾から2文字目まで
str-slice("abcd", 2, -2)
     //-&gt; "bc"</pre><p></p>

<p>第2引数より第3引数の値が小さい場合や同じ値の場合は「&#8221;&#8221;」が返されます。
また、第2、第3引数が同じ位置を示す場合は、第2引数の位置の文字が返されます。</p>

<p></p><pre class="crayon-plain-tag">// 第3引数の値の方が小さい
str-slice("abcd", 2, 1)    //-&gt; ""
str-slice("abcd", -3, -4)  //-&gt; ""

// 引数の値が同じ
str-slice("abcd", 2, 2)    //-&gt; ""

// 引数の値が同じ位置を示す
str-slice("abcd", 2, -3)   //-&gt; "b"</pre><p></p>

<h3>to-upper-case()、to-lower-case()</h3>

<p>to-upper-case()は文字列を大文字に、to-lower-case()は文字列を小文字にする関数です。</p>

<p></p><pre class="crayon-plain-tag">// 引数には文字列を指定
to-upper-case($string)
to-lower-case($string)</pre><p></p>

<p>次のように使います。</p>

<p></p><pre class="crayon-plain-tag">to-upper-case(abcd)  //-&gt; ABCD
to-upper-case(abCD)  //-&gt; ABCD

to-lower-case(ABCD)  //-&gt; abcd
to-lower-case(ABcd)  //-&gt; abcd</pre><p></p>

<h2 id="a2">リスト用の関数</h2>

<p>新たに追加されたリスト用の関数は2つあります。</p>

<ul>
<li>list-separator($list)</li>
<li>set-nth(($list, $n, $value)</li>
</ul>

<h3>list-separator()</h3>

<p>list-separator()は、リストのセパレーターを返す関数です。</p>

<p></p><pre class="crayon-plain-tag">// 引数にはリストを指定
list-separator($list)</pre><p></p>

<p>次のように使います。</p>

<p></p><pre class="crayon-plain-tag">list-separator(1px 2px 3px)      //-&gt; space
list-separator((1px, 2px, 3px))  //-&gt; comma</pre><p></p>

<p>list-separator()の引数は1つなので、カンマ区切りのリストを上記のように直接指定する場合は、括弧（()）で囲む必要があるので注意してください。</p>

<p>リストの要素が2つよりも少なく、セパレーターもない場合はspaceを返します。</p>

<p></p><pre class="crayon-plain-tag">// 要素が2つよりも少ない
list-separator('foo')     //-&gt; space

// セパレーターがある
list-separator(('foo',))  //-&gt; comma</pre><p></p>

<h3>set-nth()</h3>

<p>set-nth()は、n番目の要素を指定した値に置き換えた新しいリストを返す関数です。</p>

<p></p><pre class="crayon-plain-tag">// 引数の1つ目にリスト、2つ目に位置、3つ目に置換後の値
set-nth($list, $n, $value)</pre><p></p>

<p>次のように使います。</p>

<p></p><pre class="crayon-plain-tag">$list: 10px 20px 30px 40px;

.sample {
    set-nth($list, 2, -20px);
        //-&gt; 10px -20px 30px 40px

    set-nth($list, -2, -20px);
        //-&gt; 10px 20px -20px 40px
}</pre><p></p>

<h2 id="a3">call()</h2>

<p>call()は、動的に関数を呼ぶことができる関数です。
呼べるのは、Sassに組み込まれている関数とユーザーが定義した関数とCSSの関数です。</p>

<p></p><pre class="crayon-plain-tag">// 引数の1つ目に呼びたい関数、2つ目にその関数に渡す引数
call($name, $args...)</pre><p></p>

<p>次のコードは、2つの引数を足した値を返すというサンプル用の関数です。</p>

<p></p><pre class="crayon-plain-tag">@function sum($a: 0, $b: 0) {
    @return $a + $b;
}</pre><p></p>

<p>通常では次のように利用します。</p>

<p></p><pre class="crayon-plain-tag">.sample {
    margin: sum(1px, 2px);  //-&gt; 3px
}</pre><p></p>

<p>call()を使うと、次のようにしてsum()を利用することができます。</p>

<p></p><pre class="crayon-plain-tag">.sample{
    margin: call(sum, 1px, 2px);  //-&gt; 3px

    // call()の引数に変数を使う
    $fn-name: sum;
    padding: call($fn-name, 1px, 2px);  //-&gt;3px
}</pre><p></p>

<p>また、キーワード引数を指定した場合、それはそのまま第1引数で指定した関数に渡されるため、次のようにすることもできます。</p>

<p></p><pre class="crayon-plain-tag">.sample {
    margin: call(sum, $b: 2px);  //-&gt; 2px
}</pre><p></p>

<p>call()の使い方次第では、より汎用性をもったミックスインや関数をつくることができそうです。</p>

<h2 id="a4">unique-id()</h2>

<p>一度にコンパイルされたファイル内でユニークな、「u」から始まる9桁の文字列を返す関数です。文字列はコンパイルするたびに変わります。</p>

<p></p><pre class="crayon-plain-tag">.sample {
    content: unique-id();  //-&gt; ucxkgyjv0
    content: unique-id();  //-&gt; ucxkgyjva
    content: unique-id();  //-&gt; ucxkgyjvc
    content: unique-id();  //-&gt; ucxkgyjvg
}</pre><p></p>

<h2 id="a5">変数、ミックスイン、関数の存在を調べる関数</h2>

<ul>
<li>variable-exists($name)</li>
<li>global-variable-exists($name)</li>
<li>function-exists($name)</li>
<li>mixin-exists($name)</li>
</ul>

<h3>variable-exists()</h3>

<p>variable-exists()は、現在のスコープとグローバルスコープに指定された変数があるかどうかを調べる関数です。指定された変数がある場合はtrueを、ない場合はfalseを返します。</p>

<p></p><pre class="crayon-plain-tag">// 引数には変数名（$は不要）を指定
variable-exists($name)</pre><p></p>

<p>次のように使います。</p>

<p></p><pre class="crayon-plain-tag">$g-foo: "global foo";
.sample {
    $foo: "local foo";

    // ローカル変数
    content: variable-exists(foo);
        //-&gt; true

    // グローバル変数
    content: variable-exists(g-foo);
        //-&gt; true

    // 存在しない変数
    content: variable-exists(non-existent);
        //-&gt; false
}</pre><p></p>

<h3>global-variable-exists()</h3>

<p>global-variable-exists()は、指定されたグローバル変数があるかどうか調べる関数です。指定された変数がある場合はtrueを、ない場合はfalseを返します。</p>

<p></p><pre class="crayon-plain-tag">// 引数には変数名（$は不要）を指定
global-variable-exists($name)</pre><p></p>

<p>次のように使います。</p>

<p></p><pre class="crayon-plain-tag">$g-foo: "global foo";
.sample {
    $foo: "local foo";

    // ローカル変数
    content: global-variable-exists(foo);
        //-&gt; false

    // グローバル変数
    content: global-variable-exists(g-foo);
        //-&gt; true

    // 存在しないグローバル変数
    content: variable-exists(g-non-existent);
        //-&gt; false
}</pre><p></p>

<h3>function-exists()</h3>

<p>function-exists()は、関数があるかどうか調べる関数です。</p>

<p></p><pre class="crayon-plain-tag">// 引数には関数名を指定
function-exists($name)</pre><p></p>

<p>次のように使います。</p>

<p></p><pre class="crayon-plain-tag">// サンプル用の関数
@function sample-fn() {
    @return true;
}

.sample {
    // ユーザー定義の関数
    content: function-exists(sample-fn);
        //-&gt; true


    // Sassの組み込み関数
    content: function-exists(lighten);
        //-&gt; true
}</pre><p></p>

<h3>mixin-exists()</h3>

<p>mixin-exists()は、ミックスインがあるかどうか調べる関数です。</p>

<p></p><pre class="crayon-plain-tag">// 引数にはミックスイン名を指定
mixin-exists($name)</pre><p></p>

<p>次のように使います。</p>

<p></p><pre class="crayon-plain-tag">// サンプル用のミックスイン
@mixin sample-mixin() {
    /* ... */
}

.sample {
    // ユーザー定義のミックスイン
    content: mixin-exists(sample-mixin);
        //-&gt; true

    // 存在しないミックスイン
    content: mixin-exists(non-existent);
        //-&gt; false
}</pre><p></p>

<h2 id="a6">inspect()</h2>

<p>inspect()は、デバッグ用の関数です。</p>

<p></p><pre class="crayon-plain-tag">// 引数には調べたい値を指定
inspect($value)</pre><p></p>

<p>CSSとして有効な値でなければコンパイルエラーになったり、変数に入れたnullやネストしたリストの括弧（()）が出力されなかったりと、デバッグが簡単にはできませんでした。inspect()を使うことでこれらの問題を解決できます。</p>

<p></p><pre class="crayon-plain-tag">.sample {
    /* 変数に入れたnull */
    $var: 1px null 3px;
    content: $var;             //-&gt; 1px 3px
    content: inspect( $var );  //-&gt; 1px null 3px

    /* 空のリスト */
    $list: ();
    content: $list;             //-&gt; コンパイルエラー
    content: inspect( $list );  //-&gt; ()

    /* ネストしたリスト */
    $list: (1px, (foo (bar baz)), false);
    content: $list;             //-&gt; コンパイルエラー
    content: inspect( $list );  //-&gt; (1px, (foo (bar baz)), false)

    /* マップ */
    $map: (key1: value1, key2: value2);
    content: $map;             //-&gt; コンパイルエラー
    content: inspect( $map );  //-&gt; (key1: value1, key2: value2)
}</pre><p></p>

<p>また、@debugにも同じ問題がありましたが、inspect()と同様に値を正しく表示するようになりました。</p>

<h2 id="a7">リスト関連</h2>

<h3>nth()</h3>

<p>nth($list, $n)の$nに負の値を指定できるようになりました。負の値を指定するとリストの末尾からの位置になります。</p>

<p>これにより、リストの最後の値の取得が今までよりも簡単になりました。</p>

<p></p><pre class="crayon-plain-tag">$list: foo, bar, baz;

nth($list, -1)  //-&gt; baz

// 今まで…
nth($list, length($list))</pre><p></p>

<h3>リストの最後のカンマ</h3>

<p>カンマ区切りのリストで、最後にカンマを記述してもコンパイルエラーにならなくなりました。出力時には最後のカンマは取り除かれます。</p>

<p></p><pre class="crayon-plain-tag">$list: foo, bar, baz,;

@debug $list;  //-&gt; foo, bar, baz</pre><p></p>

<p>また、マップも同じように最後にカンマを記述することができます。</p>

<p></p><pre class="crayon-plain-tag">$map: (
    key1: value1,
    key2: value2,
);</pre><p></p>

<h3>要素が1つしかないリストの生成</h3>

<p>これまでは要素が1つしかないリストを作るのはかなり手間でした。</p>

<p></p><pre class="crayon-plain-tag">$list: ();     //-&gt; list
$list: (1);    //-&gt; number !!
$list: (1 2);  //-&gt; list
$list: (1, 2); //-&gt; list

// こうする必要があった
$list: join( (), 1 );    //-&gt; list
$list: append( (), 1 );  //-&gt; list</pre><p></p>

<p>これからは次のようにするだけでリストとして扱われます。</p>

<p></p><pre class="crayon-plain-tag">$list: (1,);</pre><p></p>

<p>ただし、カンマ区切りのリストになるので、スペース区切りのリストにしたい場合は次のようにします。</p>

<p></p><pre class="crayon-plain-tag">$list: join( (), 1, space);
$list: append( (), 1, space);</pre><p></p>

<h2 id="a8">@each</h2>

<p><a href="https://html5experts.jp/kosei27/3727/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">前回の記事</a>でも少し触れていますが、複数の変数を利用することができるようになりました。</p>

<p></p><pre class="crayon-plain-tag">$config: (
    warn: red,
    info: blue,
);

@each $class, $bg-color in $config {
    .#{$class} {
        background-color: $bg-color;
    }
}</pre><p></p>

<p>これをコンパイルすると次のようになります。</p>

<p></p><pre class="crayon-plain-tag">.warn {
  background-color: red;
}

.info {
  background-color: blue;
}</pre><p></p>

<h2 id="a9">if()</h2>

<p>if()は三項演算子みたいな感じのものですが、これまではなぜかtrue/falseの両方の戻り値を評価していたため少し使い勝手が悪いものでした。これからは、条件の結果がtrueならtrueの戻り値だけ評価するようになります。</p>

<h2 id="a10">@extend</h2>

<p>@media内で外にあるセレクタを@extendすると、警告ではなくコンパイルエラーとなるように変更されました。</p>

<p></p><pre class="crayon-plain-tag">@media screen {
    .foo {
        @extend .bar;
    }
}

.bar { ... }</pre><p></p>

<p>また、存在しないセレクタを@extendした場合も、警告ではなくコンパイルエラーとなります。!optionalフラグを記述するとコンパイルエラーを回避することができます。</p>

<p></p><pre class="crayon-plain-tag">.foo {
     @extend .non-existent !optional;
}</pre><p></p>

<h2 id="a11">!globalフラグ</h2>

<p>ローカル（ネスト内）でグローバル変数と同名の変数に代入する場合、グローバル変数の値が変更されていましたが、それがデフォルトの挙動ではなくなります。そのような場合、将来的には、新しいローカル変数が作られて処理されることになり、グローバル変数を上書きする場合には「!global」フラグをつけて明示することが必要になるようです。Sass 3.3.0.rc.2でも「!global」フラグをつけないと警告が表示されてしまいます。</p>

<p></p><pre class="crayon-plain-tag">$var: true;

.sample {
    // グローバル変数を上書きしたい場合
    $var: false !global;
    ...
}</pre><p></p>

<h2>おわりに</h2>

<p>師走だからというわけではありませんが、いろいろと駆け足で解説しました。筆者としてはライブラリに使えるものが増えたので嬉しいのですが、普通の制作には不要なものも少なくないと思います。無理に使ってみるのではなく、必要に応じて取り入れることをお勧めします。</p>

<p>よいお年を。</p>
]]></content:encoded>
		
		<series:name><![CDATA[Sass 3.3まとめ解説]]></series:name>
	</item>
		<item>
		<title>Sass 3.3で追加された新しいデータタイプ「マップ」まとめ解説</title>
		<link>/kosei27/3727/</link>
		<pubDate>Wed, 18 Dec 2013 00:00:00 +0000</pubDate>
		<dc:creator><![CDATA[上村 光星]]></dc:creator>
				<category><![CDATA[デザイン]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[CSSプリプロセッサ]]></category>
		<category><![CDATA[Sass]]></category>

		<guid isPermaLink="false">/?p=3727</guid>
		<description><![CDATA[連載： Sass 3.3まとめ解説 (2)前回の記事では、Sass 3.3で追加される「&#38;」の新機能と@at-rootについて解説しました。今回は新しいデータタイプの「マップ」について解説します。 マップは色々な...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/sass-news/" class="series-155" title="Sass 3.3まとめ解説" data-wpel-link="internal">Sass 3.3まとめ解説</a> (2)</div><p><a href="https://html5experts.jp/wp-content/uploads/2013/12/sass-1.jpg" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer"><img src="/wp-content/uploads/2013/12/sass-1.jpg" alt="sass-1" width="207" height="156" class="alignright size-full wp-image-3733" /></a><a href="https://html5experts.jp/kosei27/3297/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">前回の記事</a>では、Sass 3.3で追加される「&amp;」の新機能と@at-rootについて解説しました。今回は新しいデータタイプの「マップ」について解説します。</p>

<p>マップは色々な使い道があると思いますし、使い方によってはかなり便利なものですので、ライブラリを作っている方などは特に覚えておくと良いと思います。</p>

<p><span id="more-3727"></span></p>

<h2>マップとは</h2>

<p>マップは任意の名前と値のペアが集まったもので、名前をキーにして値を設定したり、取り出して使います。</p>

<p>マップの書き方ですが、名前と値をコロン（:）で区切り、複数記述する場合はカンマ（,）で区切り、それらを丸括弧（()）で囲みます。CSSのスタイルの書き方とちょっと似ていますね。</p>

<p></p><pre class="crayon-plain-tag">// マップ
$map: (
    key1: value1,  // key1にvalue1を設定
    key2: value2,
    key3: value3,
);

// CSSのスタイル
selector {
    property1: value1;  // property1にvalue1を設定
    property2: value2;
    property3: value3;
}</pre><p></p>

<p>マップの値には、マップも含めたすべてのタイプのデータを書くことができます。</p>

<p></p><pre class="crayon-plain-tag">$map: (
    key1: 10px,             // 数値
    key2: "string",         // 文字列
    key3: #fff,             // カラー
    key4: true,             // ブーリアン
    key5: null,             // null
    key6: (foo, bar, baz),  // リスト（カンマ区切り）
    key7: foo bar baz,      // リスト（スペース区切り）
    key8: (                 // ネストしたマップ
        key1: value1,
        key2: value2,
        ...
    ),
);</pre><p></p>

<p>Sass 3.3よりも前までは、複雑なデータ構造を作るにはリストを使って頑張るしかありませんでした。
ですが、マップを使えば、より分かりやすく書くことができますし、専用の関数もあるのでデータを扱いやすくなります。</p>

<h2>マップ用の関数</h2>

<p>マップ用の関数は5つあります。</p>

<ul>
<li>map-get($map, $key)</li>
<li>map-merge($map1, $map2)</li>
<li>map-keys($map)</li>
<li>map-values($map)</li>
<li>map-has-key($map, $key)</li>
</ul>

<h3>map-get()</h3>

<p>map-get()は、指定したキーの値を取得する関数です。</p>

<p></p><pre class="crayon-plain-tag">// 引数の1つ目にマップ、2つ目にキーを指定
map-get($map, $key)</pre><p></p>

<p>次のようにして使います。</p>

<p></p><pre class="crayon-plain-tag">$map: (
    key1: 10px,
    key2: 20px,
    key3: (
        nested-key1: red,
        nested-key2: blue,
    ),
);

.map {
    margin: map-get($map, key1);
}</pre><p></p>

<p>これをコンパイルすると次のようになります。</p>

<p></p><pre class="crayon-plain-tag">.map {
  margin: 10px;
}</pre><p></p>

<p>指定したキーがマップにない場合は、nullが返されます。</p>

<p>また、map-get()を複数回使うことで、ネストされたマップから値を取得することができます。</p>

<p></p><pre class="crayon-plain-tag">.map {
    color: map-get( map-get($map, key3), nested-key1 );
}</pre><p></p>

<p>これをコンパイルすると次のようになります。</p>

<p></p><pre class="crayon-plain-tag">.map {
  color: red;
}</pre><p></p>

<p>何回もmap-get()を書くのは正直面倒くさいですし、コードが読みづらいですね。。</p>

<h3>map-merge()</h3>

<p>map-merge()は、2つのマップをマージする関数です。</p>

<p></p><pre class="crayon-plain-tag">// 引数の1つ目と2つ目にマージしたいマップを指定
map-merge($map1, $map2)</pre><p></p>

<p>基本的には1つ目のマップの後に、2つ目のマップが追加されますが、同じキーがある場合は2つ目のマップの値で上書きされます。</p>

<p></p><pre class="crayon-plain-tag">$map1: (
    key1: value1,
    key2: value2,
    key3: value3,
);

$map2: (
    key4: value400,
    key5: value500,
    key1: value100,
);

$new-map: map-merge($map1, $map2);</pre><p></p>

<p>この場合、$new-mapの値は次のようになっています。</p>

<p></p><pre class="crayon-plain-tag">(key1: value100, key2: value2, key3: value3, key4: value400, key5: value500)</pre><p></p>

<p>key1は両方のマップにあるので、2つ目のマップの$map2の値が使われています。
そして、key3の後に$map2にあったkey4とkey5が追加されています。</p>

<p>このような特徴を利用して、ライブラリ内の設定用マップなどを自身のプロジェクトに合わせて上書きするといったこともできます。</p>

<h3>map-keys()</h3>

<p>map-keys()は、1つのマップ内のすべてのキーをカンマ区切りのリストで返す関数です。</p>

<p></p><pre class="crayon-plain-tag">// 引数にはマップを指定
map-keys($map)</pre><p></p>

<p>それではサンプルを見てみましょう。</p>

<p></p><pre class="crayon-plain-tag">$map: (
    key1: 10px,
    key2: 20px,
    key3: (
        nested-key1: red,
        nested-key2: blue,
    ),
);

.map {
    content: map-keys($map);
}</pre><p></p>

<p>これをコンパイルすると次のようになります。</p>

<p></p><pre class="crayon-plain-tag">.map {
  content: key1, key2, key3;
}</pre><p></p>

<p>ネストされたマップ内のキーを取得するには、map-get()を併用する必要があります。</p>

<p></p><pre class="crayon-plain-tag">.map {
    content: map-keys( map-get($map, key3) );
}</pre><p></p>

<p>これをコンパイルすると次のようになります。</p>

<p></p><pre class="crayon-plain-tag">.map {
  content: nested-key1, nested-key2;
}</pre><p></p>

<h3>map-values()</h3>

<p>map-values()は、1つのマップ内のすべての値をカンマ区切りのリストで返す関数です。</p>

<p></p><pre class="crayon-plain-tag">// 引数にはマップを指定
map-values($map)</pre><p></p>

<p>使い方はmap-keys()と同じです。</p>

<p></p><pre class="crayon-plain-tag">.map {
    content: map-values($map);
        //-&gt; 10px, 20px, ( nested-key1: red, nested-key2: blue )
        // 値にマップが含まれるため、実際にはエラーが出ます
}</pre><p></p>

<h3>map-has-key()</h3>

<p>map-has-key()は、1つのマップ内に特定のキーがあるかどうか調べる関数です。</p>

<p></p><pre class="crayon-plain-tag">// 引数の1つ目にマップ、2つ目に調べたいキーを指定
map-has-key($map, $key)</pre><p></p>

<p>戻り値はtrueかfalseです。</p>

<p></p><pre class="crayon-plain-tag">$map: (
    key1: 10px,
    ...
);

$has-key1: map-has-key($map, key1);</pre><p></p>

<p>この場合、$has-key1の値は true になっています。</p>

<h2>リスト用の関数</h2>

<p>マップには<a href="http://sass-lang.com/documentation/Sass/Script/Functions.html#list-functions" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">リスト用の関数</a>も使うことができます。</p>

<ul>
<li>nth()</li>
<li>length()</li>
<li>zip()</li>
<li>join()</li>
<li>append()</li>
<li>index()</li>
</ul>

<p>使い方とコンパイル結果を簡単にまとめると次のようになります。</p>

<p></p><pre class="crayon-plain-tag">$map1: (
    key1: value1,
    key2: value2,
);

$map2: (
    key4: value400,
    key1: value100,
);

.sample {
    /* nth() */
    content: nth($map1, 1); //-&gt; key1 value1

    /* length() */
    content: length($map1); //-&gt; 2

    /* zip() */
    content: zip($map1);
        //-&gt; key1 value1, key2 value2
    content: zip($map1, $map2);
        //-&gt; key1 value1 key4 value400, key2 value2 key1 value100

    /* join() */
    content: join($map1, $map2);
        //-&gt; key1 value1, key2 value2, key4 value400, key1 value100
    content: join($map1, $map2, space);
        //-&gt; key1 value1 key2 value2 key4 value400 key1 value100

    /* append() */
    content: append($map1, foo bar);
        //-&gt; key1 value1, key2 value2, foo bar
    content: append($map1, foo bar, space);
        //-&gt; key1 value1 key2 value2 foo bar

    /* index() */
    content: index($map1, key1); //-&gt; false
    content: index($map1, key1 value1); //-&gt; 1
}</pre><p></p>

<h2>@eachで使う</h2>

<p>@eachはSass 3.3から複数の変数を指定できるようになったので、マップのキーと値を別々の変数に入れて利用することができます。</p>

<p></p><pre class="crayon-plain-tag">.box {
    $config: (
        warn: red,
        info: blue,
    );

    // キーは$classに、値は$bg-colorに入ります
    @each $class, $bg-color in $config {
        @at-root #{&amp;}-#{$class} {
            background-color: $bg-color;
        }
    }
}</pre><p></p>

<p>これをコンパイルすると次のようになります。</p>

<p></p><pre class="crayon-plain-tag">.box-warn {
  background-color: red;
}
.box-info {
  background-color: blue;
}</pre><p></p>

<p>これまでと比べて、断然扱いやすいものになっていると思います。</p>

<h2>可変長キーワード引数</h2>

<p>マップを可変長引数のような感じでミックスインや関数に渡すことができます。
可変長引数と可変長キーワード引数のそれぞれの場合を、次のミックスインを使って解説します。</p>

<p></p><pre class="crayon-plain-tag">@mixin box($border, $bgColor, $color) {
    border: $border;
    background-color: $bgColor;
    color: $color;
}</pre><p></p>

<p>まずは可変長引数を使った場合です。</p>

<p></p><pre class="crayon-plain-tag">.box {
    // 値はミックスインの引数の順番に合わせる
    $config: 1px solid #ccc, #fff, #333;

    // 変数の後ろに「...」をつけ、可変長引数としてミックスインに渡す
    @include box($config...);
}</pre><p></p>

<p>$configの1つ目の「1px solid #ccc」が$borderに、2つ目の「#fff」が$bgColorに、そして3つ目の「#333」が$colorに渡されます。
これをコンパイルすると次のようになります。</p>

<p></p><pre class="crayon-plain-tag">.box {
  border: 1px solid #cccccc;
  background-color: white;
  color: #333333;
}</pre><p></p>

<p>次にマップを使った可変長キーワード引数の場合です。</p>

<p></p><pre class="crayon-plain-tag">.box {
    $config: (
        // キーはミックスインの引数名に合わせる。記述順は問わない
        color: #333,
        bgColor: #fff,
        border: 1px solid #ccc,
    );

    @include box($config...);
}</pre><p></p>

<p>コンパイル結果は可変長引数の場合と同じになります。</p>

<p>マップを使った場合は、キーと同名のミックスインの引数に値が渡されます。キー「color」はミックスインの引数の「$color」に対応するということです。
そのため、マップ内のキーをミックスインの引数の順番に合わせて記述する必要はありません。</p>

<p>ちなみに、可変長引数と併用することもできますが、その場合は可変長キーワード引数を可変長引数の後に記述する必要があります。</p>

<p>また、Sass 3.3から追加されたkeywords()関数を使って、可変長キーワード引数をマップに変換する関数をつくることができるようです。</p>

<p></p><pre class="crayon-plain-tag">@function create-map($args...) {
  @return keywords($args);
}

$map: create-map($key1: 10px, $key2: 20px);</pre><p></p>

<p>この場合、$mapの値は (key1: 10px, key2: 20px) になっています。</p>

<h2>マップのような構造のリスト</h2>

<p>リストで2つの値をペアにして、マップのようにして使っていた場合、そのリストに対してマップ用の関数を使うことができます。</p>

<p></p><pre class="crayon-plain-tag">$map: (
    key1 value1,
    key2 value2,
);
$map2: (
    key4 value400,
    key1 value100,
);

@debug map-get($map, key1);
       //-&gt; value1
@debug map-merge($map, $map2);
       //-&gt;  (key1: value100, key2: value2, key4: value400)
@debug map-keys($map);
       //-&gt; key1, key2, key3
@debug map-values($map);
       //-&gt; value1, value2, value3
@debug map-has-key($map, key2);
       //-&gt; true</pre><p></p>

<p>ただし、将来的にはこのようなリストに対してマップ用の関数を使うことはできなくなるようで、コンパイル時には警告が出されます。Sass 3.3が使えるようになったら、マップに切り替えていった方がが良さそうです。</p>

<h2>おわりに</h2>

<p>新しいデータタイプ「マップ」を解説しました。筆者としては、自前のライブラリ内のリストでなんとかしている箇所をとりあえず置き換えるつもりですが、みなさんはどのように使われますか？</p>
]]></content:encoded>
		
		<series:name><![CDATA[Sass 3.3まとめ解説]]></series:name>
	</item>
		<item>
		<title>Sass 3.3で追加された「&#038;」の新機能と@at-rootまとめ解説</title>
		<link>/kosei27/3297/</link>
		<pubDate>Thu, 05 Dec 2013 00:00:05 +0000</pubDate>
		<dc:creator><![CDATA[上村 光星]]></dc:creator>
				<category><![CDATA[デザイン]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[CSSプリプロセッサ]]></category>
		<category><![CDATA[Sass]]></category>

		<guid isPermaLink="false">/?p=3297</guid>
		<description><![CDATA[連載： Sass 3.3まとめ解説 (1)10月12日にSass 3.3.0.rc.1が出ました。まだリリース候補ですが、どのような機能が追加されるのかはChangelogにあります。今回は「&#38;」と@at-roo...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/sass-news/" class="series-155" title="Sass 3.3まとめ解説" data-wpel-link="internal">Sass 3.3まとめ解説</a> (1)</div><p><a href="https://html5experts.jp/wp-content/uploads/2013/12/dtl_thm_sass.png" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer"><img src="/wp-content/uploads/2013/12/dtl_thm_sass.png" alt="dtl_thm_sass" width="207" height="156" class="alignright size-full wp-image-3363" /></a>10月12日にSass 3.3.0.rc.1が出ました。まだリリース候補ですが、どのような機能が追加されるのかは<a href="https://github.com/nex3/sass/blob/05c6872a834bbf1ea92e8e7d7da05ee4222d24bd/doc-src/SASS_CHANGELOG.md" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Changelog</a>にあります。今回は「&amp;」と@at-rootについて解説します。</p>

<p><span id="more-3297"></span></p>

<p>HTML+CSSの命名規則に<a href="http://bem.info/method/definitions/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">BEM方法論</a>、もしくはHTML+CSS向けに派生した<a href="http://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">MindBEMding</a>を取り入れる方が増えてきているようです（筆者は使っていませんが…）。「&amp;」の新機能と@at-rootは、このBEMのためといっても過言ではありません。</p>

<h2>Sass 3.2の「&amp;」</h2>

<p>「&amp;」は親セレクタを参照する特別なキーワードとして、Sass 3.3よりも前からありましたが、擬似クラスや擬似要素、セレクタの連結など、用途が限られていました。</p>

<p></p><pre class="crayon-plain-tag">// Sass 3.3よりも前の「&amp;」の用途の例
.foo {
    &amp;:hover  { ... } //-&gt; .foo:hover
    &amp;:after  { ... } //-&gt; .foo:after
    &amp;.bar    { ... } //-&gt; .foo.bar
    &amp; + .bar { ... } //-&gt; .foo + .bar
    &amp; &gt; .bar { ... } //-&gt; .foo &gt; .bar
    .bar &amp; { ... }   //-&gt; .bar .foo
}</pre><p></p>

<p>「&amp;」を使って、親のクラス名を子のクラス名の一部にすることはできませんでした。</p>

<p></p><pre class="crayon-plain-tag">.foo {
    // .foo-barにしたいけど…
    &amp;-bar { ... }  //-&gt; ERROR
}</pre><p></p>

<h2>Sass 3.3の&amp;</h2>

<p>Sass 3.3からは「&amp;」をより多くの場所で使うことができるようになりました。
前述の「親のクラス名を子のクラス名の一部にする」には次のようにします。</p>

<p></p><pre class="crayon-plain-tag">.foo {
    #{&amp;}-bar { ... }  // #{}（インターポレーション）を使います
}</pre><p></p>

<p>これをコンパイルすると次のようになります。</p>

<p></p><pre class="crayon-plain-tag">.foo .foo-bar { ... }</pre><p></p>

<p>「&amp;」はセレクタに使用するだけでなく、変数の値に指定することもできるようになりました。</p>

<p></p><pre class="crayon-plain-tag">.foo, .bar .baz {
    $selector: &amp;;  // #{}は不要です
}</pre><p></p>

<p>このようにした場合、$selectorには (&#8220;.foo&#8221;, (&#8220;.bar&#8221; &#8220;.baz&#8221;)) というようにリストとして格納されます（実際にtype-of()で調べると list が返ってきます）。括弧や引用符で囲まれていますが、実際にはそれらは外された状態で使用されます。</p>

<p></p><pre class="crayon-plain-tag">.foo, .bar .baz {
    $selector: &amp;;
    content: $selector;
}</pre><p></p>

<p>これをコンパイルすると次のようになります。</p>

<p></p><pre class="crayon-plain-tag">.foo, .bar .baz {
  content: .foo, .bar .baz;
}</pre><p></p>

<h2>「&amp;」を使ってBEM</h2>

<p>では、「&amp;」を使ってBEMっぽく書いてみましょう。</p>

<p></p><pre class="crayon-plain-tag">.block {
    // .block__element
    #{&amp;}__element {
        ...

        // .block__element--modifier
        #{&amp;}--modifier { ... }
    }
}</pre><p></p>

<p>これをコンパイルすると次のようになります。</p>

<p></p><pre class="crayon-plain-tag">.block { ... }
.block .block__element { ... }
.block .block__element .block .block__element--modifier { ... }  // ?!</pre><p></p>

<p>.block__elementの前の.blockはともかく、.block__element&#8211;modifierの一つ前にも.blockが出力されてしまっています…。
次のようにネストを減らして書くことで、これを回避することもできますが、、</p>

<p></p><pre class="crayon-plain-tag">.block {
    #{&amp;}__element { ... }
    #{&amp;}__element--modifier { ... }
}</pre><p></p>

<p>この方法だと__elementを何度も書くことになってしまいます。.block__elementの前の.blockを出力しなくてもよいという運用ルールであれば、次に紹介する@at-rootで解決することができます。</p>

<h2>@at-root</h2>

<p>@at-rootの基本機能は、記述した場所より上のセレクタのネストを解除するというものです。<br>
使い方は次のとおりです。</p>

<p></p><pre class="crayon-plain-tag">.foo {
    // 1つのルールセットのみに適用する
    @at-root .bar { ... }

    // 複数のルールセットに適用する
    @at-root {
        .baz { ... }
        .qux {
            ...

            .quux { ... }
        }
    }
}</pre><p></p>

<p>これをコンパイルすると次のようになります。</p>

<p></p><pre class="crayon-plain-tag">.foo { ... }
.bar { ... }
.baz { ... }
.qux { ... }
.qux .quux { ... }</pre><p></p>

<p>.qux .quux { &#8230; }の.quxを取り除いて.quux { &#8230; }としたい場合は、.quuxの前にも@at-rootを記述します。</p>

<p>では、前節の問題を解決します。</p>

<p></p><pre class="crayon-plain-tag">.block {
    @at-root {
        // .block__element
        #{&amp;}__element {
            ...

            @at-root {
                // .block__element--modifier
                #{&amp;}--modifier { ... }
            }
        }
    }
}</pre><p></p>

<p>これをコンパイルすると次のようになります。</p>

<p></p><pre class="crayon-plain-tag">.block { ... }
.block__element { ... }
.block__element--modifier { ... }</pre><p></p>

<p>ようやくすべてフラットにすることができました。</p>

<p>ただ、@at-rootの分だけネストが多くなったのが気になるかもしれません。<br>
ネストを減らしたい方は@at-rootを隠蔽したミックスインを使うことを検討してみてください。</p>

<h2>@at-rootの応用</h2>

<p>@media内で@at-rootを使用した場合、そのルールセットは@media内に出力されます。</p>

<p></p><pre class="crayon-plain-tag">@media screen and (max-width:320px) {
    .foo {
        margin: 0;

        @at-root {
            .bar {
                padding: 0;
            }
        }
    }
}</pre><p></p>

<p>これをコンパイルすると次のようになります。</p>

<p></p><pre class="crayon-plain-tag">@media screen and (max-width: 320px) {
  .foo {
    margin: 0;
  }
  .bar {  /* @media内に出力される */
    padding: 0;
  }
}</pre><p></p>

<p>@mediaの外に.barを出したい場合は、@at-root (without: &#8230;)を使います。</p>

<h3>@at-root (without: &#8230; )</h3>

<p>次のように@at-root (without: media)とすると@mediaの外に出すことができます。</p>

<p></p><pre class="crayon-plain-tag">@media screen and (max-width:320px) {
    .foo {
        margin: 0;

        @at-root (without: media) {
            .bar {
                padding: 0;
            }
        }
    }
}</pre><p></p>

<p>コンパイルすると次のようになります。</p>

<p></p><pre class="crayon-plain-tag">@media screen and (max-width: 320px) {
  .foo {
    margin: 0;
  }
}
.foo .bar {
  padding: 0;
}</pre><p></p>

<p>@mediaの外には出されましたが.foo .bar { &#8230; }となってしまいました。.fooを取り除いて.bar { &#8230; }としたい場合は、withoutの値にruleを追加します。</p>

<p></p><pre class="crayon-plain-tag">@media screen and (max-width:320px) {
    .foo {
        margin: 0;

        @at-root (without: media rule) {
            .bar {
                padding: 0;
            }
        }
    }
}</pre><p></p>

<p>これをコンパイルすると次のようになります。</p>

<p></p><pre class="crayon-plain-tag">@media screen and (max-width: 320px) {
  .foo {
    margin: 0;
  }
}
.bar {
  padding: 0;
}</pre><p></p>

<p>このようにwithoutと後述するwithには、スペース区切りで複数の値を指定することができます。</p>

<table border="1">
<thead>
<tr>
<th>値</th>
<th>説明</th>
</tr>
</thead>
<tbody>
<tr>
<td>mediaやsupportなど</td>
<td>@ルールを除外する／しない</td>
</tr>
<tr>
<td>rule</td>
<td>CSSルールセットを除外する／しない</td>
</tr>
<tr>
<td>all</td>
<td>すべてを除外する／しない</td>
</tr>
</tbody>
</table>

<p>前述の例では、@at-root(without: media rule)としましたが、必ずドキュメントルートに出力したい場合は(without: all)と記述した方が良いです。</p>

<p>@at-root(without: rule)は@at-rootのみ記述した場合と同じです。推測ですが、@at-rootには初期値として(without: rule)が設定されていると思われます。(without: media)とした場合は、初期値を上書きするので(without: rule media)のようには処理されなかったと考えられます。</p>

<p>また、withoutとwithは同時に指定することはできませんでした。(with: &#8230;)を指定した場合も初期値(without: rule)が上書きされてしまうようです。</p>

<h3>@at-root(with: &#8230; )</h3>

<p>では最後に(with: &#8230;)ですが、これに指定したもの以外が除外されます。以下にいくつかのサンプルを記載しておきますので、どのように出力されるか確認してみてください。</p>

<p></p><pre class="crayon-plain-tag">@media screen and (max-width:320px) {
    .foo {
        @supports ( display: flex ) {
            @at-root (with: rule) {
                .bar {
                    width: 0;
                }
            }
            @at-root (with: supports) {
                .baz {
                    height: 0;
                }
            }
            @at-root (with: media) {
                .qux {
                    margin: 0;
                }
            }
            @at-root (with: media rule) {
                .quux {
                    padding: 0;
                }
            }
        }
    }
}</pre><p></p>

<p>コンパイルすると次のようになります。</p>

<p></p><pre class="crayon-plain-tag">@media screen and (max-width: 320px) {
  .qux {        /* (with: media) */
    margin: 0;
  }
  .foo .quux {  /* (with: media rule) */
    padding: 0;
  }
}
.foo .bar {     /* (with: rule) */
  width: 0;
}
@supports (display: flex) {
  .baz {        /* (with: supports) */
    height: 0;
  }
}</pre><p></p>

<h2>おわりに</h2>

<p>「&amp;」の新機能と@at-rootを解説しましたが、いかがだったでしょうか。確かにメリットもありますが、「&amp;」はクラス名の検索がしづらくなりますし、@at-rootは出力後のCSSがどうなるかが想像しにくいケースが出てくるなど、デメリットもあります。筆者としては、これらを利用する場合は用途を限定するなどのルールを設けたいと思いました。</p>
]]></content:encoded>
		
		<series:name><![CDATA[Sass 3.3まとめ解説]]></series:name>
	</item>
	</channel>
</rss>
