Webプログラマから見たiOS9 Safari9のCSS/JavaScriptなどの新機能解説


iOS9がリリースされ、iPhone6sも発売され、iOS9 Safari9で使える新機能をWebプログラマ目線で使ってみたいものをいくつか試してみました。iOSはアップデートの進捗がわりと良いので、新機能でもモバイルサイトであれば積極的に使える…はず。デスクトップ版の方は…お察しください。

ぶっちゃけ今回はそこまで目玉機能はなく、地味です。地味ですが、SafariでWebアプリを作れるようになりそうな気配がどことなくするようなしないような感じの内容です。残念ながらServiceWorkerには対応していないので、それに対応してくれたらもっとアレなんですが。

# iOS Safari9の新機能（OSX版含む）

## CSS系

### backdropフィルタ対応

新し目のiOSやOSXとかのメニューバーが半透過されるあれが作れます。要は背景要素に対してフィルタがかけられるプロパティです。綺麗で良いですね。

![](https://qiita-image-store.s3.amazonaws.com/0/2152/c98ece1a-4fd5-661e-99f1-a5cb0481611e.png "backdrop.png")

```css
body {
  background-image: url(./bg.jpg);
  background-position: center center;
  background-repeat: no-repeat;
  background-attachment: fixed;
  background-size: cover;
}
div {
  padding: 60px;
  border: 1px solid #fff;
  color: #000;
  font-size: 32px;
  text-align: center;
  margin: 150px 100px;
  background-color: rgba(255, 255, 255, .6);
  
  -webkit-backdrop-filter: brightness(1.5) blur(10px);
}
```

blur() / brightness() / contrast() / drop-shadow() / grayscale() / hue-rotate() / invert() / opacity() / saturate() / sepia() などのフィルタがあります。たぶんよく使うのは、blurとbrightnessかな…？

### CSSだけでカルーセルバナー（scroll-snap）

カルーセルバナーというかスライドバナーというか、スワイプするとニュッとスライドして、ピタッと止まってくれるやつがJavaScriptを使わなくてもCSSだけで出来るようになりました。横スライドだけじゃなくて、縦スライドでも出来ます。

![](https://qiita-image-store.s3.amazonaws.com/0/2152/8210ffc4-c011-f839-c03b-030826fadfc2.gif "nLFcoFLAuW.gif")

```css
.snap {
  margin: 20px auto;
  width: 80%;
  overflow: auto;
  white-space: nowrap;
  -webkit-scroll-snap-points-x: repeat(100%);
  -webkit-scroll-snap-type: mandatory;
  -webkit-overflow-scrolling: touch;
}

.snap > div {
  width: 100%;
  height: 150px;
  display: inline-block;
  line-height: 150px;
  text-align: center;
  font-size: 50px;
}

.snap > div:nth-child(even) {
  background-color: #87EA87;
}

.snap > div:nth-child(odd) {
  background-color: #87CCEA;
}
```

```html
<div class="snap">
  <div>1</div>
  <div>2</div>
  <div>3</div>
</div>
```

### @supportsの対応

ブラウザがCSSの指定プロパティをサポートしているかどうかを判定する条件式です。メディアクエリのような感じですね。

```css
@supports ( display: flexbox ) {
	section {
		display: flexbox;
	}
}
```

OR条件や、NOT条件も指定可能です。

```css
@supports ( display: flexbox ) or ( display: -webkit-flexbox) {
	section {
		display: flexbox;
	}
}

@supports not ( display: flexbox ) {
	section {
		display: flexbox;
	}
}
```

CSSは基本対応していないプロパティがあっても無視してくれるので必要なさそうですが、複数のプロパティを組み合わせて使うような場合、レガシーなブラウザとモダンなブラウザへの対応コードが混在していると非常に読みにくくなります。そんな時のために、ブロックレベルで分岐できる`@supports`は便利ですね。

### CSS4セレクタ／擬似クラス

CSS4の強力なセレクタ、疑似クラスが実装されています。より簡易に書けるようになったり、ベンダープレフィックスが取れたりと、そこまで劇的に進化しているわけではないですね。

#### :any-link

ハイパーリンクの:linkと:visitedに対応。

```css
:any-link {
	color: #f00;
}
/* 同じ効果 */
a:link, a:visited {
	color: #f00;
}
```

#### 属性セレクタ（大文字小文字判定）

CSS2の属性セレクタですが、大文字小文字は無視していました。それが`i`を付けることで判定するようになっています。

```css
a[href$="pdf" i] {
    color: #000;
}
```

```html
<a href="hoge.pdf">hoge</a> <!-- hit -->
<a href="hoge.PDF">hoge</a>
<a href="hoge.Pdf">hoge</a>
```

#### :lang

日本語や英語など言語によって要素を適用できます。多言語化環境でかつ微妙に調整したい時などに使う感じですね。

```css
:lang(en) {
  color: #00f;
}
```

```html
<body lang=en>
	<p>hoge</p>
</body>
```

#### :matches

Firefoxが先行して実装した`-moz-any`や、WebKitでの`-webkit-any`のベンダープレフィックスが取れた標準版。すでに`-webkit-any`でサポート済みなのでプレフィックスが取れただけ。

```css
table tr :matches(th, td) {
  color: #f0f;
}
/* 同じ効果 */
table tr :-webkit-any(th, td) {
  color: #f0f;
}
/* 同じ効果 */
table tr td,
table tr th {
  color: #f00;
}
```

#### :placeholder-shown

こちらも同様に先行している::-webkit-input-placeholder / ::-moz-placeholder / :-ms-input-placeholderのベンダープレフィックスが取れた標準版。

```css
:placeholder-shown {
  padding-left: 3em;
  opacity: 1;
}
/* 同じ効果 */
::-webkit-input-placeholder {
  padding-left: 3em;
  opacity: 1;
}
```

#### :not

CSS3の:not(s)が複数指定できるようになりました。

```css
a:not([href*="exmaple.com"], [href*="hoge.com"]) {
  color: #0f0;
}
```

#### :nth-child

これだけCSS3の:nth-childから何が変わったのかが分からず…。

### initial-letter対応

テキストの最初の文字を大きくする英文でよく見るスタイルの大きさを行数で指定できるようになりました。日本ではあまり使われないかな…？

![](https://qiita-image-store.s3.amazonaws.com/0/2152/14b5283c-173e-cd84-4a32-e52ae6d5677d.png "initial-letter.png")

```css
p::first-letter{
  -webkit-initial-letter: 3;
}
```


### San Franciscoフォント対応

iOS9で追加された新システムフォントSan Franciscoの指定方法です。また、iOSで定義済みの文字サイズ／太さも指定できるようです。

```css
font-family: -apple-system, sans-serif;

font: -apple-system-body;
font: -apple-system-headline;
font: -apple-system-subheadline;
font: -apple-system-caption1;
font: -apple-system-caption2;
font: -apple-system-footnote;
font: -apple-system-short-body;
font: -apple-system-short-headline;
font: -apple-system-short-subheadline;
font: -apple-system-short-caption1;
font: -apple-system-short-footnote;
font: -apple-system-tall-body;
```

## JavaScript系

### Navigation Timing API

iOS8では存在していた（iOS8.1で削除）HTML5のTiming APIがiOS9では復活しています。これはブラウザが読み込んでから表示にかかるまでの時間を計測し、解析することが出来ます。各ブラウザの開発者ツールでも同様のことができますが、こちらは動作環境に依存せず、かつ複数のユーザを対象にデータを収集することが出来ます。Webアプリを作る上で、細かいパフォーマンスチューニングを行うにはかなり便利になると思います。

- 参考 : [Navigation Timingだからできる、Webアプリを俯瞰したパフォーマンス計測](https://html5experts.jp/furoshiki/6242/)
- 参考 : [User Timing API あなたの Web アプリをもっと理解するために](http://www.html5rocks.com/ja/tutorials/webperformance/usertiming/)



### 感圧タッチ（Force touch/3D touch）イベント

iPhone6sから搭載される感圧タッチセンサをJavaScriptで取得することが出来ます。

```js
var force = document.getElementById('force');
force.addEventListener("mousedown", function(event) {
    var forceLevel = event["webkitForce"];
    var clickForce = MouseEvent.WEBKIT_FORCE_AT_MOUSE_DOWN;
    var forceClickForce = MouseEvent.WEBKIT_FORCE_AT_FORCE_MOUSE_DOWN;
    
    if (forceLevel >= clickForce && forceLevel < forceClickForce) {
    	console.log("normal click");
    } else if (forceLevel >= forceClickForce) {
    	console.log("force click");
    }
});
```

現時点（2015/09/24）では、Xcode7のiOSシミュレータでも試すことは出来ないのでiPhone6s実機で試すしかないです。メニューにはForce Touch Presureっていうのがあるんですけどね…。

![](https://qiita-image-store.s3.amazonaws.com/0/2152/72d8c12d-a3f5-0a69-9647-d9f28a0f51ef.png "forcetouch.png")


### Picture in Picture

わりと最近のiPad限定ですが、画面の端っこにワイプのように動画を再生させておくことが出来るPicture in PictureがJavaScriptでも制御可能です。

```javascript
var video = document.getElementById('video');
var pipBtn = document.getElementById('pip');

if (video.webkitSupportsPresentationMode && typeof video.webkitSetPresentationMode === "function") {
    pipBtn.addEventListener("click", function(event) {
        video.webkitSetPresentationMode(video.webkitPresentationMode === "picture-in-picture" ? "inline" : "picture-in-picture");
    });
} else {
    pipBtn.disabled = true;
}
```

```html
<video width="300" height="200" id="video">
  <source src="sample.mp4" type="video/mp4" />
</video>
<button id="pip">pip</button>
```

他にもAirPlayの制御なども出来るようです。

### document.scrollingElement対応

Chromeはすでに対応済み。scrollTopのブラウザ間での違いを吸収するための標準化？

```javascript
console.log(document.scrollingElement.scrollTop);
```

### ECMAScript2015

ES2015使うならBabelだろうということで、そこまで気にはしていません。

- Classes
- Computed Properties
- Weak Set
- Number Object
- Octal and Binary Literals
- Symbol Objects
- Template Literals


## その他

### ファイルアップロードがiCloud / サードパーティ対応

iOS8までは、`<input type="file">`は、写真しか対応していませんでしたが、ようやくiCloudおよびサードパーティアプリに対応しました。僕が確認したところだとGoogleDriveやDropboxなどが対応しているようです。

![](https://qiita-image-store.s3.amazonaws.com/0/2152/faa5d62b-c2ef-a498-eed7-58f624928128.png "fileupload.png")


### HTTPSにHTTPなコンテンツが含まれている場合

HTTPSなURLの場合、URLの左隣に鍵アイコンが表示されますが、非HTTPSなコンテンツが含まれている場合は、そのアイコンが表示されません。アイコンが表示されないだけで、コンテンツは表示されます。

### 開発者向け

- レスポンシブデザインのシミュレータ
- Web Inspectorがリデザイン

ここらへんは、OS X El Capitanがリリースされてからですね。

# アプリと連携する新機能

2大新機能については、すでにmono0926さんが詳細に解説してくれているので、そちらを参考にしてください。

- Universal Links
	- 参考：[URLスキーム・独自ディープリンク実装に代わる、Universal Links(iOS 9で導入)でより良いUXを実現](http://qiita.com/mono0926/items/2bf651246714f20df626)
- App Search API
	- 参考：[iOS 9の「Search API Best Practices and FAQs」が公開されたので読み解いてみた](http://qiita.com/mono0926/items/27af791065ed919255e0)

## CloudKit JS

CloudKitは、iOSやOSXのアプリで利用できるBaaSです。今まではアプリからのみの利用でしたが、今回からはJavaScriptを用いてWebアプリからも利用が可能になりました。

- [CloudKit JS Reference](https://developer.apple.com/library/prerelease/mac/documentation/CloudKitJS/Reference/CloudKitJavaScriptReference/index.html)

これを使えば、アプリで作業していたものを、ブラウザ上で引き続き作業できるという感じになります。ただ、どれだけのアプリがこの恩恵をうけるかは…ちょっと分からない。