<?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>Sass &#8211; HTML5Experts.jp</title>
	<atom:link href="/tag/sass/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>【速攻レビュー】よりモバイルフレンドリーになった「Twitter Bootstrap v4」</title>
		<link>/albatrosary/16824/</link>
		<pubDate>Wed, 02 Sep 2015 02:00:54 +0000</pubDate>
		<dc:creator><![CDATA[佐川 夫美雄]]></dc:creator>
				<category><![CDATA[最新動向]]></category>
		<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[Bootstrap]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Sass]]></category>

		<guid isPermaLink="false">/?p=16824</guid>
		<description><![CDATA[Twitter Bootstrapバージョン4アルファ版が8月19日に公開されました。既にご存知の通りTwitter BootstrapはレスポンシブでモバイルファーストなCSSフレームワークです。さっとレスポンシブなサ...]]></description>
				<content:encoded><![CDATA[<p><a href="http://v4-alpha.getbootstrap.com/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Twitter Bootstrapバージョン4アルファ版</a>が8月19日に公開されました。既にご存知の通りTwitter BootstrapはレスポンシブでモバイルファーストなCSSフレームワークです。さっとレスポンシブなサイトを構築するのに多くの方が利用しているのではないかと思います。この記事ではTwitter Bootstrapバージョン4の変更点について、筆者が「これは！」と思ったところをピックアップしてまとめます。</p>

<p><a href="https://html5experts.jp/wp-content/uploads/2015/08/79686793859202b9371ec01cdd197c6e.png" data-wpel-link="internal"><img src="/wp-content/uploads/2015/08/79686793859202b9371ec01cdd197c6e-640x372.png" alt="Twitter Bootstrap v4 Site" width="640" height="372" class="alignnone size-large wp-image-16825" srcset="/wp-content/uploads/2015/08/79686793859202b9371ec01cdd197c6e.png 640w, /wp-content/uploads/2015/08/79686793859202b9371ec01cdd197c6e-300x174.png 300w, /wp-content/uploads/2015/08/79686793859202b9371ec01cdd197c6e-207x120.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></a></p>

<p>バージョン4の変更内容はGitHub上の<a href="https://github.com/twbs/bootstrap/pull/17021" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">issue</a>で確認することができます。この中で筆者が注目している事項は</p>

<ul>
<li>LESSからSASSへの変更</li>
<li>アイコン（グラフィックアイコン）の削除</li>
<li>IE8のサポート終了とjQuery1系からjQuery2系へ</li>
<li>pxからemへの変更</li>
<li>グリッドシステムに、さらに大きなブレイクポイントを追加</li>
<li>ボタンのカラー指定にClass属性「default」がなくなり「secondary」を指定するようになった</li>
<li>Class属性「display-*」でフォントサイズを指定可能に</li>
<li>ECMAScript2015(babel)の採用</li>
<li>Angularのui.bootstrapはどうなる？</li>
</ul>

<p>現段階ではバージョン4はアルファ版ではありますが、先取りして早速レビューします。</p>

<h2>LESSからSASS</h2>

<p>Twitter Bootstrapはバージョン3ではLESSを用いて開発を行っていましたが、<a href="https://github.com/twbs/bootstrap-sass" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">SASS版Bootstrap</a>もあり、LESS版/SASS版の両方メンテナンスが行われていました。バージョン4からはSASSを採用することになりました。</p>

<p>開発者にとってこれは大きな変更です。例えば、<a href="http://bower.io/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">bower</a>を使ってTwitter Bootstrapを利用する場合、LESS版では</p>

<p><code>$ bower install bootstrap</code></p>

<p>SASS版を利用する場合は</p>

<p><code>$ bower install bootstrap-sass-official</code></p>

<p>と、LESS版を利用するかSASS版を利用するかで呼び出すパッケージが分かれ、しかもgruntタスクやgulpタスク等のコンフィグレーションを記載する際に、それぞれの異なる記載を行っていました。こうしたことが一本化されたことは、冗長的な記述をスッキリさせてくれます。</p>

<p>YEOMANジェネレータに<a href="https://github.com/yeoman/generator-webapp" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">generator-webapp</a>というWeb開発のベーシックなジェネレータがありますが、CSS版/SASS版の切り替えのために、いたるところの分岐が書かれています。</p>

<p>ちなみに、bowerを使ったアルファ版のインストールは、明示的にバージョンを指定する必要があります。バージョンを指定しない場合は3系がダウンロードされます。</p>

<p><code>$ bower install bootstrap#4.0.0-alpha</code></p>

<h2>アイコン（グラフィックアイコン）の削除</h2>

<p>Twitter Bootstrapと言えば、豊富な人気のあった<a href="http://getbootstrap.com/components/#glyphicons-glyphs" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Glyphicons</a>ですが、バージョン4では削除されています。</p>

<p><a href="https://html5experts.jp/wp-content/uploads/2015/08/b5c2950df2785ae0cd4f8e7cabf6e83d.png" data-wpel-link="internal"><img src="/wp-content/uploads/2015/08/b5c2950df2785ae0cd4f8e7cabf6e83d-640x463.png" alt="Glyphicons" width="640" height="463" class="alignnone size-large wp-image-16841" srcset="/wp-content/uploads/2015/08/b5c2950df2785ae0cd4f8e7cabf6e83d.png 640w, /wp-content/uploads/2015/08/b5c2950df2785ae0cd4f8e7cabf6e83d-300x217.png 300w, /wp-content/uploads/2015/08/b5c2950df2785ae0cd4f8e7cabf6e83d-207x150.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></a></p>

<p>現段階では極わずかにGlyphiconsが残されているだけになっていて、入力時の警告等を表示させているだけになっています。</p>

<p><a href="https://html5experts.jp/wp-content/uploads/2015/08/dbe6928786ed5ad5d354e7096134d3a71.png" data-wpel-link="internal"><img src="/wp-content/uploads/2015/08/dbe6928786ed5ad5d354e7096134d3a71-640x480.png" alt="form-icon" width="640" height="480" class="alignnone size-large wp-image-16827" srcset="/wp-content/uploads/2015/08/dbe6928786ed5ad5d354e7096134d3a71.png 640w, /wp-content/uploads/2015/08/dbe6928786ed5ad5d354e7096134d3a71-300x225.png 300w, /wp-content/uploads/2015/08/dbe6928786ed5ad5d354e7096134d3a71-207x155.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></a></p>

<p><code></p>

<div class="form-group has-success">
  <label class="control-label" for="inputSuccess1">Input with success</label>
</div>

<div class="form-group has-warning">
  <label class="control-label" for="inputWarning1">Input with warning</label>
</div>

<div class="form-group has-error">
  <label class="control-label" for="inputError1">Input with error</label>
</div>

<p></code></p>

<p>削除されたグラフィックアイコンですが、現状ではTwitter Bootstrapの管理外で定義されているような記述もありません。もしグラフィックアイコンを利用したい場合は、別途どこかからお気に入りグラフィックアイコンを利用する必要があります。</p>

<h2>IE8のサポート終了とjQuery1系からjQuery2系へ</h2>

<p>Internet Explorer8とiOS6へのサポートが終了します。Twitter BootstrapがjQueryのバージョンを1系から2系への利用変更に伴いInternet Explorer8のサポートも打ち切られました。IE8を利用する必要がある場合にはバージョン3を利用します。</p>

<p>さようならIE8…</p>

<h2>pxからemへの変更</h2>

<p>フォントサイズ等の指定が<code>px</code>から<code>em</code>(およびCSS3で導入された<code>rem</code>)に変更されました。<code>px</code>はピクセル単位の指定で、環境によって変化しない絶対単位です。<code>em</code>は文字の高さを基準にした単位で<code>1em</code>は1文字を表します。特に<code>rem</code>はCSS3で新しく定義された<code>root em</code>でroot要素（html要素）のフォントサイズを継承します。</p>

<p><code>px</code>の場合、ブラウザのフォントサイズを変更しても文字の大きさが変わりませんが、<code>em</code>ではフォントサイズの大きさに合わせ表示されるフォントサイズも変わります。chromeの場合は「chrome://settings/」でフォントサイズを変更した場合に違いが確認できます。</p>

<p><a href="https://html5experts.jp/wp-content/uploads/2015/08/095f235c11c239866cb784e0ea46022b.png" data-wpel-link="internal"><img src="/wp-content/uploads/2015/08/095f235c11c239866cb784e0ea46022b-640x192.png" alt="chrome-settings" width="640" height="192" class="alignnone size-large wp-image-16829" srcset="/wp-content/uploads/2015/08/095f235c11c239866cb784e0ea46022b.png 640w, /wp-content/uploads/2015/08/095f235c11c239866cb784e0ea46022b-300x90.png 300w, /wp-content/uploads/2015/08/095f235c11c239866cb784e0ea46022b-207x62.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></a></p>

<p>乱暴な言い方ですが、ユーザの好みのフォントサイズに対応するというのはある意味よりレスポンシブになったと言えるのではと思います。<code>px</code>が良いのか<code>em</code>が良いのか議論としては様々だとは思いますが、Twitter Bootstrapでは<code>em</code>を利用します。</p>

<h2>グリッドシステムに、さらに大きなブレイクポイントを追加</h2>

<p><a href="https://html5experts.jp/shumpei-shiraishi/1538/" data-wpel-link="internal">Bootstrap3超速レビュー！刷新されたグリッドシステムを理解しよう！</a>でも記述されているグリッドシステムですが、4つ定義されていたブレークポイントがバージョン4ではブレークポイントが5つになり「Extra large」が追加されました。</p>

<p>具体的に、バージョン3では</p>

<p><a href="https://html5experts.jp/wp-content/uploads/2015/08/98765df1dd03b7a0590d98a4b1e5caea.png" data-wpel-link="internal"><img src="/wp-content/uploads/2015/08/98765df1dd03b7a0590d98a4b1e5caea-640x299.png" alt="Grid v3" width="640" height="299" class="alignnone size-large wp-image-16830" srcset="/wp-content/uploads/2015/08/98765df1dd03b7a0590d98a4b1e5caea.png 640w, /wp-content/uploads/2015/08/98765df1dd03b7a0590d98a4b1e5caea-300x140.png 300w, /wp-content/uploads/2015/08/98765df1dd03b7a0590d98a4b1e5caea-207x97.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></a></p>

<p>バージョン4では</p>

<p><a href="https://html5experts.jp/wp-content/uploads/2015/08/157e413c151d7fac9b20d016b4a8e104.png" data-wpel-link="internal"><img src="/wp-content/uploads/2015/08/157e413c151d7fac9b20d016b4a8e104-640x377.png" alt="Grid v4" width="640" height="377" class="alignnone size-large wp-image-16831" srcset="/wp-content/uploads/2015/08/157e413c151d7fac9b20d016b4a8e104.png 640w, /wp-content/uploads/2015/08/157e413c151d7fac9b20d016b4a8e104-300x177.png 300w, /wp-content/uploads/2015/08/157e413c151d7fac9b20d016b4a8e104-207x122.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></a></p>

<p>ブレークポイントにより大きなExtra largeが定義されましたが、実際には小さい画面に対するブレークポイントが追加されています。</p>

<p>比較するとわかりますが</p>

<table>
<thead>
<tr>
  <th>サイズ</th>
  <th>バージョン3</th>
  <th>バージョン4</th>
</tr>
</thead>
<tbody>
<tr>
  <td>&lt;34em</td>
  <td>&#8211;</td>
  <td>Extra small &lt;34em</td>
</tr>
<tr>
  <td>≥34em(544px)</td>
  <td>Extra small devices Phones &lt;768px</td>
  <td>Small ≥34em</td>
</tr>
<tr>
  <td>≥48em(768px)</td>
  <td>Small devices Tablets ≥768px</td>
  <td>Medium ≥48em</td>
</tr>
<tr>
  <td>≥62em(922px)</td>
  <td>Medium devices Desktops ≥992px</td>
  <td>Large ≥62em</td>
</tr>
<tr>
  <td>≥75em(1200px)</td>
  <td>Large devices Desktops ≥1200px</td>
  <td>Extra large ≥75em</td>
</tr>
</tbody>
</table>

<p>※ 1emを16pxとした場合</p>

<p><code>visible-*(-block)</code>というクラス属性ですが、バージョン４では実装されていません。これは特定のサイズのときに表示させるのもで、例えば</p>

<p><code>
<span class="visible-sm-block">✔ Visible on small</span>
</code></p>

<p>としたときに「smサイズ」で表示されます。<code>.visible-*(-block)</code>が削除され変わりに<code>.hidden-*-up</code> or <code>.hidden-*-down</code> を利用する方向です。</p>

<h2>ボタンのカラー指定にClass属性「default」がなくなり「secondary」を指定するようになった</h2>

<p><code>btn-*</code>では、<code>default</code>がなくなり<code>secondary</code>が新たに追加されました。<code>default</code>と同様の色を指定する場合は<code>secondary</code>を指定する必要があります。btn-primaryのバックグラウンドカラーも若干明るめに定義されています。</p>

<p>バージョン3では</p>

<p><a href="https://html5experts.jp/wp-content/uploads/2015/08/6dcd69e278bea198b5794240e3cb0f6d.png" data-wpel-link="internal"><img src="/wp-content/uploads/2015/08/6dcd69e278bea198b5794240e3cb0f6d-640x85.png" alt="スクリーンショット 2015-08-26 14.23.38" width="640" height="85" class="alignnone size-large wp-image-16834" srcset="/wp-content/uploads/2015/08/6dcd69e278bea198b5794240e3cb0f6d.png 640w, /wp-content/uploads/2015/08/6dcd69e278bea198b5794240e3cb0f6d-300x40.png 300w, /wp-content/uploads/2015/08/6dcd69e278bea198b5794240e3cb0f6d-207x27.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></a></p>

<p>バージョン4では</p>

<p><a href="https://html5experts.jp/wp-content/uploads/2015/08/22d933c35c469e05131a490b6b0c0f58.png" data-wpel-link="internal"><img src="/wp-content/uploads/2015/08/22d933c35c469e05131a490b6b0c0f58-640x93.png" alt="buttons v3" width="640" height="93" class="alignnone size-large wp-image-16833" srcset="/wp-content/uploads/2015/08/22d933c35c469e05131a490b6b0c0f58.png 640w, /wp-content/uploads/2015/08/22d933c35c469e05131a490b6b0c0f58-300x44.png 300w, /wp-content/uploads/2015/08/22d933c35c469e05131a490b6b0c0f58-207x30.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></a></p>

<p>現在バージョン3とバージョン4で定義されている値を比較すると次の通りです：</p>

<table>
<thead>
<tr>
  <th>クラス属性</th>
  <th>v3</th>
  <th>v4</th>
</tr>
</thead>
<tbody>
<tr>
  <td>btn-default-bg</td>
  <td>#fff</td>
  <td>&#8211;</td>
</tr>
<tr>
  <td>btn-primary-bg</td>
  <td>darken(#428bca, 6.5%); // #337ab7</td>
  <td>#0275d8</td>
</tr>
<tr>
  <td>btn-secondary-bg</td>
  <td>&#8211;</td>
  <td>#fff</td>
</tr>
<tr>
  <td>btn-success-bg</td>
  <td>#5cb85c;</td>
  <td>#5cb85c</td>
</tr>
<tr>
  <td>btn-info-bg</td>
  <td>#5bc0de;</td>
  <td>#5bc0de</td>
</tr>
<tr>
  <td>btn-warning-bg</td>
  <td>#f0ad4e;</td>
  <td>#f0ad4e</td>
</tr>
<tr>
  <td>btn-danger-bg</td>
  <td>#d9534f;</td>
  <td>#d9534f</td>
</tr>
</tbody>
</table>

<p>こうしたカラーリングですが、ラベルやアラートに関しては今のところ変更がありません、ボタンのみ変更されています。</p>

<h2>Class属性「display-*」でフォントサイズを指定可能に</h2>

<p>小さい部分ですが、フォントサイズを指定するクラス属性に<code>display-*</code>が追加されました。コメントには次のような記載があります:</p>

<p>&gt; 見出し要素(h1,h2,…h6)はページのコンテンツのボディで最適に動作するように設計されています。より目立つような見出しが必要な場合は、より大きいスタイルを使用することを検討してください。</p>

<p>具体的には</p>

<table>
<thead>
<tr>
  <th>display-*</th>
  <th>フォントサイズ</th>
</tr>
</thead>
<tbody>
<tr>
  <td>display-1</td>
  <td>3.5rem</td>
</tr>
<tr>
  <td>display-2</td>
  <td>4.5rem</td>
</tr>
<tr>
  <td>display-3</td>
  <td>5.5rem</td>
</tr>
<tr>
  <td>display-4</td>
  <td>6rem</td>
</tr>
</tbody>
</table>

<p>として定義されています。しかし、CSSの<code>font-weight</code>の定義が<code>h1</code>では<code>500</code>であるのに対し、<code>display-*</code>では<code>300</code>ですので若干ほっそりとした表示になります。</p>

<p><a href="https://html5experts.jp/wp-content/uploads/2015/08/f649fc61464b206a51073e74a1661248.png" data-wpel-link="internal"><img src="/wp-content/uploads/2015/08/f649fc61464b206a51073e74a1661248-640x480.png" alt="display-*" width="640" height="480" class="alignnone size-large wp-image-16836" srcset="/wp-content/uploads/2015/08/f649fc61464b206a51073e74a1661248.png 640w, /wp-content/uploads/2015/08/f649fc61464b206a51073e74a1661248-300x225.png 300w, /wp-content/uploads/2015/08/f649fc61464b206a51073e74a1661248-207x155.png 207w" sizes="(max-width: 640px) 100vw, 640px" /></a></p>

<p><code></p>

<h1 class="display-4">Display 4</h1>

<h1 class="display-3">Display 3</h1>

<h1 class="display-2">Display 2</h1>

<h1 class="display-1">Display 1</h1>

<h1>Display</h1>

<p></code></p>

<h2>ECMAScript2015(Babel)の採用</h2>

<p>Twitter BootstrapのJavaScript開発には<a href="https://babeljs.io/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">Babel</a>が採用されています。Babelは、<a href="https://html5experts.jp/vvakame/16241/" data-wpel-link="internal">TypeScriptを使ってECMAScript 2015時代のJavaScriptを先取りしよう！</a>での記載もあるように、今年6月に公式に次のECMAScriptとして仕様が公開されたECMAScript2015(今まではECMAScript6と呼ばれていました)の文法で記載することが出来ます。参考までに、ECMAScriptは<a href="http://www.ecma-international.org/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ECMA International</a>が策定した仕様で、この仕様に基いて実装されたものがJavaScriptです。</p>

<p>ECMAScript2015の特徴をいくつか上げると次の通りです。詳しくは<a href="https://babeljs.io/docs/learn-es2015/#ecmascript-6-features" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">こちら</a>を参照ください。</p>

<ul>
<li>Arrows</li>
<li>Classes</li>
<li>Let + Const</li>
<li>Iterators + For..Of</li>
<li>Generators</li>
<li>Modules and Module Loaders</li>
<li>Map + Set + WeakMap + WeakSet</li>
<li>Proxies</li>
<li>Promises</li>
</ul>

<h2>Angularのui.bootstrapはどうなる？</h2>

<p>AngularにはBootstrap Componentsをベースにした<a href="http://angular-ui.github.io/bootstrap/" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">ui.bootstrap</a>があります。Angularを使って日頃開発を行っている方には、ui.bootstrapの動向も気になるところではないかと思います。というのも私は、ui.bootstrapのディレクティブ実装が非常に良いと思っているので、積極的に利用しています。</p>

<p>ui.bootstrapの対応に関しては現在<a href="https://github.com/angular-ui/bootstrap/issues/4234" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer">issue</a>で話が上がっています。ui.bootstrapはAngular2の対応もありますので、Twitter Bootstrapバージョン4の対応は難しい状況のようです。</p>

<h2>まとめ</h2>

<p>バージョン3からレスポンシブWebデザインを前提として作られたTwitter Bootstrapですが、バージョン4では現在のモバイル環境に合わせより強力に洗練されたCSSフレームワークです。</p>

<p>今回のレビューはまだアルファ版のため一部機能が実装されていない部分もありますが正式リリースが楽しみです。</p>
]]></content:encoded>
			</item>
		<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>HTML5を駆使したRakuten Technology Conference 2013サイト制作の内側</title>
		<link>/ogaoga/3370/</link>
		<pubDate>Fri, 06 Dec 2013 00:00:37 +0000</pubDate>
		<dc:creator><![CDATA[小笠原 努]]></dc:creator>
				<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[デザイン]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Canvas]]></category>
		<category><![CDATA[Grunt]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Sass]]></category>

		<guid isPermaLink="false">/?p=3370</guid>
		<description><![CDATA[楽天では、10月26日に「Rakuten Technology Conference 2013」を開催し、多くの方にご来場頂きました。ご参加者の皆様、ありがとうございました！ 私が所属している「HTML5 Project...]]></description>
				<content:encoded><![CDATA[<p><a href="https://html5experts.jp/wp-content/uploads/2013/12/Rakuten-Technology-Conference-2013.png" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer"><img src="/wp-content/uploads/2013/12/Rakuten-Technology-Conference-2013-206x300.png" alt="Rakuten Technology Conference 2013 のトップページ" width="206" height="300" class="alignright size-medium wp-image-3380" style="border:1px solid gray" srcset="/wp-content/uploads/2013/12/Rakuten-Technology-Conference-2013-206x300.png 206w, /wp-content/uploads/2013/12/Rakuten-Technology-Conference-2013-705x1024.png 705w, /wp-content/uploads/2013/12/Rakuten-Technology-Conference-2013-142x207.png 142w, /wp-content/uploads/2013/12/Rakuten-Technology-Conference-2013.png 441w" sizes="(max-width: 206px) 100vw, 206px" /></a></p>

<p>楽天では、10月26日に「<a href="http://tech.rakuten.co.jp/" title="Rakuten Technology Conference 2013" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">Rakuten Technology Conference 2013</a>」を開催し、多くの方にご来場頂きました。ご参加者の皆様、ありがとうございました！</p>

<p>私が所属している「HTML5 Project Team」が<a href="http://tech.rakuten.co.jp/timetable.html#session-e2" title="担当したセッション（HTML5 in Rakuten）" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">担当したセッション</a>では、今回制作を担当したカンファレンスのサイトについて発表をしました。技術者の祭典ということもあり、HTML5やフロントエンドの技術をふんだんに盛り込み、皆さんご存知の賑やかな楽天市場とはひと味違ったクールなサイトに仕上げました。ご覧頂けましたでしょうか？</p>

<p>当日のセッションの内容と重複しますが、今回は、HTML5の活用事例として、このサイトがどのような技術で作られたのか、<a href="http://www.slideshare.net/rakutentech/tech-conf2013e2" title="セッションでも使用したスライド（HTML5 in Rakuten）" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">セッションでも使用したスライド</a>を交えて紹介していきます。</p>

<h2>「Rakuten Technology Conference 2013」サイトのコンセプトと要求仕様</h2>

<p>このサイトでは、よくあるカンファレンスのサイトと同じく、講演者の紹介やタイムテーブルなどを公開しています。メインのターゲットユーザーはエンジニアで、日頃はPCをよく使い、最新のスマートフォンを持ち歩いていると想定しました。また、情報だけでなく技術面でもアピールする機会にしたかったこともあり、過剰なほどにあらゆる技術を盛り込んでいます。</p>

<p>サイトを構築する上で、いくつか要求仕様がありました。</p>

<ul>
    <li>情報の更新が頻繁に行われる</li>
    <li>SEOを考慮する</li>
    <li>サーバサイドスクリプトは使用しない</li>
</ul>

<p>これらを満たすために、</p>

<ul>
    <li>都度、複数のHTMLを編集するのではなく、スタッフから受け取ったデータ（JSON）からHTMLを生成する。</li>
    <li>サーバサイドスクリプトが使えないので、ローカルで生成する。</li>
</ul>

<p>という方針を定め、様々な技術を使って実現しました。</p>

<h2>活用した技術</h2>

<p>コンテンツ自体にもHTML5をはじめとした最新技術が使われていますが、制作面においても、最新のツールを駆使して効率化を図りました。</p>

<h3>Canvasを使ったインタラクティブな背景</h3>

<p>サイト全体にタイルをモチーフとした背景を採用していて、PCでご覧頂くと、マウスの動きに合わせてハイライトとされ、タイルが微妙に移動していることがわかるかと思います。この背景部分は、Canvas
で描画しています。PC向けにはタイルは固定幅ですが、タブレット向けでは画面幅に合わせてタイル幅を調整しています。また、Canvasの処理部分には<a href="http://www.createjs.com/#!/CreateJS" title="CreateJS" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">CreateJS</a>を使用しています。</p>

<h3>CSSによるスムーズなインタラクション</h3>

<p><a href="http://tech.rakuten.co.jp/" title="Rakuten Technology Conference 2013 のトップページ" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">トップページ</a>の「M」のタイルをクリックすると、実行委員長からのメッセージが表示されます。このとき、委員長の顔のタイルが拡張して、それに合わせて他のタイルが追いやられるようなアニメーションを行っています。この動きはCSSによって実現されていて、スマートフォンでも同様に動きます。これ以外にも、様々な場面でCSSによるアニメーションを使用しています。</p>

<h3>スマートフォン最適化とレスポンシブWebデザイン</h3>

<p>当日会場でスマートフォンからタイムテーブルを確認することを考慮し、スマートフォン対応をしました。タイムテーブルは縦横に長いコンテンツのため、スマートフォンとの相性は悪いのですが、時間帯ごとに横スクロールするようにして、閲覧性を確保しました。</p>

<p>各デバイスへの対応は、レスポンシブWebデザインで行いました。PCとスマートフォンでレイアウトが大きく異なるので、かなり苦戦しました。</p>

<p><a href="http://www.slideshare.net/rakutentech/tech-conf2013e2/92" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer"><img src="/wp-content/uploads/2013/12/Screen-Shot-2013-11-25-at-2.34.58-PM-300x224.png" alt="ページの幅ごとのレイアウト" width="300" height="224" class="aligncenter size-medium wp-image-3387" style="border:1px solid gray" srcset="/wp-content/uploads/2013/12/Screen-Shot-2013-11-25-at-2.34.58-PM-300x224.png 300w, /wp-content/uploads/2013/12/Screen-Shot-2013-11-25-at-2.34.58-PM-207x154.png 207w, /wp-content/uploads/2013/12/Screen-Shot-2013-11-25-at-2.34.58-PM.png 640w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>

<p>また、それぞれの表示ごとにJavaScriptの処理も異なっているため、ウィンドウ幅を監視して、表示の切り替わり時にそれぞれ適切な処理を実行するような仕組みも取り入れました。</p>

<h3>お気に入りのセッションをブックマークできるWeb Storage</h3>

<p>タイムテーブルで、お気に入りのセッションをブックマークできる機能を追加しました。ブックマークするとブラウザのlocalStorageに保存され、いつでもお気に入りのセッションだけを表示できます。</p>

<p>また、ページ上部のSpeakersやUpdatesの部分に、赤枠の数字が表示されますが、これは、前回閲覧したときのデータをlocalStorageに保持し、今回読み込んだデータ数の差を表示して、何件更新されたかを示しています（表示すると消えます）。</p>

<p><a href="http://www.slideshare.net/rakutentech/tech-conf2013e2/116" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer"><img src="/wp-content/uploads/2013/12/Screen-Shot-2013-11-27-at-10.57.51-AM-300x224.png" alt="Notification feature の説明図" width="300" height="224" class="aligncenter size-medium wp-image-3391" style="border:1px solid gray" srcset="/wp-content/uploads/2013/12/Screen-Shot-2013-11-27-at-10.57.51-AM-300x224.png 300w, /wp-content/uploads/2013/12/Screen-Shot-2013-11-27-at-10.57.51-AM-207x154.png 207w, /wp-content/uploads/2013/12/Screen-Shot-2013-11-27-at-10.57.51-AM.png 640w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>

<p>PCで登録したブックマークをカンファレンス当日にスマートフォンで呼び出せるように、URLでその情報を引き継げるようにはしていたのですが、UIを提供できませんでした。来年はその辺りも提供できればと思っています。</p>

<h3>PhantomJS + UnderscoreJSで更新負荷を下げる</h3>

<p><a href="http://phantomjs.org/" title="PhantomJS" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">PhantomJS</a>は、コマンドラインから呼び出せるWebKitエンジンで、今回は、テンプレートとデータからHTMLを生成する処理で利用しました。テンプレートエンジンは<a href="http://underscorejs.org/" title="Underscore.js" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">Underscore.js</a>を利用しました。</p>

<p>講演者の情報やセッションの時間などの情報は開催日まで頻繁に更新があり、その度にHTMLを修正しているとかなりの手間となります。そのため、それらの情報をまとめるカンファレンススタッフに、データをJSON形式で記述して納品してもらうようにしました。納品されたJSONファイルをUnderscore.jsでテンプレートに適用して、HTMLを出力しました。</p>

<p>データは構造化されているため、例えばタイムテーブルのデータを更新すると、タイムテーブルだけではなく、その講演者のページの情報も同時に変更されます。また、セッションの場所の名称が変更されたときも、１箇所修正するだけで、すべての名称が新しいものに置き換わります。</p>

<p><a href="http://www.slideshare.net/rakutentech/tech-conf2013e2/139" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer"><img src="/wp-content/uploads/2013/12/Screen-Shot-2013-11-25-at-2.13.39-PM-300x225.png" alt="What&#039;s PhantomJS? の説明図" width="300" height="225" class="aligncenter size-medium wp-image-3393" style="border:1px solid gray" srcset="/wp-content/uploads/2013/12/Screen-Shot-2013-11-25-at-2.13.39-PM-300x225.png 300w, /wp-content/uploads/2013/12/Screen-Shot-2013-11-25-at-2.13.39-PM-207x155.png 207w, /wp-content/uploads/2013/12/Screen-Shot-2013-11-25-at-2.13.39-PM.png 640w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>

<h3>レスポンシブ対応がシンプルに記述できるSass / Compass</h3>

<p>CSSの生成には、おなじみ<a href="http://sass-lang.com/" title="Sass" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">Sass</a>と<a href="http://compass-style.org/" title="Compass" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">Compass</a>を使用しました。Sass内でif文を使って各デバイスの判定ができるようにして、レスポンシブ対応がシンプルに記述できました。</p>

<p><a href="http://www.slideshare.net/rakutentech/tech-conf2013e2/99" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer"><img src="/wp-content/uploads/2013/12/Screen-Shot-2013-11-25-at-2.23.10-PM-300x224.png" alt="Coding into Condition branch の説明図" width="300" height="224" class="aligncenter size-medium wp-image-3395" style="border:1px solid gray" srcset="/wp-content/uploads/2013/12/Screen-Shot-2013-11-25-at-2.23.10-PM-300x224.png 300w, /wp-content/uploads/2013/12/Screen-Shot-2013-11-25-at-2.23.10-PM-207x154.png 207w, /wp-content/uploads/2013/12/Screen-Shot-2013-11-25-at-2.23.10-PM.png 640w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>

<h3>Gruntによる処理の自動化</h3>

<p>PhantomJSでのHTMLの生成、Sass/Compassのコンパイル、ファイル操作などは<a href="http://gruntjs.com/" title="Grunt" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">Grunt</a>を使い自動化しました。PhantomJSの呼び出し部分は、いいモジュールを見つけられなかったため、シェルコマンドを呼び出すタスクを書きました。</p>

<p><a href="http://www.slideshare.net/rakutentech/tech-conf2013e2/127" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer"><img src="/wp-content/uploads/2013/12/Screen-Shot-2013-11-25-at-2.26.25-PM-300x224.png" alt="Tools and flow の説明図" width="300" height="224" class="aligncenter size-medium wp-image-3397" style="border:1px solid gray" srcset="/wp-content/uploads/2013/12/Screen-Shot-2013-11-25-at-2.26.25-PM-300x224.png 300w, /wp-content/uploads/2013/12/Screen-Shot-2013-11-25-at-2.26.25-PM-207x154.png 207w, /wp-content/uploads/2013/12/Screen-Shot-2013-11-25-at-2.26.25-PM.png 640w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>

<p>このように、目的に合わせた最新技術に挑戦して、今回の「Rakuten Technology Conference 2013」のサイトを作り上げていて、私たちも様々な収穫がありました。まだ、パフォーマンスやユーザビリティなどで不十分な点もあるので、今後の課題として取り組みたいと思っています。</p>

<p>また、「サーバでスクリプト使えなくても、ローカルでRubyやPHPとか使えば楽じゃね？」という話もありますが（汗）、そこは我々「HTML5 Project Team」ということで、今回はフロントエンドの技術だけにこだわってみました。来年は、NodeベースのWebサーバに移行して、より簡単にサイトを更新できるようなことも考えています。</p>

<p>今後もこのような挑戦を続け、そこで得ていく知見を楽天のサービスに活かして行きたいと思っています。またこのような形で、いつもお世話になっているコミュニティにも還元できれば幸いです。今後ともよろしくお願いします。</p>

<p>このセッションのビデオは<a href="http://www.youtube.com/watch?v=BgCdgkHEn8M" title="YouTubeにアップ" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">YouTubeにアップ</a>されており、使ったスライドも<a href="http://www.slideshare.net/rakutentech/tech-conf2013e2" title="SlideShareで公開" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">SlideShareで公開</a>されています。もしよろしければそちらもご覧ください。</p>

<div style="float:left">

<!-- iframe plugin v.4.3 wordpress.org/plugins/iframe/ -->
<iframe width="398" height="224" src="//www.youtube.com/embed/BgCdgkHEn8M?rel=0" frameborder="0" 0="allowfullscreen" scrolling="yes" class="iframe-class"></iframe>

</div>

<div>

<!-- iframe plugin v.4.3 wordpress.org/plugins/iframe/ -->
<iframe src="http://www.slideshare.net/slideshow/embed_code/28399053" width="264" height="224" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC;border-width:1px 1px 0;margin-bottom:5px" 0="allowfullscreen" class="iframe-class"></iframe>

</div>

<div style="clear:both"></div>
]]></content:encoded>
			</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>
